internal: use config to create attestation validators (#1561)

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2023-04-06 17:00:56 +02:00 committed by GitHub
parent 2b962598bf
commit ec01c57661
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 649 additions and 274 deletions

View File

@ -15,7 +15,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/atls"
"github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/choose"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
@ -26,7 +25,7 @@ import (
type Validator struct { type Validator struct {
attestationVariant variant.Variant attestationVariant variant.Variant
pcrs measurements.M pcrs measurements.M
idKeyConfig idkeydigest.Config idKeyConfig config.SNPFirmwareSignerConfig
validator atls.Validator validator atls.Validator
log debugLog log debugLog
} }
@ -45,10 +44,10 @@ func NewValidator(conf *config.Config, maaURL string, log debugLog) (*Validator,
} }
if v.attestationVariant.Equal(variant.AzureSEVSNP{}) { if v.attestationVariant.Equal(variant.AzureSEVSNP{}) {
v.idKeyConfig = idkeydigest.Config{ v.idKeyConfig = config.SNPFirmwareSignerConfig{
IDKeyDigests: conf.Provider.Azure.IDKeyDigest, AcceptedKeyDigests: conf.Provider.Azure.IDKeyDigest,
EnforcementPolicy: conf.IDKeyDigestPolicy(), EnforcementPolicy: conf.IDKeyDigestPolicy(),
MAAURL: maaURL, MAAURL: maaURL,
} }
} }

View File

@ -120,8 +120,8 @@ func TestNewValidator(t *testing.T) {
Provider: config.ProviderConfig{ Provider: config.ProviderConfig{
Azure: &config.AzureConfig{ Azure: &config.AzureConfig{
Measurements: testPCRs, Measurements: testPCRs,
IDKeyDigest: idkeydigest.IDKeyDigests{[]byte("414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141")}, IDKeyDigest: idkeydigest.List{[]byte("414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141")},
EnforceIDKeyDigest: idkeydigest.StrictChecking, EnforceIDKeyDigest: idkeydigest.Equal,
}, },
}, },
}, },
@ -174,26 +174,31 @@ func TestValidatorV(t *testing.T) {
"gcp": { "gcp": {
variant: variant.GCPSEVES{}, variant: variant.GCPSEVES{},
pcrs: newTestPCRs(), pcrs: newTestPCRs(),
wantVs: gcp.NewValidator(newTestPCRs(), nil), wantVs: gcp.NewValidator(config.GCPSEVES{Measurements: newTestPCRs()}, nil),
}, },
"azure cvm": { "azure cvm": {
variant: variant.AzureSEVSNP{}, variant: variant.AzureSEVSNP{},
pcrs: newTestPCRs(), pcrs: newTestPCRs(),
wantVs: snp.NewValidator( wantVs: snp.NewValidator(
newTestPCRs(), config.AzureSEVSNP{
idkeydigest.Config{IDKeyDigests: idkeydigest.IDKeyDigests{}, EnforcementPolicy: idkeydigest.WarnOnly}, Measurements: newTestPCRs(),
FirmwareSignerConfig: config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.List{},
EnforcementPolicy: idkeydigest.WarnOnly,
},
},
nil, nil,
), ),
}, },
"azure trusted launch": { "azure trusted launch": {
variant: variant.AzureTrustedLaunch{}, variant: variant.AzureTrustedLaunch{},
pcrs: newTestPCRs(), pcrs: newTestPCRs(),
wantVs: trustedlaunch.NewValidator(newTestPCRs(), nil), wantVs: trustedlaunch.NewValidator(config.AzureTrustedLaunch{Measurements: newTestPCRs()}, nil),
}, },
"qemu": { "qemu": {
variant: variant.QEMUVTPM{}, variant: variant.QEMUVTPM{},
pcrs: newTestPCRs(), pcrs: newTestPCRs(),
wantVs: qemu.NewValidator(newTestPCRs(), nil), wantVs: qemu.NewValidator(config.QEMUVTPM{Measurements: newTestPCRs()}, nil),
}, },
} }

View File

