PRISM-821 - Fix attestation policy for azure cvms (#437)

* Refactor attestation handling: update logging messages, adjust command arguments, and enhance provider initialization with MaaURL support

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Add default PcrConfig to attestation policy generation

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Remove unused validateClaims function and its dependencies from snp.go

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Fix GenerateAttestationPolicy: update TCB composition handling and remove unused minimalTCB assignment

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Refactor vtpm provider initialization: remove unused MaaURL parameter and update related function calls

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: Sammy Oina <sammyoina@gmail.com>
This commit is contained in:
Sammy Kerata Oina
2025-05-22 18:33:10 +03:00
committed by GitHub
parent 94c169febb
commit 90807d9576
6 changed files with 28 additions and 63 deletions
+1 -1
View File
@@ -134,7 +134,7 @@ func (lm *loggingMiddleware) IMAMeasurements(ctx context.Context) (file []byte,
func (lm *loggingMiddleware) AttestationResult(ctx context.Context, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) (response []byte, err error) {
defer func(begin time.Time) {
message := fmt.Sprintf("Method Attestation took %s to complete", time.Since(begin))
message := fmt.Sprintf("Method AttestationResult took %s to complete", time.Since(begin))
if err != nil {
lm.logger.Warn(fmt.Sprintf("%s with error: %s", message, err))
return
+4 -5
View File
@@ -232,8 +232,8 @@ func (cli *CLI) NewAzureAttestationPolicy() *cobra.Command {
cmd := &cobra.Command{
Use: "azure",
Short: "Get attestation policy for Azure CVM",
Example: `azure <azure_maa_token_file> <token_nonce> <product_name>`,
Args: cobra.ExactArgs(3),
Example: `azure <azure_maa_token_file> <product_name>`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
token, err := os.ReadFile(args[0])
if err != nil {
@@ -241,10 +241,9 @@ func (cli *CLI) NewAzureAttestationPolicy() *cobra.Command {
return
}
nonce := []byte(args[1])
product := args[2]
product := args[1]
config, err := azure.GenerateAttestationPolicy(string(token), product, policy, nonce)
config, err := azure.GenerateAttestationPolicy(string(token), product, policy)
if err != nil {
printError(cmd, "Error generating attestation policy: %v ❌ ", err)
return
+8 -8
View File
@@ -43,15 +43,15 @@ const (
)
type config struct {
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
AgentGrpcHost string `env:"AGENT_GRPC_HOST" envDefault:"0.0.0.0"`
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
AgentGrpcHost string `env:"AGENT_GRPC_HOST" envDefault:"0.0.0.0"`
CAUrl string `env:"AGENT_CVM_CA_URL" envDefault:""`
CVMId string `env:"AGENT_CVM_ID" envDefault:""`
AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"`
AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"`
AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"`
AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"`
CVMId string `env:"AGENT_CVM_ID" envDefault:""`
AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"`
AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"`
AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"`
AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"`
}
func main() {
+1
View File
@@ -27,6 +27,7 @@ func InitializeDefaultMAAVars(config *EnvConfig) {
maa.OSBuild = config.OSBuild
maa.OSType = config.OSType
maa.OSDistro = config.OSDistro
MaaURL = config.MaaURL
}
func (c *EnvConfig) InitializeOSVars(build, osType, osDistro string) {
+13 -32
View File
@@ -5,7 +5,6 @@ package azure
import (
"context"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
@@ -117,7 +116,7 @@ func (a provider) VerifyAttestation(report []byte, teeNonce []byte, vTpmNonce []
}
func (a provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
quote, err := vtpm.FetchAzureAttestation(tokenNonce)
quote, err := FetchAzureAttestationToken(tokenNonce, MaaURL)
if err != nil {
return nil, errors.Wrap(vtpm.ErrFetchAzureToken, err)
}
@@ -125,16 +124,12 @@ func (a provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
return quote, nil
}
func GenerateAttestationPolicy(token string, product string, policy uint64, nonce []byte) (*attestation.Config, error) {
func GenerateAttestationPolicy(token, product string, policy uint64) (*attestation.Config, error) {
claims, err := validateToken(token)
if err != nil {
return nil, fmt.Errorf("failed to validate token: %w", err)
}
if err := validateClaims(claims, nonce); err != nil {
return nil, fmt.Errorf("failed to validate claims: %w", err)
}
tee, ok := claims["x-ms-isolation-tee"].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("failed to get tee from claims")
@@ -195,7 +190,8 @@ func GenerateAttestationPolicy(token string, product string, policy uint64, nonc
UcodeSpl: uint8(microcodeVersion),
}
minimalTCB, err := kds.ComposeTCBParts(minimalTCBParts)
// Minimum TCB at the moment is not valid and will be fixed in the future.
_, err = kds.ComposeTCBParts(minimalTCBParts)
if err != nil {
return nil, fmt.Errorf("failed to compose TCB parts: %w", err)
}
@@ -235,16 +231,24 @@ func GenerateAttestationPolicy(token string, product string, policy uint64, nonc
FamilyId: familyId,
Measurement: measurement,
MinimumGuestSvn: uint32(guestSVN),
MinimumTcb: uint64(minimalTCB),
TrustedIdKeyHashes: [][]byte{idKeyDigest},
ReportId: reportID,
Product: &sevsnp.SevProduct{Name: sevProduct},
Policy: policy,
},
},
PcrConfig: &attestation.PcrConfig{},
}, nil
}
func FetchAzureAttestationToken(tokenNonce []byte, maaURL string) ([]byte, error) {
token, err := maa.Attest(context.Background(), tokenNonce, maaURL, http.DefaultClient)
if err != nil {
return nil, fmt.Errorf("error fetching azure token: %w", err)
}
return []byte(token), nil
}
func validateToken(token string) (map[string]interface{}, error) {
unverifiedToken, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
if err != nil {
@@ -273,26 +277,3 @@ func validateToken(token string) (map[string]interface{}, error) {
return claims, nil
}
func validateClaims(claims map[string]interface{}, nonce []byte) error {
runtime, ok := claims["x-ms-runtime"].(map[string]interface{})
if !ok {
return fmt.Errorf("failed to get runtime from claims")
}
payload, ok := runtime["client-payload"].(map[string]interface{})
if !ok {
return fmt.Errorf("failed to get client payload from claims")
}
tokenNonce, ok := payload["nonce"].(string)
if !ok {
return fmt.Errorf("failed to get nonce from claims")
}
if tokenNonce != base64.StdEncoding.EncodeToString(nonce) {
return fmt.Errorf("nonce mismatch: expected %s, got %s", base64.StdEncoding.EncodeToString(nonce), tokenNonce)
}
return nil
}
+1 -17
View File
@@ -5,19 +5,16 @@ package vtpm
import (
"bytes"
"context"
"crypto"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"fmt"
"io"
"net/http"
"os"
"strconv"
"github.com/absmach/magistrala/pkg/errors"
"github.com/edgelesssys/go-azguestattestation/maa"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-tpm-tools/client"
@@ -147,12 +144,7 @@ func (v provider) VerifyAttestation(report []byte, teeNonce []byte, vTpmNonce []
}
func (v provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
quote, err := FetchAzureAttestation(tokenNonce)
if err != nil {
return nil, errors.Wrap(ErrFetchQuote, err)
}
return quote, nil
return nil, errors.New("Azure attestation token is not supported")
}
func Attest(teeNonce []byte, vTPMNonce []byte, teeAttestaion bool, vmpl uint) ([]byte, error) {
@@ -171,14 +163,6 @@ func Attest(teeNonce []byte, vTPMNonce []byte, teeAttestaion bool, vmpl uint) ([
return marshalQuote(attestation)
}
func FetchAzureAttestation(tokenNonce []byte) ([]byte, error) {
token, err := maa.Attest(context.Background(), tokenNonce, os.Getenv("AgentMaaURL"), http.DefaultClient)
if err != nil {
return nil, fmt.Errorf("error fetching azure token: %w", err)
}
return []byte(token), nil
}
func VTPMVerify(quote []byte, pubKeyTLS []byte, teeNonce []byte, vtpmNonce []byte, writer io.Writer) error {
if err := VerifyQuote(quote, pubKeyTLS, vtpmNonce, writer); err != nil {
return fmt.Errorf("failed to verify vTPM quote: %v", err)