mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
COCOS-560 - EAT (#561)
* feat: Implement EAT (Evidence Attestation Token) generation and verification for attestation responses, replacing raw quotes with EAT tokens in the attestation service and protobuf. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * style: standardize comment formatting and fix a debug log format specifier. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix pkg test Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Introduce named constants for OEM IDs and use them in attestation claim extraction. Signed-off-by: SammyOina <sammyoina@gmail.com> * feat: Implement and test minimum length validation for EAT nonce in `NewEATClaims`. Signed-off-by: SammyOina <sammyoina@gmail.com> * feat: Add EATClaims.Sanitize method and integrate it into the validator to enforce claim dependencies. Signed-off-by: SammyOina <sammyoina@gmail.com> * feat: Add Signature field to SNPExtensions and TDXExtensions for enhanced claim validation Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Update dependencies and improve code structure in attestation package Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Introduce comprehensive test suites for EAT, ATLS, TDX, Azure SNP, and vTPM attestation, and improve EAT decoder robustness. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add encryption and admin keys, an encrypted algorithm file, and update go.mod to use go-jose/v4. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: add new encryption and KBS admin keys while improving TDX attestation test error handling. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Add new KBS admin and encryption keys, an encrypted linear regression algorithm, and refactor TDX test error message checks. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Implement Azure SNP attestation policy, update certificate verification, and add key management. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * refactor: replace hardcoded string literals with variables in Azure SNP attestation tests. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * feat: Refactor TDX EAT claims to use individual RTMR fields with `tdx_` prefixes and add an `IntUse` field. Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com> Signed-off-by: SammyOina <sammyoina@gmail.com>
This commit is contained in:
committed by
GitHub
parent
a3265bc346
commit
de50b6d2d4
+1
-2
@@ -138,7 +138,6 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
var provider attestation.Provider
|
||||
ccPlatform := attestation.CCPlatform()
|
||||
|
||||
azureConfig := azure.NewEnvConfigFromAgent(
|
||||
@@ -217,7 +216,7 @@ func main() {
|
||||
CertsURL: cfg.CAUrl,
|
||||
})
|
||||
}
|
||||
certProvider, err = atls.NewProvider(provider, ccPlatform, cfg.CertsToken, cfg.CVMId, certsSDK)
|
||||
certProvider, err = atls.NewProvider(attClient, ccPlatform, cfg.CertsToken, cfg.CVMId, certsSDK)
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to create certificate provider: %s", err))
|
||||
exitCode = 1
|
||||
|
||||
@@ -4,6 +4,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
@@ -16,6 +17,7 @@ import (
|
||||
attestationpb "github.com/ultravioletrs/cocos/internal/proto/attestation/v1"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/azure"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/eat"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/quoteprovider"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/tdx"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/vtpm"
|
||||
@@ -35,6 +37,8 @@ type config struct {
|
||||
AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"`
|
||||
AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"`
|
||||
AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"`
|
||||
EATFormat string `env:"ATTESTATION_EAT_FORMAT" envDefault:"CBOR"` // JWT or CBOR
|
||||
EATIssuer string `env:"ATTESTATION_EAT_ISSUER" envDefault:"cocos-attestation-service"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -121,10 +125,21 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// Generate EAT signing key
|
||||
signingKey, err := eat.GenerateSigningKey()
|
||||
if err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to generate EAT signing key: %s", err))
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
grpcServer := grpc.NewServer()
|
||||
svc := &service{
|
||||
provider: provider,
|
||||
logger: logger,
|
||||
provider: provider,
|
||||
logger: logger,
|
||||
signingKey: signingKey,
|
||||
eatFormat: cfg.EATFormat,
|
||||
eatIssuer: cfg.EATIssuer,
|
||||
}
|
||||
attestationpb.RegisterAttestationServiceServer(grpcServer, svc)
|
||||
|
||||
@@ -156,29 +171,37 @@ func main() {
|
||||
|
||||
type service struct {
|
||||
attestationpb.UnimplementedAttestationServiceServer
|
||||
provider attestation.Provider
|
||||
logger *slog.Logger
|
||||
provider attestation.Provider
|
||||
logger *slog.Logger
|
||||
signingKey *ecdsa.PrivateKey
|
||||
eatFormat string
|
||||
eatIssuer string
|
||||
}
|
||||
|
||||
func (s *service) FetchAttestation(ctx context.Context, req *attestationpb.AttestationRequest) (*attestationpb.AttestationResponse, error) {
|
||||
var quote []byte
|
||||
var binaryReport []byte
|
||||
var err error
|
||||
var platformType attestation.PlatformType
|
||||
|
||||
// Get binary attestation report based on platform type
|
||||
switch req.PlatformType {
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_SNP, attestationpb.PlatformType_PLATFORM_TYPE_TDX:
|
||||
var reportData [64]byte
|
||||
copy(reportData[:], req.ReportData)
|
||||
quote, err = s.provider.TeeAttestation(reportData[:])
|
||||
binaryReport, err = s.provider.TeeAttestation(reportData[:])
|
||||
platformType = convertPlatformType(req.PlatformType)
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_VTPM:
|
||||
var nonce [32]byte
|
||||
copy(nonce[:], req.Nonce)
|
||||
quote, err = s.provider.VTpmAttestation(nonce[:])
|
||||
binaryReport, err = s.provider.VTpmAttestation(nonce[:])
|
||||
platformType = attestation.VTPM
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_SNP_VTPM:
|
||||
var reportData [64]byte
|
||||
copy(reportData[:], req.ReportData)
|
||||
var nonce [32]byte
|
||||
copy(nonce[:], req.Nonce)
|
||||
quote, err = s.provider.Attestation(reportData[:], nonce[:])
|
||||
binaryReport, err = s.provider.Attestation(reportData[:], nonce[:])
|
||||
platformType = attestation.SNPvTPM
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported platform type")
|
||||
}
|
||||
@@ -187,7 +210,57 @@ func (s *service) FetchAttestation(ctx context.Context, req *attestationpb.Attes
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &attestationpb.AttestationResponse{Quote: quote}, nil
|
||||
// Create EAT claims from binary report
|
||||
nonce := req.ReportData
|
||||
if len(req.Nonce) > 0 {
|
||||
nonce = req.Nonce
|
||||
}
|
||||
|
||||
claims, err := eat.NewEATClaims(binaryReport, nonce, platformType)
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("failed to create EAT claims: %s", err))
|
||||
return nil, fmt.Errorf("failed to create EAT claims: %w", err)
|
||||
}
|
||||
|
||||
// Encode to EAT token based on configured format
|
||||
var eatToken []byte
|
||||
switch s.eatFormat {
|
||||
case "JWT":
|
||||
tokenString, err := eat.EncodeToJWT(claims, s.signingKey, s.eatIssuer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode JWT: %w", err)
|
||||
}
|
||||
eatToken = []byte(tokenString)
|
||||
case "CBOR":
|
||||
eatToken, err = eat.EncodeToCBOR(claims, s.signingKey, s.eatIssuer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode CBOR: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported EAT format: %s", s.eatFormat)
|
||||
}
|
||||
|
||||
s.logger.Debug(fmt.Sprintf("generated EAT token (%s format) for platform %v", s.eatFormat, platformType))
|
||||
|
||||
return &attestationpb.AttestationResponse{EatToken: eatToken}, nil
|
||||
}
|
||||
|
||||
// convertPlatformType converts protobuf platform type to internal platform type.
|
||||
func convertPlatformType(pt attestationpb.PlatformType) attestation.PlatformType {
|
||||
switch pt {
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_SNP:
|
||||
return attestation.SNP
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_TDX:
|
||||
return attestation.TDX
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_VTPM:
|
||||
return attestation.VTPM
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_SNP_VTPM:
|
||||
return attestation.SNPvTPM
|
||||
case attestationpb.PlatformType_PLATFORM_TYPE_AZURE:
|
||||
return attestation.Azure
|
||||
default:
|
||||
return attestation.NoCC
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) GetAzureToken(ctx context.Context, req *attestationpb.AzureTokenRequest) (*attestationpb.AzureTokenResponse, error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/ultravioletrs/cocos/pkg/atls"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation/azure"
|
||||
attestation_client "github.com/ultravioletrs/cocos/pkg/clients/grpc/attestation"
|
||||
"github.com/ultravioletrs/cocos/pkg/ingress"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -76,7 +77,6 @@ func run(cfg config) error {
|
||||
}
|
||||
|
||||
// Initialize Certificate Provider
|
||||
var provider attestation.Provider
|
||||
ccPlatform := attestation.CCPlatform()
|
||||
|
||||
azureConfig := azure.NewEnvConfigFromAgent(
|
||||
@@ -90,13 +90,20 @@ func run(cfg config) error {
|
||||
var certProvider atls.CertificateProvider
|
||||
|
||||
if ccPlatform != attestation.NoCC {
|
||||
// Create attestation client
|
||||
attClient, err := attestation_client.NewClient("/run/cocos/attestation.sock")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create attestation client: %w", err)
|
||||
}
|
||||
defer attClient.Close()
|
||||
|
||||
var certsSDK sdk.SDK
|
||||
if cfg.CAUrl != "" {
|
||||
certsSDK = sdk.NewSDK(sdk.Config{
|
||||
CertsURL: cfg.CAUrl,
|
||||
})
|
||||
}
|
||||
certProvider, err = atls.NewProvider(provider, ccPlatform, cfg.CertsToken, cfg.CVMId, certsSDK)
|
||||
certProvider, err = atls.NewProvider(attClient, ccPlatform, cfg.CertsToken, cfg.CVMId, certsSDK)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create certificate provider: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user