@ -105,7 +105,7 @@ func (c *createCmd) create(cmd *cobra.Command, creator cloudCreator, fileHandler
if attestVariant.Equal(variant.AzureTrustedLaunch{}) { if attestVariant.Equal(variant.AzureTrustedLaunch{}) {
cmd.PrintErrln("Disabling Confidential VMs is insecure. Use only for evaluation purposes.") cmd.PrintErrln("Disabling Confidential VMs is insecure. Use only for evaluation purposes.")
printedAWarning = true printedAWarning = true
if conf.IDKeyDigestPolicy() == idkeydigest.StrictChecking || conf.IDKeyDigestPolicy() == idkeydigest.MAAFallback { if conf.IDKeyDigestPolicy() == idkeydigest.Equal || conf.IDKeyDigestPolicy() == idkeydigest.MAAFallback {
cmd.PrintErrln("Your config asks for validating the idkeydigest. This is only available on Confidential VMs. It will not be enforced.") cmd.PrintErrln("Your config asks for validating the idkeydigest. This is only available on Confidential VMs. It will not be enforced.")
} }
} }

View File

@ -13,7 +13,7 @@
"idKeyConfig": { "idKeyConfig": {
"description": "Configuration for validating the ID Key Digest of the SEV-SNP attestation.", "description": "Configuration for validating the ID Key Digest of the SEV-SNP attestation.",
"type": "string", "type": "string",
"examples": ["{'EnforcementPolicy': 'MAAFallback', 'MAAURL': 'https://192.0.2.1:8080/maa', 'IDKeyDigests': ['57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696', '0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3'}"] "examples": ["{'enforcementPolicy': 'MAAFallback', 'maaURL': 'https://192.0.2.1:8080/maa', 'acceptedKeyDigests': ['57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696', '0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3'}"]
}, },
"image": { "image": {
"description": "Container image to use for the spawned pods.", "description": "Container image to use for the spawned pods.",

View File

@ -380,16 +380,16 @@ func setAttestationVariant(values map[string]any, variant string) error {
// TODO: v2.8: remove. This function is only temporarily needed as a migration from 2.6 to 2.7. // TODO: v2.8: remove. This function is only temporarily needed as a migration from 2.6 to 2.7.
// setIdkeyConfig sets the idkeyconfig value on the join-service value maps. // setIdkeyConfig sets the idkeyconfig value on the join-service value maps.
func setIdkeyConfig(values map[string]any, config *config.Config, maaURL string) error { func setIdkeyConfig(values map[string]any, cfg *config.Config, maaURL string) error {
joinServiceVals, ok := values["join-service"].(map[string]any) joinServiceVals, ok := values["join-service"].(map[string]any)
if !ok { if !ok {
return errors.New("invalid join-service values") return errors.New("invalid join-service values")
} }
idKeyCfg := idkeydigest.Config{ idKeyCfg := config.SNPFirmwareSignerConfig{
IDKeyDigests: config.IDKeyDigests(), AcceptedKeyDigests: cfg.IDKeyDigests(),
EnforcementPolicy: config.IDKeyDigestPolicy(), EnforcementPolicy: cfg.IDKeyDigestPolicy(),
MAAURL: maaURL, MAAURL: maaURL,
} }
marshalledCfg, err := json.Marshal(idKeyCfg) marshalledCfg, err := json.Marshal(idKeyCfg)
if err != nil { if err != nil {

View File

@ -17,7 +17,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/compatibility"
"github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/config"
@ -466,7 +465,7 @@ func (i *ChartLoader) loadConstellationServicesValues() (map[string]any, error)
// extendConstellationServicesValues extends the given values map by some values depending on user input. // extendConstellationServicesValues extends the given values map by some values depending on user input.
// Values set inside this function are only applied during init, not during upgrade. // Values set inside this function are only applied during init, not during upgrade.
func extendConstellationServicesValues( func extendConstellationServicesValues(
in map[string]any, config *config.Config, masterSecret, salt []byte, maaURL string, in map[string]any, cfg *config.Config, masterSecret, salt []byte, maaURL string,
) error { ) error {
keyServiceValues, ok := in["key-service"].(map[string]any) keyServiceValues, ok := in["key-service"].(map[string]any)
if !ok { if !ok {
@ -479,11 +478,11 @@ func extendConstellationServicesValues(
if !ok { if !ok {
return errors.New("invalid join-service values") return errors.New("invalid join-service values")
} }
joinServiceVals["attestationVariant"] = config.AttestationVariant joinServiceVals["attestationVariant"] = cfg.AttestationVariant
// measurements are updated separately during upgrade, // measurements are updated separately during upgrade,
// so we only set them in Helm during init. // so we only set them in Helm during init.
measurementsJSON, err := json.Marshal(config.GetMeasurements()) measurementsJSON, err := json.Marshal(cfg.GetMeasurements())
if err != nil { if err != nil {
return fmt.Errorf("marshalling measurements: %w", err) return fmt.Errorf("marshalling measurements: %w", err)
} }
@ -493,9 +492,9 @@ func extendConstellationServicesValues(
if !ok { if !ok {
return errors.New("invalid verification-service values") return errors.New("invalid verification-service values")
} }
verifyServiceVals["attestationVariant"] = config.AttestationVariant verifyServiceVals["attestationVariant"] = cfg.AttestationVariant
csp := config.GetProvider() csp := cfg.GetProvider()
switch csp { switch csp {
case cloudprovider.Azure: case cloudprovider.Azure:
joinServiceVals, ok := in["join-service"].(map[string]any) joinServiceVals, ok := in["join-service"].(map[string]any)
@ -503,10 +502,10 @@ func extendConstellationServicesValues(
return errors.New("invalid join-service values") return errors.New("invalid join-service values")
} }
idKeyCfg := idkeydigest.Config{ idKeyCfg := config.SNPFirmwareSignerConfig{
IDKeyDigests: config.IDKeyDigests(), AcceptedKeyDigests: cfg.IDKeyDigests(),
EnforcementPolicy: config.IDKeyDigestPolicy(), EnforcementPolicy: cfg.IDKeyDigestPolicy(),
MAAURL: maaURL, MAAURL: maaURL,
} }
marshalledCfg, err := json.Marshal(idKeyCfg) marshalledCfg, err := json.Marshal(idKeyCfg)
if err != nil { if err != nil {
@ -515,12 +514,12 @@ func extendConstellationServicesValues(
joinServiceVals["idKeyConfig"] = string(marshalledCfg) joinServiceVals["idKeyConfig"] = string(marshalledCfg)
in["azure"] = map[string]any{ in["azure"] = map[string]any{
"deployCSIDriver": config.DeployCSIDriver(), "deployCSIDriver": cfg.DeployCSIDriver(),
} }
case cloudprovider.GCP: case cloudprovider.GCP:
in["gcp"] = map[string]any{ in["gcp"] = map[string]any{
"deployCSIDriver": config.DeployCSIDriver(), "deployCSIDriver": cfg.DeployCSIDriver(),
} }
} }

View File

@ -74,7 +74,7 @@ func TestConstellationServices(t *testing.T) {
AttestationVariant: variant.AzureSEVSNP{}.String(), AttestationVariant: variant.AzureSEVSNP{}.String(),
Provider: config.ProviderConfig{Azure: &config.AzureConfig{ Provider: config.ProviderConfig{Azure: &config.AzureConfig{
DeployCSIDriver: toPtr(true), DeployCSIDriver: toPtr(true),
EnforceIDKeyDigest: idkeydigest.StrictChecking, EnforceIDKeyDigest: idkeydigest.Equal,
IDKeyDigest: [][]byte{ IDKeyDigest: [][]byte{
{0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad}, {0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad, 0xba, 0xaa, 0xaa, 0xad},
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa},

View File

@ -5,6 +5,6 @@ metadata:
namespace: testNamespace namespace: testNamespace
data: data:
measurements: "{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}" measurements: "{\"1\":{\"expected\":\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\"warnOnly\":false}}"
idKeyConfig: "{\"idKeyDigests\":[\"baaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaad\",\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"],\"enforcementPolicy\":\"StrictChecking\",\"maaURL\":\"https://192.0.2.1:8080/maa\"}" idKeyConfig: "{\"acceptedKeyDigests\":[\"baaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaadbaaaaaad\",\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"],\"enforcementPolicy\":\"Equal\",\"maaURL\":\"https://192.0.2.1:8080/maa\"}"
binaryData: binaryData:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View File

@ -11,8 +11,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/variant", "//internal/variant",
"@com_github_aws_aws_sdk_go_v2_config//:config", "@com_github_aws_aws_sdk_go_v2_config//:config",
"@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds",

View File

@ -15,8 +15,8 @@ import (
awsConfig "github.com/aws/aws-sdk-go-v2/config" awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2" "github.com/google/go-tpm/tpm2"
@ -30,10 +30,10 @@ type Validator struct {
} }
// NewValidator create a new Validator structure and returns it. // NewValidator create a new Validator structure and returns it.
func NewValidator(pcrs measurements.M, log vtpm.AttestationLogger) *Validator { func NewValidator(cfg config.AWSNitroTPM, log vtpm.AttestationLogger) *Validator {
v := &Validator{} v := &Validator{}
v.Validator = vtpm.NewValidator( v.Validator = vtpm.NewValidator(
pcrs, cfg.Measurements,
getTrustedKey, getTrustedKey,
v.tpmEnabled, v.tpmEnabled,
log, log,

View File

@ -15,9 +15,9 @@ go_library(
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/measurements",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/cloud/azure", "//internal/cloud/azure",
"//internal/config",
"//internal/crypto", "//internal/crypto",
"//internal/variant", "//internal/variant",
"@com_github_edgelesssys_go_azguestattestation//maa", "@com_github_edgelesssys_go_azguestattestation//maa",
@ -44,6 +44,7 @@ go_test(
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/simulator", "//internal/attestation/simulator",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/logger", "//internal/logger",
"@com_github_edgelesssys_go_azguestattestation//maa", "@com_github_edgelesssys_go_azguestattestation//maa",
"@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm//tpm2",

View File

@ -9,8 +9,6 @@ package snp
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
) )
type signatureError struct { type signatureError struct {
@ -51,7 +49,7 @@ func (e *vcekError) Error() string {
type idKeyError struct { type idKeyError struct {
encounteredValue []byte encounteredValue []byte
expectedValues idkeydigest.IDKeyDigests expectedValues [][]byte
} }
func (e *idKeyError) Unwrap() error { func (e *idKeyError) Unwrap() error {

View File

@ -21,23 +21,14 @@ import (
"math/big" "math/big"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
internalCrypto "github.com/edgelesssys/constellation/v2/internal/crypto" internalCrypto "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2" "github.com/google/go-tpm/tpm2"
) )
const (
// AMD root key. Received from the AMD Key Distribution System API (KDS).
arkPEM = "-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n"
bootloaderVersion = 2
teeVersion = 0
snpVersion = 6
microcodeVersion = 93
)
// Validator for Azure confidential VM attestation. // Validator for Azure confidential VM attestation.
type Validator struct { type Validator struct {
variant.AzureSEVSNP variant.AzureSEVSNP
@ -45,28 +36,24 @@ type Validator struct {
hclValidator hclAkValidator hclValidator hclAkValidator
maa maaValidator maa maaValidator
idKeyDigests idkeydigest.IDKeyDigests config config.AzureSEVSNP
enforceIDKeyDigest idkeydigest.EnforceIDKeyDigest
maaURL string
log vtpm.AttestationLogger log vtpm.AttestationLogger
} }
// NewValidator initializes a new Azure validator with the provided PCR values. // NewValidator initializes a new Azure validator with the provided PCR values.
func NewValidator(pcrs measurements.M, idKeyConf idkeydigest.Config, log vtpm.AttestationLogger) *Validator { func NewValidator(cfg config.AzureSEVSNP, log vtpm.AttestationLogger) *Validator {
if log == nil { if log == nil {
log = nopAttestationLogger{} log = nopAttestationLogger{}
} }
v := &Validator{ v := &Validator{
hclValidator: &azureInstanceInfo{}, hclValidator: &azureInstanceInfo{},
maa: newMAAClient(), maa: newMAAClient(),
idKeyDigests: idKeyConf.IDKeyDigests, config: cfg,
enforceIDKeyDigest: idKeyConf.EnforcementPolicy, log: log,
maaURL: idKeyConf.MAAURL,
log: log,
} }
v.Validator = vtpm.NewValidator( v.Validator = vtpm.NewValidator(
pcrs, cfg.Measurements,
v.getTrustedKey, v.getTrustedKey,
validateCVM, validateCVM,
log, log,
@ -107,7 +94,7 @@ func (v *Validator) getTrustedKey(ctx context.Context, attDoc vtpm.AttestationDo
return nil, fmt.Errorf("parsing attestation report: %w", err) return nil, fmt.Errorf("parsing attestation report: %w", err)
} }
vcek, err := validateVCEK(instanceInfo.Vcek, instanceInfo.CertChain) vcek, err := v.validateVCEK(instanceInfo.Vcek, instanceInfo.CertChain)
if err != nil { if err != nil {
return nil, fmt.Errorf("validating VCEK: %w", err) return nil, fmt.Errorf("validating VCEK: %w", err)
} }
@ -130,24 +117,19 @@ func (v *Validator) getTrustedKey(ctx context.Context, attDoc vtpm.AttestationDo
// validateVCEK takes the PEM-encoded X509 certificate VCEK, ASK and ARK and verifies the integrity of the chain. // validateVCEK takes the PEM-encoded X509 certificate VCEK, ASK and ARK and verifies the integrity of the chain.
// ARK (hardcoded) validates ASK (cloud metadata API) validates VCEK (cloud metadata API). // ARK (hardcoded) validates ASK (cloud metadata API) validates VCEK (cloud metadata API).
func validateVCEK(vcekRaw []byte, certChain []byte) (*x509.Certificate, error) { func (v *Validator) validateVCEK(vcekRaw []byte, certChain []byte) (*x509.Certificate, error) {
vcek, err := internalCrypto.PemToX509Cert(vcekRaw) vcek, err := internalCrypto.PemToX509Cert(vcekRaw)
if err != nil { if err != nil {
return nil, fmt.Errorf("loading vcek: %w", err) return nil, fmt.Errorf("loading vcek: %w", err)
} }
ark, err := internalCrypto.PemToX509Cert([]byte(arkPEM))
if err != nil {
return nil, fmt.Errorf("loading arkPEM: %w", err)
}
// certChain includes two PEM encoded certs. The ASK and the ARK, in that order. // certChain includes two PEM encoded certs. The ASK and the ARK, in that order.
ask, err := internalCrypto.PemToX509Cert(certChain) ask, err := internalCrypto.PemToX509Cert(certChain)
if err != nil { if err != nil {
return nil, fmt.Errorf("loading askPEM: %w", err) return nil, fmt.Errorf("loading askPEM: %w", err)
} }
if err = ask.CheckSignatureFrom(ark); err != nil { if err = ask.CheckSignatureFrom((*x509.Certificate)(&v.config.AMDRootKey)); err != nil {
return nil, &askError{err} return nil, &askError{err}
} }
@ -165,7 +147,7 @@ func (v *Validator) validateSNPReport(
return errDebugEnabled return errDebugEnabled
} }
if !report.CommittedTCB.isVersion(bootloaderVersion, teeVersion, snpVersion, microcodeVersion) { if !report.CommittedTCB.isVersion(v.config.BootloaderVersion, v.config.TEEVersion, v.config.SNPVersion, v.config.MicrocodeVersion) {
return &versionError{"COMMITTED_TCB", report.CommittedTCB} return &versionError{"COMMITTED_TCB", report.CommittedTCB}
} }
if report.LaunchTCB != report.CommittedTCB { if report.LaunchTCB != report.CommittedTCB {
@ -205,7 +187,7 @@ func (v *Validator) validateSNPReport(
} }
hasExpectedIDKeyDigest := false hasExpectedIDKeyDigest := false
for _, digest := range v.idKeyDigests { for _, digest := range v.config.FirmwareSignerConfig.AcceptedKeyDigests {
if bytes.Equal(digest, report.IDKeyDigest[:]) { if bytes.Equal(digest, report.IDKeyDigest[:]) {
hasExpectedIDKeyDigest = true hasExpectedIDKeyDigest = true
break break
@ -213,14 +195,22 @@ func (v *Validator) validateSNPReport(
} }
if !hasExpectedIDKeyDigest { if !hasExpectedIDKeyDigest {
switch v.enforceIDKeyDigest { switch v.config.FirmwareSignerConfig.EnforcementPolicy {
case idkeydigest.MAAFallback: case idkeydigest.MAAFallback:
v.log.Infof("configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation", v.idKeyDigests, report.IDKeyDigest[:]) v.log.Infof(
return v.maa.validateToken(ctx, v.maaURL, maaToken, extraData) "configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.IDKeyDigest[:],
)
return v.maa.validateToken(ctx, v.config.FirmwareSignerConfig.MAAURL, maaToken, extraData)
case idkeydigest.WarnOnly: case idkeydigest.WarnOnly:
v.log.Warnf("configured idkeydigests %x don't contain reported idkeydigest %x", v.idKeyDigests, report.IDKeyDigest[:]) v.log.Warnf(
"configured idkeydigests %x don't contain reported idkeydigest %x",
v.config.FirmwareSignerConfig.AcceptedKeyDigests,
report.IDKeyDigest[:],
)
default: default:
return &idKeyError{report.IDKeyDigest[:], v.idKeyDigests} return &idKeyError{report.IDKeyDigest[:], v.config.FirmwareSignerConfig.AcceptedKeyDigests}
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -11,8 +11,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/crypto", "//internal/crypto",
"//internal/variant", "//internal/variant",
"@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm//tpm2",
@ -34,6 +34,7 @@ go_test(
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/attestation/simulator", "//internal/attestation/simulator",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/crypto", "//internal/crypto",
"//internal/logger", "//internal/logger",
"@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm//tpm2",

View File

@ -21,6 +21,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/simulator" "github.com/edgelesssys/constellation/v2/internal/attestation/simulator"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/crypto" "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
tpmclient "github.com/google/go-tpm-tools/client" tpmclient "github.com/google/go-tpm-tools/client"
@ -200,7 +201,7 @@ func TestGetAttestationCert(t *testing.T) {
}, },
} }
validator := NewValidator(measurements.M{}, nil) validator := NewValidator(config.AzureTrustedLaunch{Measurements: measurements.M{}}, nil)
cert, err := x509.ParseCertificate(rootCert.Raw) cert, err := x509.ParseCertificate(rootCert.Raw)
require.NoError(err) require.NoError(err)
roots := x509.NewCertPool() roots := x509.NewCertPool()

View File

@ -15,8 +15,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
certutil "github.com/edgelesssys/constellation/v2/internal/crypto" certutil "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
@ -35,12 +35,12 @@ type Validator struct {
} }
// NewValidator initializes a new Azure validator with the provided PCR values. // NewValidator initializes a new Azure validator with the provided PCR values.
func NewValidator(pcrs measurements.M, log vtpm.AttestationLogger) *Validator { func NewValidator(cfg config.AzureTrustedLaunch, log vtpm.AttestationLogger) *Validator {
rootPool := x509.NewCertPool() rootPool := x509.NewCertPool()
rootPool.AddCert(ameRoot) rootPool.AddCert(ameRoot)
v := &Validator{roots: rootPool} v := &Validator{roots: rootPool}
v.Validator = vtpm.NewValidator( v.Validator = vtpm.NewValidator(
pcrs, cfg.Measurements,
v.verifyAttestationKey, v.verifyAttestationKey,
validateVM, validateVM,
log, log,

View File

@ -12,10 +12,10 @@ go_library(
"//internal/attestation/azure/snp", "//internal/attestation/azure/snp",
"//internal/attestation/azure/trustedlaunch", "//internal/attestation/azure/trustedlaunch",
"//internal/attestation/gcp", "//internal/attestation/gcp",
"//internal/attestation/idkeydigest",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/attestation/qemu", "//internal/attestation/qemu",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/variant", "//internal/variant",
], ],
) )
@ -25,7 +25,7 @@ go_test(
srcs = ["choose_test.go"], srcs = ["choose_test.go"],
embed = [":choose"], embed = [":choose"],
deps = [ deps = [
"//internal/attestation/idkeydigest", "//internal/config",
"//internal/variant", "//internal/variant",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",

View File

@ -14,10 +14,10 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp" "github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp"
"github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch" "github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch"
"github.com/edgelesssys/constellation/v2/internal/attestation/gcp" "github.com/edgelesssys/constellation/v2/internal/attestation/gcp"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/qemu" "github.com/edgelesssys/constellation/v2/internal/attestation/qemu"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
) )
@ -43,19 +43,22 @@ func Issuer(attestationVariant variant.Variant, log vtpm.AttestationLogger) (atl
// Validator returns the validator for the given variant. // Validator returns the validator for the given variant.
func Validator( func Validator(
attestationVariant variant.Variant, measurements measurements.M, idKeyCfg idkeydigest.Config, log vtpm.AttestationLogger, attestationVariant variant.Variant, measurements measurements.M, idKeyCfg config.SNPFirmwareSignerConfig, log vtpm.AttestationLogger,
) (atls.Validator, error) { ) (atls.Validator, error) {
switch attestationVariant { switch attestationVariant {
case variant.AWSNitroTPM{}: case variant.AWSNitroTPM{}:
return aws.NewValidator(measurements, log), nil return aws.NewValidator(config.AWSNitroTPM{Measurements: measurements}, log), nil
case variant.AzureTrustedLaunch{}: case variant.AzureTrustedLaunch{}:
return trustedlaunch.NewValidator(measurements, log), nil return trustedlaunch.NewValidator(config.AzureTrustedLaunch{Measurements: measurements}, log), nil
case variant.AzureSEVSNP{}: case variant.AzureSEVSNP{}:
return snp.NewValidator(measurements, idKeyCfg, log), nil cfg := config.DefaultForAzureSEVSNP()
cfg.Measurements = measurements
cfg.FirmwareSignerConfig = idKeyCfg
return snp.NewValidator(cfg, log), nil
case variant.GCPSEVES{}: case variant.GCPSEVES{}:
return gcp.NewValidator(measurements, log), nil return gcp.NewValidator(config.GCPSEVES{Measurements: measurements}, log), nil
case variant.QEMUVTPM{}: case variant.QEMUVTPM{}:
return qemu.NewValidator(measurements, log), nil return qemu.NewValidator(config.QEMUVTPM{Measurements: measurements}, log), nil
case variant.Dummy{}: case variant.Dummy{}:
return atls.NewFakeValidator(variant.Dummy{}), nil return atls.NewFakeValidator(variant.Dummy{}), nil
default: default:

View File

@ -10,7 +10,7 @@ import (
"encoding/asn1" "encoding/asn1"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -96,7 +96,7 @@ func TestValidator(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
require := require.New(t) require := require.New(t)
validator, err := Validator(tc.variant, nil, idkeydigest.Config{}, nil) validator, err := Validator(tc.variant, nil, config.SNPFirmwareSignerConfig{}, nil)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)

View File

@ -11,8 +11,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/gcp", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/gcp",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/variant", "//internal/variant",
"@com_github_google_go_tpm_tools//client", "@com_github_google_go_tpm_tools//client",
"@com_github_google_go_tpm_tools//proto/attest", "@com_github_google_go_tpm_tools//proto/attest",

View File

@ -16,8 +16,8 @@ import (
compute "cloud.google.com/go/compute/apiv1" compute "cloud.google.com/go/compute/apiv1"
"cloud.google.com/go/compute/apiv1/computepb" "cloud.google.com/go/compute/apiv1/computepb"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
"github.com/googleapis/gax-go/v2" "github.com/googleapis/gax-go/v2"
@ -35,12 +35,12 @@ type Validator struct {
} }
// NewValidator initializes a new GCP validator with the provided PCR values. // NewValidator initializes a new GCP validator with the provided PCR values.
func NewValidator(pcrs measurements.M, log vtpm.AttestationLogger) *Validator { func NewValidator(cfg config.GCPSEVES, log vtpm.AttestationLogger) *Validator {
v := &Validator{ v := &Validator{
restClient: newInstanceClient, restClient: newInstanceClient,
} }
v.Validator = vtpm.NewValidator( v.Validator = vtpm.NewValidator(
pcrs, cfg.Measurements,
v.trustedKeyFromGCEAPI, v.trustedKeyFromGCEAPI,
validateCVM, validateCVM,
log, log,

View File

@ -4,12 +4,11 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library( go_library(
name = "idkeydigest", name = "idkeydigest",
srcs = [ srcs = [
"enforceidkeydigest_string.go", "enforcement_string.go",
"idkeydigest.go", "idkeydigest.go",
], ],
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = ["//internal/cloud/cloudprovider"],
) )
go_test( go_test(

View File

@ -1,26 +0,0 @@
// Code generated by "stringer -type=EnforceIDKeyDigest"; DO NOT EDIT.
package idkeydigest
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Unknown-0]
_ = x[StrictChecking-1]
_ = x[MAAFallback-2]
_ = x[WarnOnly-3]
}
const _EnforceIDKeyDigest_name = "UnknownStrictCheckingMAAFallbackWarnOnly"
var _EnforceIDKeyDigest_index = [...]uint8{0, 7, 21, 32, 40}
func (i EnforceIDKeyDigest) String() string {
if i >= EnforceIDKeyDigest(len(_EnforceIDKeyDigest_index)-1) {
return "EnforceIDKeyDigest(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _EnforceIDKeyDigest_name[_EnforceIDKeyDigest_index[i]:_EnforceIDKeyDigest_index[i+1]]
}

View File

@ -0,0 +1,26 @@
// Code generated by "stringer -type=Enforcement"; DO NOT EDIT.
package idkeydigest
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Unknown-0]
_ = x[Equal-1]
_ = x[MAAFallback-2]
_ = x[WarnOnly-3]
}
const _Enforcement_name = "UnknownEqualMAAFallbackWarnOnly"
var _Enforcement_index = [...]uint8{0, 7, 12, 23, 31}
func (i Enforcement) String() string {
if i >= Enforcement(len(_Enforcement_index)-1) {
return "Enforcement(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Enforcement_name[_Enforcement_index[i]:_Enforcement_index[i+1]]
}

View File

@ -4,8 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only SPDX-License-Identifier: AGPL-3.0-only
*/ */
// Package idkeydigest contains policies and type definitions // Package idkeydigest provides type definitions for the `idkeydigest` value of SEV-SNP attestation.
// for checking the ID Key Digest value in SEV-SNP attestation.
package idkeydigest package idkeydigest
import ( import (
@ -14,59 +13,48 @@ import (
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
) )
// Config contains the configuration for ID Key Digest validation. //go:generate stringer -type=Enforcement
type Config struct {
IDKeyDigests IDKeyDigests `json:"idKeyDigests"`
EnforcementPolicy EnforceIDKeyDigest `json:"enforcementPolicy"`
MAAURL string `json:"maaURL,omitempty"`
}
//go:generate stringer -type=EnforceIDKeyDigest // Enforcement defines the behavior of the validator when the ID key digest is not found in the expected list.
type Enforcement uint32
// EnforceIDKeyDigest defines the behavior of the validator when the ID key digest is not found in the expected list.
type EnforceIDKeyDigest uint32
// TODO: Decide on final value naming.
const ( const (
// Unknown is reserved for invalid configurations. // Unknown is reserved for invalid configurations.
Unknown EnforceIDKeyDigest = iota Unknown Enforcement = iota
// StrictChecking will return an error if the ID key digest is not found in the expected list. // Equal will error if the reported signing key digest does not match any of the values in 'acceptedKeyDigests'.
StrictChecking Equal
// MAAFallback attempts to verify the attestation using Microsoft Azure Attestation (MAA), // MAAFallback uses 'equal' checking for validation, but fallback to using Microsoft Azure Attestation (MAA)
// if the ID key digest is not found in the expected list. // for validation if the reported digest does not match any of the values in 'acceptedKeyDigests'.
MAAFallback MAAFallback
// WarnOnly logs a warning if the ID key digest is not found in the expected list. // WarnOnly is the same as 'equal', but only prints a warning instead of returning an error if no match is found.
// No error is returned.
WarnOnly WarnOnly
) )
// UnmarshalJSON implements the json.Unmarshaler interface. // UnmarshalJSON implements the json.Unmarshaler interface.
func (e *EnforceIDKeyDigest) UnmarshalJSON(b []byte) error { func (e *Enforcement) UnmarshalJSON(b []byte) error {
return e.unmarshal(func(val any) error { return e.unmarshal(func(val any) error {
return json.Unmarshal(b, val) return json.Unmarshal(b, val)
}) })
} }
// MarshalJSON implements the json.Marshaler interface. // MarshalJSON implements the json.Marshaler interface.
func (e EnforceIDKeyDigest) MarshalJSON() ([]byte, error) { func (e Enforcement) MarshalJSON() ([]byte, error) {
return json.Marshal(e.String()) return json.Marshal(e.String())
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.
func (e *EnforceIDKeyDigest) UnmarshalYAML(unmarshal func(any) error) error { func (e *Enforcement) UnmarshalYAML(unmarshal func(any) error) error {
return e.unmarshal(unmarshal) return e.unmarshal(unmarshal)
} }
// MarshalYAML implements the yaml.Marshaler interface. // MarshalYAML implements the yaml.Marshaler interface.
func (e EnforceIDKeyDigest) MarshalYAML() (any, error) { func (e Enforcement) MarshalYAML() (any, error) {
return e.String(), nil return e.String(), nil
} }
func (e *EnforceIDKeyDigest) unmarshal(unmarshalFunc func(any) error) error { func (e *Enforcement) unmarshal(unmarshalFunc func(any) error) error {
// Check for legacy format: EnforceIDKeyDigest might be a boolean. // Check for legacy format: EnforceIDKeyDigest might be a boolean.
// If set to true, the value will be set to StrictChecking. // If set to true, the value will be set to StrictChecking.
// If set to false, the value will be set to WarnOnly. // If set to false, the value will be set to WarnOnly.
@ -74,7 +62,7 @@ func (e *EnforceIDKeyDigest) unmarshal(unmarshalFunc func(any) error) error {
legacyErr := unmarshalFunc(&legacyEnforce) legacyErr := unmarshalFunc(&legacyEnforce)
if legacyErr == nil { if legacyErr == nil {
if legacyEnforce { if legacyEnforce {
*e = StrictChecking *e = Equal
} else { } else {
*e = WarnOnly *e = WarnOnly
} }
@ -91,18 +79,18 @@ func (e *EnforceIDKeyDigest) unmarshal(unmarshalFunc func(any) error) error {
*e = EnforcePolicyFromString(enforce) *e = EnforcePolicyFromString(enforce)
if *e == Unknown { if *e == Unknown {
return fmt.Errorf("unknown EnforceIDKeyDigest value: %q", enforce) return fmt.Errorf("unknown Enforcement value: %q", enforce)
} }
return nil return nil
} }
// EnforcePolicyFromString returns EnforceIDKeyDigest from string. // EnforcePolicyFromString returns Enforcement from string.
func EnforcePolicyFromString(s string) EnforceIDKeyDigest { func EnforcePolicyFromString(s string) Enforcement {
s = strings.ToLower(s) s = strings.ToLower(s)
switch s { switch s {
case "strictchecking": case "equal":
return StrictChecking return Equal
case "maafallback": case "maafallback":
return MAAFallback return MAAFallback
case "warnonly": case "warnonly":
@ -112,37 +100,32 @@ func EnforcePolicyFromString(s string) EnforceIDKeyDigest {
} }
} }
// IDKeyDigests is a list of trusted digest values for the ID key. // List is a list of trusted digest values for the ID key.
type IDKeyDigests [][]byte type List [][]byte
type encodedIDKeyDigests []string type encodedList []string
// encodedDigestLength is the length of a digest in hex encoding. // encodedDigestLength is the length of a digest in hex encoding.
const encodedDigestLength = 2 * 48 const encodedDigestLength = 2 * 48
// NewIDKeyDigests creates a new IDKeyDigests from a list of digests. // NewList creates a new IDKeyDigests from a list of digests.
func NewIDKeyDigests(digests [][]byte) IDKeyDigests { func NewList(digests [][]byte) List {
idKeyDigests := make(IDKeyDigests, len(digests)) idKeyDigests := make(List, len(digests))
copy(idKeyDigests, digests) copy(idKeyDigests, digests)
return idKeyDigests return idKeyDigests
} }
// DefaultsFor returns the default IDKeyDigests for the given cloud provider. // DefaultList returns the default list of accepted ID key digests.
func DefaultsFor(csp cloudprovider.Provider) IDKeyDigests { func DefaultList() List {
switch csp { return List{
case cloudprovider.Azure: {0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96},
return IDKeyDigests{ {0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3},
{0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96}, {0x93, 0x4f, 0x68, 0xbd, 0x8b, 0xa0, 0x19, 0x38, 0xee, 0xc2, 0x14, 0x75, 0xc8, 0x72, 0xe3, 0xa9, 0x42, 0xb6, 0x0c, 0x59, 0xfa, 0xfc, 0x6d, 0xf9, 0xe9, 0xa7, 0x6e, 0xe6, 0x6b, 0xc4, 0x7f, 0x2d, 0x09, 0xc6, 0x76, 0xf6, 0x1c, 0x03, 0x15, 0xc5, 0x78, 0xda, 0x26, 0x08, 0x5f, 0xb1, 0x3a, 0x71},
{0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3},
{0x93, 0x4f, 0x68, 0xbd, 0x8b, 0xa0, 0x19, 0x38, 0xee, 0xc2, 0x14, 0x75, 0xc8, 0x72, 0xe3, 0xa9, 0x42, 0xb6, 0x0c, 0x59, 0xfa, 0xfc, 0x6d, 0xf9, 0xe9, 0xa7, 0x6e, 0xe6, 0x6b, 0xc4, 0x7f, 0x2d, 0x09, 0xc6, 0x76, 0xf6, 0x1c, 0x03, 0x15, 0xc5, 0x78, 0xda, 0x26, 0x08, 0x5f, 0xb1, 0x3a, 0x71},
}
default:
return nil
} }
} }
// MarshalYAML implements the yaml.Marshaler interface. // MarshalYAML implements the yaml.Marshaler interface.
func (d IDKeyDigests) MarshalYAML() (any, error) { func (d List) MarshalYAML() (any, error) {
encodedIDKeyDigests := []string{} encodedIDKeyDigests := []string{}
for _, digest := range d { for _, digest := range d {
encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest)) encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest))
@ -151,8 +134,8 @@ func (d IDKeyDigests) MarshalYAML() (any, error) {
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. // UnmarshalYAML implements the yaml.Unmarshaler interface.
func (d *IDKeyDigests) UnmarshalYAML(unmarshal func(any) error) error { func (d *List) UnmarshalYAML(unmarshal func(any) error) error {
var encodedDigests encodedIDKeyDigests var encodedDigests encodedList
if err := unmarshal(&encodedDigests); err != nil { if err := unmarshal(&encodedDigests); err != nil {
// Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct. // Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct.
var unmarshalledString string var unmarshalledString string
@ -171,7 +154,7 @@ func (d *IDKeyDigests) UnmarshalYAML(unmarshal func(any) error) error {
} }
// MarshalJSON implements the json.Marshaler interface. // MarshalJSON implements the json.Marshaler interface.
func (d IDKeyDigests) MarshalJSON() ([]byte, error) { func (d List) MarshalJSON() ([]byte, error) {
encodedIDKeyDigests := []string{} encodedIDKeyDigests := []string{}
for _, digest := range d { for _, digest := range d {
encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest)) encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest))
@ -180,8 +163,8 @@ func (d IDKeyDigests) MarshalJSON() ([]byte, error) {
} }
// UnmarshalJSON implements the json.Unmarshaler interface. // UnmarshalJSON implements the json.Unmarshaler interface.
func (d *IDKeyDigests) UnmarshalJSON(b []byte) error { func (d *List) UnmarshalJSON(b []byte) error {
var encodedDigests encodedIDKeyDigests var encodedDigests encodedList
if err := json.Unmarshal(b, &encodedDigests); err != nil { if err := json.Unmarshal(b, &encodedDigests); err != nil {
// Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct. // Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct.
var unmarshalledString string var unmarshalledString string
@ -200,7 +183,7 @@ func (d *IDKeyDigests) UnmarshalJSON(b []byte) error {
} }
// unmarshal is a helper function for unmarshalling encodedIDKeyDigests into IDKeyDigests. // unmarshal is a helper function for unmarshalling encodedIDKeyDigests into IDKeyDigests.
func (d *IDKeyDigests) unmarshal(encodedDigests encodedIDKeyDigests) error { func (d *List) unmarshal(encodedDigests encodedList) error {
for _, encodedDigest := range encodedDigests { for _, encodedDigest := range encodedDigests {
if len(encodedDigest) != encodedDigestLength { if len(encodedDigest) != encodedDigestLength {
return fmt.Errorf("invalid digest length: %d", len(encodedDigest)) return fmt.Errorf("invalid digest length: %d", len(encodedDigest))

View File

@ -17,12 +17,12 @@ import (
func TestMarshal(t *testing.T) { func TestMarshal(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
dgst IDKeyDigests dgst List
wantYAML string wantYAML string
wantJSON string wantJSON string
}{ }{
"digest": { "digest": {
dgst: IDKeyDigests{{0x01, 0x02, 0x03, 0x04}, {0xff, 0xff, 0xff, 0xff}}, dgst: List{{0x01, 0x02, 0x03, 0x04}, {0xff, 0xff, 0xff, 0xff}},
wantJSON: `["01020304","ffffffff"]`, wantJSON: `["01020304","ffffffff"]`,
wantYAML: ` wantYAML: `
- "01020304" - "01020304"
@ -58,7 +58,7 @@ func TestUnmarshal(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
yaml string yaml string
json string json string
wantDgst IDKeyDigests wantDgst List
wantErr bool wantErr bool
}{ }{
"digest struct": { "digest struct": {
@ -66,20 +66,15 @@ func TestUnmarshal(t *testing.T) {
yaml: ` yaml: `
- "57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696" - "57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696"
- "0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3"`, - "0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3"`,
wantDgst: IDKeyDigests{ wantDgst: List{
{0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96}, {0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96},
{0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3}, {0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3},
}, },
}, },
"legacy digest as string": {
json: `"57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696"`,
yaml: `"57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696"`,
wantDgst: IDKeyDigests{{0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96}},
},
"invalid length": { "invalid length": {
json: `"010203"`, json: `"010203"`,
yaml: `"010203"`, yaml: `"010203"`,
wantDgst: IDKeyDigests{{}}, wantDgst: List{{}},
wantErr: true, wantErr: true,
}, },
} }
@ -91,7 +86,7 @@ func TestUnmarshal(t *testing.T) {
{ {
// YAML // YAML
var dgst IDKeyDigests var dgst List
err := yaml.Unmarshal([]byte(tc.yaml), &dgst) err := yaml.Unmarshal([]byte(tc.yaml), &dgst)
if tc.wantErr { if tc.wantErr {
require.Error(err) require.Error(err)
@ -104,7 +99,7 @@ func TestUnmarshal(t *testing.T) {
{ {
// JSON // JSON
var dgst IDKeyDigests var dgst List
err := json.Unmarshal([]byte(tc.json), &dgst) err := json.Unmarshal([]byte(tc.json), &dgst)
if tc.wantErr { if tc.wantErr {
require.Error(err) require.Error(err)
@ -118,16 +113,16 @@ func TestUnmarshal(t *testing.T) {
} }
} }
func TestEnforceIDKeyDigestMarshal(t *testing.T) { func TestEnforcementMarshal(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
input EnforceIDKeyDigest input Enforcement
wantJSON string wantJSON string
wantYAML string wantYAML string
}{ }{
"strict": { "strict": {
input: StrictChecking, input: Equal,
wantJSON: `"StrictChecking"`, wantJSON: `"Equal"`,
wantYAML: "StrictChecking", wantYAML: "Equal",
}, },
"maaFallback": { "maaFallback": {
input: MAAFallback, input: MAAFallback,
@ -163,17 +158,17 @@ func TestEnforceIDKeyDigestMarshal(t *testing.T) {
} }
} }
func TestEnforceIDKeyDigestUnmarshal(t *testing.T) { func TestEnforcementUnmarshal(t *testing.T) {
testCases := map[string]struct { testCases := map[string]struct {
inputJSON string inputJSON string
inputYAML string inputYAML string
want EnforceIDKeyDigest want Enforcement
wantErr bool wantErr bool
}{ }{
"strict": { "strict": {
inputJSON: `"StrictChecking"`, inputJSON: `"Equal"`,
inputYAML: "StrictChecking", inputYAML: "Equal",
want: StrictChecking, want: Equal,
}, },
"maaFallback": { "maaFallback": {
inputJSON: `"MAAFallback"`, inputJSON: `"MAAFallback"`,
@ -185,16 +180,6 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
inputYAML: "WarnOnly", inputYAML: "WarnOnly",
want: WarnOnly, want: WarnOnly,
}, },
"legacyTrue": {
inputJSON: `true`,
inputYAML: "true",
want: StrictChecking,
},
"legacyFalse": {
inputJSON: `false`,
inputYAML: "false",
want: WarnOnly,
},
"invalid": { "invalid": {
inputJSON: `"invalid"`, inputJSON: `"invalid"`,
inputYAML: "invalid", inputYAML: "invalid",
@ -214,7 +199,7 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
{ {
// YAML // YAML
var got EnforceIDKeyDigest var got Enforcement
err := yaml.Unmarshal([]byte(tc.inputYAML), &got) err := yaml.Unmarshal([]byte(tc.inputYAML), &got)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)
@ -227,7 +212,7 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
{ {
// JSON // JSON
var got EnforceIDKeyDigest var got Enforcement
err := json.Unmarshal([]byte(tc.inputJSON), &got) err := json.Unmarshal([]byte(tc.inputJSON), &got)
if tc.wantErr { if tc.wantErr {
assert.Error(err) assert.Error(err)

View File

@ -10,8 +10,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/qemu", importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/qemu",
visibility = ["//:__subpackages__"], visibility = ["//:__subpackages__"],
deps = [ deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm", "//internal/attestation/vtpm",
"//internal/config",
"//internal/variant", "//internal/variant",
"@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm//tpm2",
"@com_github_google_go_tpm_tools//client", "@com_github_google_go_tpm_tools//client",

View File

@ -10,8 +10,8 @@ import (
"context" "context"
"crypto" "crypto"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2" "github.com/google/go-tpm/tpm2"
@ -24,10 +24,10 @@ type Validator struct {
} }
// NewValidator initializes a new QEMU validator with the provided PCR values. // NewValidator initializes a new QEMU validator with the provided PCR values.
func NewValidator(pcrs measurements.M, log vtpm.AttestationLogger) *Validator { func NewValidator(cfg config.QEMUVTPM, log vtpm.AttestationLogger) *Validator {
return &Validator{ return &Validator{
Validator: vtpm.NewValidator( Validator: vtpm.NewValidator(
pcrs, cfg.Measurements,
unconditionalTrust, unconditionalTrust,
func(vtpm.AttestationDocument, *attest.MachineState) error { return nil }, func(vtpm.AttestationDocument, *attest.MachineState) error { return nil },
log, log,

View File

@ -4,6 +4,7 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library( go_library(
name = "config", name = "config",
srcs = [ srcs = [
"attestation.go",
"config.go", "config.go",
"config_doc.go", "config_doc.go",
# keep # keep
@ -37,6 +38,7 @@ go_library(
go_test( go_test(
name = "config_test", name = "config_test",
srcs = [ srcs = [
"attestation_test.go",
"config_test.go", "config_test.go",
"validation_test.go", "validation_test.go",
], ],
@ -56,6 +58,7 @@ go_test(
"@com_github_spf13_afero//:afero", "@com_github_spf13_afero//:afero",
"@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require", "@com_github_stretchr_testify//require",
"@in_gopkg_yaml_v3//:yaml_v3",
"@org_uber_go_goleak//:goleak", "@org_uber_go_goleak//:goleak",
], ],
) )

View File

@ -0,0 +1,75 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package config
import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/variant"
)
// AttestationConfig is the common interface for passing attestation configs.
type AttestationConfig interface {
// GetMeasurements returns the measurements that should be used for attestation.
GetMeasurements() measurements.M
// GetVariant returns the variant of the attestation config.
GetVariant() variant.Variant
}
// Certificate is a wrapper around x509.Certificate allowing custom marshaling.
type Certificate x509.Certificate
// MarshalJSON marshals the certificate to PEM.
func (c Certificate) MarshalJSON() ([]byte, error) {
pem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.Raw})
return json.Marshal(string(pem))
}
// MarshalYAML marshals the certificate to PEM.
func (c Certificate) MarshalYAML() (any, error) {
pem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: c.Raw})
return string(pem), nil
}
// UnmarshalJSON unmarshals the certificate from PEM.
func (c *Certificate) UnmarshalJSON(data []byte) error {
return c.unmarshal(func(val any) error {
return json.Unmarshal(data, val)
})
}
// UnmarshalYAML unmarshals the certificate from PEM.
func (c *Certificate) UnmarshalYAML(unmarshal func(any) error) error {
return c.unmarshal(unmarshal)
}
func (c *Certificate) unmarshal(unmarshalFunc func(any) error) error {
var pemData string
if err := unmarshalFunc(&pemData); err != nil {
return err
}
block, _ := pem.Decode([]byte(pemData))
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return err
}
*c = Certificate(*cert)
return nil
}
func mustParsePEM(data string) Certificate {
jsonData := fmt.Sprintf("\"%s\"", data)
var cert Certificate
if err := json.Unmarshal([]byte(jsonData), &cert); err != nil {
panic(err)
}
return cert
}

View File

@ -0,0 +1,46 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package config
import (
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v3"
)
// testCertPEM is a certificate in PEM format used for unit tests.
var testCertPEM = `-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`
func TestCertificateMarshalJSON(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
jsonCert := fmt.Sprintf("\"%s\"", testCertPEM)
var cert Certificate
require.NoError(json.Unmarshal([]byte(jsonCert), &cert))
out, err := json.Marshal(cert)
require.NoError(err)
assert.JSONEq(jsonCert, string(out))
}
func TestCertificateMarshalYAML(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
yamlCert := fmt.Sprintf("\"%s\"", testCertPEM)
var cert Certificate
require.NoError(yaml.Unmarshal([]byte(yamlCert), &cert))
out, err := yaml.Marshal(cert)
require.NoError(err)
assert.YAMLEq(yamlCert, string(out))
}

View File

@ -37,6 +37,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/compatibility"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
) )
@ -46,7 +47,7 @@ type Measurements = measurements.M
// Digests is a required alias since docgen is not able to work with // Digests is a required alias since docgen is not able to work with
// types in other packages. // types in other packages.
type Digests = idkeydigest.IDKeyDigests type Digests = idkeydigest.List
const ( const (
// Version2 is the second version number for Constellation config file. // Version2 is the second version number for Constellation config file.
@ -175,7 +176,7 @@ type AzureConfig struct {
IDKeyDigest Digests `yaml:"idKeyDigest" validate:"required_if=EnforceIdKeyDigest true,omitempty"` IDKeyDigest Digests `yaml:"idKeyDigest" validate:"required_if=EnforceIdKeyDigest true,omitempty"`
// description: | // description: |
// Enforce the specified idKeyDigest value during remote attestation. // Enforce the specified idKeyDigest value during remote attestation.
EnforceIDKeyDigest idkeydigest.EnforceIDKeyDigest `yaml:"enforceIdKeyDigest" validate:"required"` EnforceIDKeyDigest idkeydigest.Enforcement `yaml:"enforceIdKeyDigest" validate:"required"`
// description: | // description: |
// Expected confidential VM measurements. // Expected confidential VM measurements.
Measurements Measurements `yaml:"measurements" validate:"required,no_placeholders"` Measurements Measurements `yaml:"measurements" validate:"required,no_placeholders"`
@ -314,7 +315,7 @@ func Default() *Config {
InstanceType: "Standard_DC4as_v5", InstanceType: "Standard_DC4as_v5",
StateDiskType: "Premium_LRS", StateDiskType: "Premium_LRS",
DeployCSIDriver: toPtr(true), DeployCSIDriver: toPtr(true),
IDKeyDigest: idkeydigest.DefaultsFor(cloudprovider.Azure), IDKeyDigest: idkeydigest.DefaultList(),
EnforceIDKeyDigest: idkeydigest.MAAFallback, EnforceIDKeyDigest: idkeydigest.MAAFallback,
SecureBoot: toPtr(false), SecureBoot: toPtr(false),
Measurements: measurements.DefaultsFor(cloudprovider.Azure), Measurements: measurements.DefaultsFor(cloudprovider.Azure),
@ -504,7 +505,7 @@ func (c *Config) GetMeasurements() measurements.M {
} }
// IDKeyDigestPolicy returns the IDKeyDigest checking policy for a cloud provider. // IDKeyDigestPolicy returns the IDKeyDigest checking policy for a cloud provider.
func (c *Config) IDKeyDigestPolicy() idkeydigest.EnforceIDKeyDigest { func (c *Config) IDKeyDigestPolicy() idkeydigest.Enforcement {
if c.Provider.Azure != nil { if c.Provider.Azure != nil {
return c.Provider.Azure.EnforceIDKeyDigest return c.Provider.Azure.EnforceIDKeyDigest
} }
@ -512,7 +513,7 @@ func (c *Config) IDKeyDigestPolicy() idkeydigest.EnforceIDKeyDigest {
} }
// IDKeyDigests returns the ID Key Digests for the configured cloud provider. // IDKeyDigests returns the ID Key Digests for the configured cloud provider.
func (c *Config) IDKeyDigests() idkeydigest.IDKeyDigests { func (c *Config) IDKeyDigests() idkeydigest.List {
if c.Provider.Azure != nil { if c.Provider.Azure != nil {
return c.Provider.Azure.IDKeyDigest return c.Provider.Azure.IDKeyDigest
} }
@ -651,6 +652,141 @@ func (c *Config) Validate(force bool) error {
return &ValidationError{validationErrMsgs: validationErrMsgs} return &ValidationError{validationErrMsgs: validationErrMsgs}
} }
// AWSNitroTPM is the configuration for AWS Nitro TPM attestation.
type AWSNitroTPM struct {
// description: |
// Expected TPM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements"`
}
// GetVariant returns aws-nitro-tpm as the variant.
func (AWSNitroTPM) GetVariant() variant.Variant {
return variant.AWSNitroTPM{}
}
// GetMeasurements returns the measurements used for attestation.
func (c AWSNitroTPM) GetMeasurements() measurements.M {
return c.Measurements
}
// AzureSEVSNP is the configuration for Azure SEV-SNP attestation.
type AzureSEVSNP struct {
// description: |
// Expected confidential VM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements"`
// description: |
// Lowest acceptable bootloader version.
BootloaderVersion uint8 `json:"bootloaderVersion" yaml:"bootloaderVersion"`
// description: |
// Lowest acceptable TEE version.
TEEVersion uint8 `json:"teeVersion" yaml:"teeVersion"`
// description: |
// Lowest acceptable SEV-SNP version.
SNPVersion uint8 `json:"snpVersion" yaml:"snpVersion"`
// description: |
// Lowest acceptable microcode version.
MicrocodeVersion uint8 `json:"microcodeVersion" yaml:"microcodeVersion"`
// description: |
// Configuration for validating the firmware signature.
FirmwareSignerConfig SNPFirmwareSignerConfig `json:"firmwareSignerConfig" yaml:"firmwareSignerConfig"`
// description: |
// AMD Root Key certificate used to verify the SEV-SNP certificate chain.
AMDRootKey Certificate `json:"amdRootKey" yaml:"amdRootKey"`
}
// DefaultForAzureSEVSNP returns the default configuration for Azure SEV-SNP attestation.
// Version numbers are hard coded and should be updated with each new release.
// TODO(AB#3042): replace with dynamic lookup for configurable values.
func DefaultForAzureSEVSNP() AzureSEVSNP {
return AzureSEVSNP{
Measurements: measurements.DefaultsFor(cloudprovider.Azure),
BootloaderVersion: 2,
TEEVersion: 0,
SNPVersion: 6,
MicrocodeVersion: 93,
FirmwareSignerConfig: SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.DefaultList(),
EnforcementPolicy: idkeydigest.MAAFallback,
},
// AMD root key. Received from the AMD Key Distribution System API (KDS).
AMDRootKey: mustParsePEM(`-----BEGIN CERTIFICATE-----\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\nAFZEAwoKCQ==\n-----END CERTIFICATE-----\n`),
}
}
// GetVariant returns azure-sev-snp as the variant.
func (AzureSEVSNP) GetVariant() variant.Variant {
return variant.AzureSEVSNP{}
}
// GetMeasurements returns the measurements used for attestation.
func (c AzureSEVSNP) GetMeasurements() measurements.M {
return c.Measurements
}
// SNPFirmwareSignerConfig is the configuration for validating the firmware signer.
type SNPFirmwareSignerConfig struct {
// description: |
// List of accepted values for the firmware signing key digest.\nValues are enforced according to the 'enforcementPolicy'\n - 'equal' : Error if the reported signing key digest does not match any of the values in 'acceptedKeyDigests'\n - 'maaFallback' : Use 'equal' checking for validation, but fallback to using Microsoft Azure Attestation (MAA) for validation if the reported digest does not match any of the values in 'acceptedKeyDigests'. See the Azure docs for more details: https://learn.microsoft.com/en-us/azure/attestation/overview#amd-sev-snp-attestation\n - 'warnOnly' : Same as 'equal', but only prints a warning instead of returning an error if no match is found
AcceptedKeyDigests idkeydigest.List `json:"acceptedKeyDigests" yaml:"acceptedKeyDigests"`
// description: |
// Key digest enforcement policy. One of {'equal', 'maaFallback', 'warnOnly'}
EnforcementPolicy idkeydigest.Enforcement `json:"enforcementPolicy" yaml:"enforcementPolicy" validate:"required"`
// description: |
// URL of the Microsoft Azure Attestation (MAA) instance to use for fallback validation. Only used if 'enforcementPolicy' is set to 'maaFallback'.
MAAURL string `json:"maaURL,omitempty" yaml:"maaURL,omitempty" validate:"len=0"`
}
// AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation.
type AzureTrustedLaunch struct {
// description: |
// Expected TPM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements"`
}
// GetVariant returns azure-trusted-launch as the variant.
func (AzureTrustedLaunch) GetVariant() variant.Variant {
return variant.AzureTrustedLaunch{}
}
// GetMeasurements returns the measurements used for attestation.
func (c AzureTrustedLaunch) GetMeasurements() measurements.M {
return c.Measurements
}
// GCPSEVES is the configuration for GCP SEV-ES attestation.
type GCPSEVES struct {
// description: |
// Expected TPM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements"`
}
// GetVariant returns gcp-sev-es as the variant.
func (GCPSEVES) GetVariant() variant.Variant {
return variant.GCPSEVES{}
}
// GetMeasurements returns the measurements used for attestation.
func (c GCPSEVES) GetMeasurements() measurements.M {
return c.Measurements
}
// QEMUVTPM is the configuration for QEMU vTPM attestation.
type QEMUVTPM struct {
// description: |
// Expected TPM measurements.
Measurements measurements.M `json:"measurements" yaml:"measurements"`
}
// GetVariant returns qemu-vtpm as the variant.
func (QEMUVTPM) GetVariant() variant.Variant {
return variant.QEMUVTPM{}
}
// GetMeasurements returns the measurements used for attestation.
func (c QEMUVTPM) GetMeasurements() measurements.M {
return c.Measurements
}
func toPtr[T any](v T) *T { func toPtr[T any](v T) *T {
return &v return &v
} }

View File

@ -11,13 +11,19 @@ import (
) )
var ( var (
ConfigDoc encoder.Doc ConfigDoc encoder.Doc
ProviderConfigDoc encoder.Doc ProviderConfigDoc encoder.Doc
AWSConfigDoc encoder.Doc AWSConfigDoc encoder.Doc
AzureConfigDoc encoder.Doc AzureConfigDoc encoder.Doc
GCPConfigDoc encoder.Doc GCPConfigDoc encoder.Doc
OpenStackConfigDoc encoder.Doc OpenStackConfigDoc encoder.Doc
QEMUConfigDoc encoder.Doc QEMUConfigDoc encoder.Doc
AWSNitroTPMDoc encoder.Doc
AzureSEVSNPDoc encoder.Doc
SNPFirmwareSignerConfigDoc encoder.Doc
AzureTrustedLaunchDoc encoder.Doc
GCPSEVESDoc encoder.Doc
QEMUVTPMDoc encoder.Doc
) )
func init() { func init() {
@ -229,7 +235,7 @@ func init() {
AzureConfigDoc.Fields[12].Description = "List of accepted values for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf" AzureConfigDoc.Fields[12].Description = "List of accepted values for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf"
AzureConfigDoc.Fields[12].Comments[encoder.LineComment] = "List of accepted values for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf" AzureConfigDoc.Fields[12].Comments[encoder.LineComment] = "List of accepted values for the field 'idkeydigest' in the AMD SEV-SNP attestation report. Only usable with ConfidentialVMs. See 4.6 and 7.3 in: https://www.amd.com/system/files/TechDocs/56860.pdf"
AzureConfigDoc.Fields[13].Name = "enforceIdKeyDigest" AzureConfigDoc.Fields[13].Name = "enforceIdKeyDigest"
AzureConfigDoc.Fields[13].Type = "EnforceIDKeyDigest" AzureConfigDoc.Fields[13].Type = "Enforcement"
AzureConfigDoc.Fields[13].Note = "" AzureConfigDoc.Fields[13].Note = ""
AzureConfigDoc.Fields[13].Description = "Enforce the specified idKeyDigest value during remote attestation." AzureConfigDoc.Fields[13].Description = "Enforce the specified idKeyDigest value during remote attestation."
AzureConfigDoc.Fields[13].Comments[encoder.LineComment] = "Enforce the specified idKeyDigest value during remote attestation." AzureConfigDoc.Fields[13].Comments[encoder.LineComment] = "Enforce the specified idKeyDigest value during remote attestation."
@ -426,6 +432,112 @@ func init() {
QEMUConfigDoc.Fields[8].Note = "" QEMUConfigDoc.Fields[8].Note = ""
QEMUConfigDoc.Fields[8].Description = "Measurement used to enable measured boot." QEMUConfigDoc.Fields[8].Description = "Measurement used to enable measured boot."
QEMUConfigDoc.Fields[8].Comments[encoder.LineComment] = "Measurement used to enable measured boot." QEMUConfigDoc.Fields[8].Comments[encoder.LineComment] = "Measurement used to enable measured boot."
AWSNitroTPMDoc.Type = "AWSNitroTPM"
AWSNitroTPMDoc.Comments[encoder.LineComment] = "AWSNitroTPM is the configuration for AWS Nitro TPM attestation."
AWSNitroTPMDoc.Description = "AWSNitroTPM is the configuration for AWS Nitro TPM attestation."
AWSNitroTPMDoc.Fields = make([]encoder.Doc, 1)
AWSNitroTPMDoc.Fields[0].Name = "measurements"
AWSNitroTPMDoc.Fields[0].Type = "M"
AWSNitroTPMDoc.Fields[0].Note = ""
AWSNitroTPMDoc.Fields[0].Description = "Expected TPM measurements."
AWSNitroTPMDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements."
AzureSEVSNPDoc.Type = "AzureSEVSNP"
AzureSEVSNPDoc.Comments[encoder.LineComment] = "AzureSEVSNP is the configuration for Azure SEV-SNP attestation."
AzureSEVSNPDoc.Description = "AzureSEVSNP is the configuration for Azure SEV-SNP attestation."
AzureSEVSNPDoc.Fields = make([]encoder.Doc, 7)
AzureSEVSNPDoc.Fields[0].Name = "measurements"
AzureSEVSNPDoc.Fields[0].Type = "M"
AzureSEVSNPDoc.Fields[0].Note = ""
AzureSEVSNPDoc.Fields[0].Description = "Expected confidential VM measurements."
AzureSEVSNPDoc.Fields[0].Comments[encoder.LineComment] = "Expected confidential VM measurements."
AzureSEVSNPDoc.Fields[1].Name = "bootloaderVersion"
AzureSEVSNPDoc.Fields[1].Type = "uint8"
AzureSEVSNPDoc.Fields[1].Note = ""
AzureSEVSNPDoc.Fields[1].Description = "Lowest acceptable bootloader version."
AzureSEVSNPDoc.Fields[1].Comments[encoder.LineComment] = "Lowest acceptable bootloader version."
AzureSEVSNPDoc.Fields[2].Name = "teeVersion"
AzureSEVSNPDoc.Fields[2].Type = "uint8"
AzureSEVSNPDoc.Fields[2].Note = ""
AzureSEVSNPDoc.Fields[2].Description = "Lowest acceptable TEE version."
AzureSEVSNPDoc.Fields[2].Comments[encoder.LineComment] = "Lowest acceptable TEE version."
AzureSEVSNPDoc.Fields[3].Name = "snpVersion"
AzureSEVSNPDoc.Fields[3].Type = "uint8"
AzureSEVSNPDoc.Fields[3].Note = ""
AzureSEVSNPDoc.Fields[3].Description = "Lowest acceptable SEV-SNP version."
AzureSEVSNPDoc.Fields[3].Comments[encoder.LineComment] = "Lowest acceptable SEV-SNP version."
AzureSEVSNPDoc.Fields[4].Name = "microcodeVersion"
AzureSEVSNPDoc.Fields[4].Type = "uint8"
AzureSEVSNPDoc.Fields[4].Note = ""
AzureSEVSNPDoc.Fields[4].Description = "Lowest acceptable microcode version."
AzureSEVSNPDoc.Fields[4].Comments[encoder.LineComment] = "Lowest acceptable microcode version."
AzureSEVSNPDoc.Fields[5].Name = "firmwareSignerConfig"
AzureSEVSNPDoc.Fields[5].Type = "SNPFirmwareSignerConfig"
AzureSEVSNPDoc.Fields[5].Note = ""
AzureSEVSNPDoc.Fields[5].Description = "Configuration for validating the firmware signature."
AzureSEVSNPDoc.Fields[5].Comments[encoder.LineComment] = "Configuration for validating the firmware signature."
AzureSEVSNPDoc.Fields[6].Name = "amdRootKey"
AzureSEVSNPDoc.Fields[6].Type = "Certificate"
AzureSEVSNPDoc.Fields[6].Note = ""
AzureSEVSNPDoc.Fields[6].Description = "AMD Root Key certificate used to verify the SEV-SNP certificate chain."
AzureSEVSNPDoc.Fields[6].Comments[encoder.LineComment] = "AMD Root Key certificate used to verify the SEV-SNP certificate chain."
SNPFirmwareSignerConfigDoc.Type = "SNPFirmwareSignerConfig"
SNPFirmwareSignerConfigDoc.Comments[encoder.LineComment] = "SNPFirmwareSignerConfig is the configuration for validating the firmware signer."
SNPFirmwareSignerConfigDoc.Description = "SNPFirmwareSignerConfig is the configuration for validating the firmware signer."
SNPFirmwareSignerConfigDoc.AppearsIn = []encoder.Appearance{
{
TypeName: "AzureSEVSNP",
FieldName: "firmwareSignerConfig",
},
}
SNPFirmwareSignerConfigDoc.Fields = make([]encoder.Doc, 3)
SNPFirmwareSignerConfigDoc.Fields[0].Name = "acceptedKeyDigests"
SNPFirmwareSignerConfigDoc.Fields[0].Type = "List"
SNPFirmwareSignerConfigDoc.Fields[0].Note = ""
SNPFirmwareSignerConfigDoc.Fields[0].Description = "List of accepted values for the firmware signing key digest.\nValues are enforced according to the 'enforcementPolicy'\n - 'equal' : Error if the reported signing key digest does not match any of the values in 'acceptedKeyDigests'\n - 'maaFallback' : Use 'equal' checking for validation, but fallback to using Microsoft Azure Attestation (MAA) for validation if the reported digest does not match any of the values in 'acceptedKeyDigests'. See the Azure docs for more details: https://learn.microsoft.com/en-us/azure/attestation/overview#amd-sev-snp-attestation\n - 'warnOnly' : Same as 'equal', but only prints a warning instead of returning an error if no match is found"
SNPFirmwareSignerConfigDoc.Fields[0].Comments[encoder.LineComment] = "List of accepted values for the firmware signing key digest.\nValues are enforced according to the 'enforcementPolicy'\n - 'equal' : Error if the reported signing key digest does not match any of the values in 'acceptedKeyDigests'\n - 'maaFallback' : Use 'equal' checking for validation, but fallback to using Microsoft Azure Attestation (MAA) for validation if the reported digest does not match any of the values in 'acceptedKeyDigests'. See the Azure docs for more details: https://learn.microsoft.com/en-us/azure/attestation/overview#amd-sev-snp-attestation\n - 'warnOnly' : Same as 'equal', but only prints a warning instead of returning an error if no match is found"
SNPFirmwareSignerConfigDoc.Fields[1].Name = "enforcementPolicy"
SNPFirmwareSignerConfigDoc.Fields[1].Type = "Enforcement"
SNPFirmwareSignerConfigDoc.Fields[1].Note = ""
SNPFirmwareSignerConfigDoc.Fields[1].Description = "Key digest enforcement policy. One of {'equal', 'maaFallback', 'warnOnly'}"
SNPFirmwareSignerConfigDoc.Fields[1].Comments[encoder.LineComment] = "Key digest enforcement policy. One of {'equal', 'maaFallback', 'warnOnly'}"
SNPFirmwareSignerConfigDoc.Fields[2].Name = "maaURL"
SNPFirmwareSignerConfigDoc.Fields[2].Type = "string"
SNPFirmwareSignerConfigDoc.Fields[2].Note = ""
SNPFirmwareSignerConfigDoc.Fields[2].Description = "URL of the Microsoft Azure Attestation (MAA) instance to use for fallback validation. Only used if 'enforcementPolicy' is set to 'maaFallback'."
SNPFirmwareSignerConfigDoc.Fields[2].Comments[encoder.LineComment] = "URL of the Microsoft Azure Attestation (MAA) instance to use for fallback validation. Only used if 'enforcementPolicy' is set to 'maaFallback'."
AzureTrustedLaunchDoc.Type = "AzureTrustedLaunch"
AzureTrustedLaunchDoc.Comments[encoder.LineComment] = "AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation."
AzureTrustedLaunchDoc.Description = "AzureTrustedLaunch is the configuration for Azure Trusted Launch attestation."
AzureTrustedLaunchDoc.Fields = make([]encoder.Doc, 1)
AzureTrustedLaunchDoc.Fields[0].Name = "measurements"
AzureTrustedLaunchDoc.Fields[0].Type = "M"
AzureTrustedLaunchDoc.Fields[0].Note = ""
AzureTrustedLaunchDoc.Fields[0].Description = "Expected TPM measurements."
AzureTrustedLaunchDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements."
GCPSEVESDoc.Type = "GCPSEVES"
GCPSEVESDoc.Comments[encoder.LineComment] = "GCPSEVES is the configuration for GCP SEV-ES attestation."
GCPSEVESDoc.Description = "GCPSEVES is the configuration for GCP SEV-ES attestation."
GCPSEVESDoc.Fields = make([]encoder.Doc, 1)
GCPSEVESDoc.Fields[0].Name = "measurements"
GCPSEVESDoc.Fields[0].Type = "M"
GCPSEVESDoc.Fields[0].Note = ""
GCPSEVESDoc.Fields[0].Description = "Expected TPM measurements."
GCPSEVESDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements."
QEMUVTPMDoc.Type = "QEMUVTPM"
QEMUVTPMDoc.Comments[encoder.LineComment] = "QEMUVTPM is the configuration for QEMU vTPM attestation."
QEMUVTPMDoc.Description = "QEMUVTPM is the configuration for QEMU vTPM attestation."
QEMUVTPMDoc.Fields = make([]encoder.Doc, 1)
QEMUVTPMDoc.Fields[0].Name = "measurements"
QEMUVTPMDoc.Fields[0].Type = "M"
QEMUVTPMDoc.Fields[0].Note = ""
QEMUVTPMDoc.Fields[0].Description = "Expected TPM measurements."
QEMUVTPMDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements."
} }
func (_ Config) Doc() *encoder.Doc { func (_ Config) Doc() *encoder.Doc {
@ -456,6 +568,30 @@ func (_ QEMUConfig) Doc() *encoder.Doc {
return &QEMUConfigDoc return &QEMUConfigDoc
} }
func (_ AWSNitroTPM) Doc() *encoder.Doc {
return &AWSNitroTPMDoc
}
func (_ AzureSEVSNP) Doc() *encoder.Doc {
return &AzureSEVSNPDoc
}
func (_ SNPFirmwareSignerConfig) Doc() *encoder.Doc {
return &SNPFirmwareSignerConfigDoc
}
func (_ AzureTrustedLaunch) Doc() *encoder.Doc {
return &AzureTrustedLaunchDoc
}
func (_ GCPSEVES) Doc() *encoder.Doc {
return &GCPSEVESDoc
}
func (_ QEMUVTPM) Doc() *encoder.Doc {
return &QEMUVTPMDoc
}
// GetConfigurationDoc returns documentation for the file ./config_doc.go. // GetConfigurationDoc returns documentation for the file ./config_doc.go.
func GetConfigurationDoc() *encoder.FileDoc { func GetConfigurationDoc() *encoder.FileDoc {
return &encoder.FileDoc{ return &encoder.FileDoc{
@ -469,6 +605,12 @@ func GetConfigurationDoc() *encoder.FileDoc {
&GCPConfigDoc, &GCPConfigDoc,
&OpenStackConfigDoc, &OpenStackConfigDoc,
&QEMUConfigDoc, &QEMUConfigDoc,
&AWSNitroTPMDoc,
&AzureSEVSNPDoc,
&SNPFirmwareSignerConfigDoc,
&AzureTrustedLaunchDoc,
&GCPSEVESDoc,
&QEMUVTPMDoc,
}, },
} }
} }

View File

@ -739,7 +739,7 @@ func TestConfigVersionCompatibility(t *testing.T) {
StateDiskType: "Premium_LRS", StateDiskType: "Premium_LRS",
ConfidentialVM: toPtr(true), ConfidentialVM: toPtr(true),
InstanceType: "Standard_DC4as_v5", InstanceType: "Standard_DC4as_v5",
IDKeyDigest: idkeydigest.IDKeyDigests{{0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3}}, IDKeyDigest: idkeydigest.List{{0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3}},
EnforceIDKeyDigest: idkeydigest.WarnOnly, EnforceIDKeyDigest: idkeydigest.WarnOnly,
SecureBoot: toPtr(false), SecureBoot: toPtr(false),
DeployCSIDriver: toPtr(true), DeployCSIDriver: toPtr(true),
@ -768,7 +768,7 @@ func TestConfigVersionCompatibility(t *testing.T) {
StateDiskType: "Premium_LRS", StateDiskType: "Premium_LRS",
ConfidentialVM: toPtr(true), ConfidentialVM: toPtr(true),
InstanceType: "Standard_DC4as_v5", InstanceType: "Standard_DC4as_v5",
IDKeyDigest: idkeydigest.IDKeyDigests{ IDKeyDigest: idkeydigest.List{
{0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96}, {0x57, 0x48, 0x6a, 0x44, 0x7e, 0xc0, 0xf1, 0x95, 0x80, 0x02, 0xa2, 0x2a, 0x06, 0xb7, 0x67, 0x3b, 0x9f, 0xd2, 0x7d, 0x11, 0xe1, 0xc6, 0x52, 0x74, 0x98, 0x05, 0x60, 0x54, 0xc5, 0xfa, 0x92, 0xd2, 0x3c, 0x50, 0xf9, 0xde, 0x44, 0x07, 0x27, 0x60, 0xfe, 0x2b, 0x6f, 0xb8, 0x97, 0x40, 0xb6, 0x96},
{0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3}, {0x03, 0x56, 0x21, 0x58, 0x82, 0xa8, 0x25, 0x27, 0x9a, 0x85, 0xb3, 0x00, 0xb0, 0xb7, 0x42, 0x93, 0x1d, 0x11, 0x3b, 0xf7, 0xe3, 0x2d, 0xde, 0x2e, 0x50, 0xff, 0xde, 0x7e, 0xc7, 0x43, 0xca, 0x49, 0x1e, 0xcd, 0xd7, 0xf3, 0x36, 0xdc, 0x28, 0xa6, 0xe0, 0xb2, 0xbb, 0x57, 0xaf, 0x7a, 0x44, 0xa3},
}, },

View File

@ -14,6 +14,7 @@ go_library(
"//internal/attestation/choose", "//internal/attestation/choose",
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/config",
"//internal/constants", "//internal/constants",
"//internal/file", "//internal/file",
"//internal/logger", "//internal/logger",
@ -35,7 +36,7 @@ go_test(
"//internal/atls", "//internal/atls",
"//internal/attestation/idkeydigest", "//internal/attestation/idkeydigest",
"//internal/attestation/measurements", "//internal/attestation/measurements",
"//internal/cloud/cloudprovider", "//internal/config",
"//internal/constants", "//internal/constants",
"//internal/file", "//internal/file",
"//internal/logger", "//internal/logger",

View File

@ -19,6 +19,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/choose"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
@ -77,7 +78,7 @@ func (u *Updatable) Update() error {
u.log.Debugf("New measurements: %+v", measurements) u.log.Debugf("New measurements: %+v", measurements)
// Read ID Key config // Read ID Key config
var idKeyCfg idkeydigest.Config var idKeyCfg config.SNPFirmwareSignerConfig
if u.variant.Equal(variant.AzureSEVSNP{}) { if u.variant.Equal(variant.AzureSEVSNP{}) {
u.log.Infof("Updating SEV-SNP ID Key config") u.log.Infof("Updating SEV-SNP ID Key config")
@ -91,8 +92,8 @@ func (u *Updatable) Update() error {
// v2.6 fallback // v2.6 fallback
// TODO: Remove after v2.7 release // TODO: Remove after v2.7 release
var digest idkeydigest.IDKeyDigests var digest idkeydigest.List
var enforceIDKeyDigest idkeydigest.EnforceIDKeyDigest var enforceIDKeyDigest idkeydigest.Enforcement
enforceRaw, err := u.fileHandler.Read(filepath.Join(constants.ServiceBasePath, constants.EnforceIDKeyDigestFilename)) enforceRaw, err := u.fileHandler.Read(filepath.Join(constants.ServiceBasePath, constants.EnforceIDKeyDigestFilename))
if err != nil { if err != nil {
return err return err
@ -110,7 +111,7 @@ func (u *Updatable) Update() error {
return fmt.Errorf("unmarshaling content of IDKeyDigestFilename: %s: %w", idkeydigestRaw, err) return fmt.Errorf("unmarshaling content of IDKeyDigestFilename: %s: %w", idkeydigestRaw, err)
} }
idKeyCfg.IDKeyDigests = digest idKeyCfg.AcceptedKeyDigests = digest
idKeyCfg.EnforcementPolicy = enforceIDKeyDigest idKeyCfg.EnforcementPolicy = enforceIDKeyDigest
} }

View File

@ -20,7 +20,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/atls"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
@ -82,9 +82,9 @@ func TestNewUpdateableValidator(t *testing.T) {
require.NoError(handler.WriteJSON( require.NoError(handler.WriteJSON(
filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename), filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename),
idkeydigest.Config{ config.SNPFirmwareSignerConfig{
IDKeyDigests: idkeydigest.DefaultsFor(cloudprovider.Azure), AcceptedKeyDigests: idkeydigest.DefaultList(),
EnforcementPolicy: idkeydigest.WarnOnly, EnforcementPolicy: idkeydigest.WarnOnly,
}, },
)) ))
} }
@ -126,9 +126,9 @@ func TestUpdate(t *testing.T) {
)) ))
require.NoError(handler.WriteJSON( require.NoError(handler.WriteJSON(
filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename), filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename),
idkeydigest.Config{ config.SNPFirmwareSignerConfig{
IDKeyDigests: idkeydigest.IDKeyDigests{[]byte{0x00}}, AcceptedKeyDigests: idkeydigest.List{[]byte{0x00}},
EnforcementPolicy: idkeydigest.WarnOnly, EnforcementPolicy: idkeydigest.WarnOnly,
}, },
)) ))
@ -189,9 +189,9 @@ func TestOIDConcurrency(t *testing.T) {
)) ))
require.NoError(handler.WriteJSON( require.NoError(handler.WriteJSON(
filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename), filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename),
idkeydigest.Config{ config.SNPFirmwareSignerConfig{
IDKeyDigests: idkeydigest.IDKeyDigests{[]byte{0x00}}, AcceptedKeyDigests: idkeydigest.List{[]byte{0x00}},
EnforcementPolicy: idkeydigest.WarnOnly, EnforcementPolicy: idkeydigest.WarnOnly,
}, },
)) ))
@ -237,9 +237,9 @@ func TestUpdateConcurrency(t *testing.T) {
)) ))
require.NoError(handler.WriteJSON( require.NoError(handler.WriteJSON(
filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename), filepath.Join(constants.ServiceBasePath, constants.IDKeyConfigFilename),
idkeydigest.Config{ config.SNPFirmwareSignerConfig{
IDKeyDigests: idkeydigest.IDKeyDigests{[]byte{0x00}}, AcceptedKeyDigests: idkeydigest.List{[]byte{0x00}},
EnforcementPolicy: idkeydigest.WarnOnly, EnforcementPolicy: idkeydigest.WarnOnly,
}, },
)) ))