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

View File

@ -120,8 +120,8 @@ func TestNewValidator(t *testing.T) {
Provider: config.ProviderConfig{
Azure: &config.AzureConfig{
Measurements: testPCRs,
IDKeyDigest: idkeydigest.IDKeyDigests{[]byte("414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141")},
EnforceIDKeyDigest: idkeydigest.StrictChecking,
IDKeyDigest: idkeydigest.List{[]byte("414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141")},
EnforceIDKeyDigest: idkeydigest.Equal,
},
},
},
@ -174,26 +174,31 @@ func TestValidatorV(t *testing.T) {
"gcp": {
variant: variant.GCPSEVES{},
pcrs: newTestPCRs(),
wantVs: gcp.NewValidator(newTestPCRs(), nil),
wantVs: gcp.NewValidator(config.GCPSEVES{Measurements: newTestPCRs()}, nil),
},
"azure cvm": {
variant: variant.AzureSEVSNP{},
pcrs: newTestPCRs(),
wantVs: snp.NewValidator(
newTestPCRs(),
idkeydigest.Config{IDKeyDigests: idkeydigest.IDKeyDigests{}, EnforcementPolicy: idkeydigest.WarnOnly},
config.AzureSEVSNP{
Measurements: newTestPCRs(),
FirmwareSignerConfig: config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: idkeydigest.List{},
EnforcementPolicy: idkeydigest.WarnOnly,
},
},
nil,
),
},
"azure trusted launch": {
variant: variant.AzureTrustedLaunch{},
pcrs: newTestPCRs(),
wantVs: trustedlaunch.NewValidator(newTestPCRs(), nil),
wantVs: trustedlaunch.NewValidator(config.AzureTrustedLaunch{Measurements: newTestPCRs()}, nil),
},
"qemu": {
variant: variant.QEMUVTPM{},
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{}) {
cmd.PrintErrln("Disabling Confidential VMs is insecure. Use only for evaluation purposes.")
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.")
}
}

View File

@ -13,7 +13,7 @@
"idKeyConfig": {
"description": "Configuration for validating the ID Key Digest of the SEV-SNP attestation.",
"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": {
"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.
// 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)
if !ok {
return errors.New("invalid join-service values")
}
idKeyCfg := idkeydigest.Config{
IDKeyDigests: config.IDKeyDigests(),
EnforcementPolicy: config.IDKeyDigestPolicy(),
MAAURL: maaURL,
idKeyCfg := config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: cfg.IDKeyDigests(),
EnforcementPolicy: cfg.IDKeyDigestPolicy(),
MAAURL: maaURL,
}
marshalledCfg, err := json.Marshal(idKeyCfg)
if err != nil {

View File

@ -17,7 +17,6 @@ import (
"path/filepath"
"strings"
"github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility"
"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.
// Values set inside this function are only applied during init, not during upgrade.
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 {
keyServiceValues, ok := in["key-service"].(map[string]any)
if !ok {
@ -479,11 +478,11 @@ func extendConstellationServicesValues(
if !ok {
return errors.New("invalid join-service values")
}
joinServiceVals["attestationVariant"] = config.AttestationVariant
joinServiceVals["attestationVariant"] = cfg.AttestationVariant
// measurements are updated separately during upgrade,
// so we only set them in Helm during init.
measurementsJSON, err := json.Marshal(config.GetMeasurements())
measurementsJSON, err := json.Marshal(cfg.GetMeasurements())
if err != nil {
return fmt.Errorf("marshalling measurements: %w", err)
}
@ -493,9 +492,9 @@ func extendConstellationServicesValues(
if !ok {
return errors.New("invalid verification-service values")
}
verifyServiceVals["attestationVariant"] = config.AttestationVariant
verifyServiceVals["attestationVariant"] = cfg.AttestationVariant
csp := config.GetProvider()
csp := cfg.GetProvider()
switch csp {
case cloudprovider.Azure:
joinServiceVals, ok := in["join-service"].(map[string]any)
@ -503,10 +502,10 @@ func extendConstellationServicesValues(
return errors.New("invalid join-service values")
}
idKeyCfg := idkeydigest.Config{
IDKeyDigests: config.IDKeyDigests(),
EnforcementPolicy: config.IDKeyDigestPolicy(),
MAAURL: maaURL,
idKeyCfg := config.SNPFirmwareSignerConfig{
AcceptedKeyDigests: cfg.IDKeyDigests(),
EnforcementPolicy: cfg.IDKeyDigestPolicy(),
MAAURL: maaURL,
}
marshalledCfg, err := json.Marshal(idKeyCfg)
if err != nil {
@ -515,12 +514,12 @@ func extendConstellationServicesValues(
joinServiceVals["idKeyConfig"] = string(marshalledCfg)
in["azure"] = map[string]any{
"deployCSIDriver": config.DeployCSIDriver(),
"deployCSIDriver": cfg.DeployCSIDriver(),
}
case cloudprovider.GCP:
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(),
Provider: config.ProviderConfig{Azure: &config.AzureConfig{
DeployCSIDriver: toPtr(true),
EnforceIDKeyDigest: idkeydigest.StrictChecking,
EnforceIDKeyDigest: idkeydigest.Equal,
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},
{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
data:
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:
measurementSalt: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

View File

@ -11,8 +11,8 @@ go_library(
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws",
visibility = ["//:__subpackages__"],
deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm",
"//internal/config",
"//internal/variant",
"@com_github_aws_aws_sdk_go_v2_config//:config",
"@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"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"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/config"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2"
@ -30,10 +30,10 @@ type Validator struct {
}
// 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 = vtpm.NewValidator(
pcrs,
cfg.Measurements,
getTrustedKey,
v.tpmEnabled,
log,

View File

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

View File

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

View File

@ -21,23 +21,14 @@ import (
"math/big"
"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/config"
internalCrypto "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest"
"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.
type Validator struct {
variant.AzureSEVSNP
@ -45,28 +36,24 @@ type Validator struct {
hclValidator hclAkValidator
maa maaValidator
idKeyDigests idkeydigest.IDKeyDigests
enforceIDKeyDigest idkeydigest.EnforceIDKeyDigest
maaURL string
config config.AzureSEVSNP
log vtpm.AttestationLogger
}
// 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 {
log = nopAttestationLogger{}
}
v := &Validator{
hclValidator: &azureInstanceInfo{},
maa: newMAAClient(),
idKeyDigests: idKeyConf.IDKeyDigests,
enforceIDKeyDigest: idKeyConf.EnforcementPolicy,
maaURL: idKeyConf.MAAURL,
log: log,
hclValidator: &azureInstanceInfo{},
maa: newMAAClient(),
config: cfg,
log: log,
}
v.Validator = vtpm.NewValidator(
pcrs,
cfg.Measurements,
v.getTrustedKey,
validateCVM,
log,
@ -107,7 +94,7 @@ func (v *Validator) getTrustedKey(ctx context.Context, attDoc vtpm.AttestationDo
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 {
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.
// 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)
if err != nil {
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.
ask, err := internalCrypto.PemToX509Cert(certChain)
if err != nil {
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}
}
@ -165,7 +147,7 @@ func (v *Validator) validateSNPReport(
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}
}
if report.LaunchTCB != report.CommittedTCB {
@ -205,7 +187,7 @@ func (v *Validator) validateSNPReport(
}
hasExpectedIDKeyDigest := false
for _, digest := range v.idKeyDigests {
for _, digest := range v.config.FirmwareSignerConfig.AcceptedKeyDigests {
if bytes.Equal(digest, report.IDKeyDigest[:]) {
hasExpectedIDKeyDigest = true
break
@ -213,14 +195,22 @@ func (v *Validator) validateSNPReport(
}
if !hasExpectedIDKeyDigest {
switch v.enforceIDKeyDigest {
switch v.config.FirmwareSignerConfig.EnforcementPolicy {
case idkeydigest.MAAFallback:
v.log.Infof("configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation", v.idKeyDigests, report.IDKeyDigest[:])
return v.maa.validateToken(ctx, v.maaURL, maaToken, extraData)
v.log.Infof(
"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:
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:
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",
visibility = ["//:__subpackages__"],
deps = [
"//internal/attestation/measurements",
"//internal/attestation/vtpm",
"//internal/config",
"//internal/crypto",
"//internal/variant",
"@com_github_google_go_tpm//tpm2",
@ -34,6 +34,7 @@ go_test(
"//internal/attestation/measurements",
"//internal/attestation/simulator",
"//internal/attestation/vtpm",
"//internal/config",
"//internal/crypto",
"//internal/logger",
"@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/simulator"
"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/logger"
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)
require.NoError(err)
roots := x509.NewCertPool()

View File

@ -15,8 +15,8 @@ import (
"errors"
"fmt"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
certutil "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/variant"
"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.
func NewValidator(pcrs measurements.M, log vtpm.AttestationLogger) *Validator {
func NewValidator(cfg config.AzureTrustedLaunch, log vtpm.AttestationLogger) *Validator {
rootPool := x509.NewCertPool()
rootPool.AddCert(ameRoot)
v := &Validator{roots: rootPool}
v.Validator = vtpm.NewValidator(
pcrs,
cfg.Measurements,
v.verifyAttestationKey,
validateVM,
log,

View File

@ -12,10 +12,10 @@ go_library(
"//internal/attestation/azure/snp",
"//internal/attestation/azure/trustedlaunch",
"//internal/attestation/gcp",
"//internal/attestation/idkeydigest",
"//internal/attestation/measurements",
"//internal/attestation/qemu",
"//internal/attestation/vtpm",
"//internal/config",
"//internal/variant",
],
)
@ -25,7 +25,7 @@ go_test(
srcs = ["choose_test.go"],
embed = [":choose"],
deps = [
"//internal/attestation/idkeydigest",
"//internal/config",
"//internal/variant",
"@com_github_stretchr_testify//assert",
"@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/trustedlaunch"
"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/qemu"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"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.
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) {
switch attestationVariant {
case variant.AWSNitroTPM{}:
return aws.NewValidator(measurements, log), nil
return aws.NewValidator(config.AWSNitroTPM{Measurements: measurements}, log), nil
case variant.AzureTrustedLaunch{}:
return trustedlaunch.NewValidator(measurements, log), nil
return trustedlaunch.NewValidator(config.AzureTrustedLaunch{Measurements: measurements}, log), nil
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{}:
return gcp.NewValidator(measurements, log), nil
return gcp.NewValidator(config.GCPSEVES{Measurements: measurements}, log), nil
case variant.QEMUVTPM{}:
return qemu.NewValidator(measurements, log), nil
return qemu.NewValidator(config.QEMUVTPM{Measurements: measurements}, log), nil
case variant.Dummy{}:
return atls.NewFakeValidator(variant.Dummy{}), nil
default:

View File

@ -10,7 +10,7 @@ import (
"encoding/asn1"
"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/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -96,7 +96,7 @@ func TestValidator(t *testing.T) {
assert := assert.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 {
assert.Error(err)

View File

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

View File

@ -16,8 +16,8 @@ import (
compute "cloud.google.com/go/compute/apiv1"
"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/config"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest"
"github.com/googleapis/gax-go/v2"
@ -35,12 +35,12 @@ type Validator struct {
}
// 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{
restClient: newInstanceClient,
}
v.Validator = vtpm.NewValidator(
pcrs,
cfg.Measurements,
v.trustedKeyFromGCEAPI,
validateCVM,
log,

View File

@ -4,12 +4,11 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "idkeydigest",
srcs = [
"enforceidkeydigest_string.go",
"enforcement_string.go",
"idkeydigest.go",
],
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest",
visibility = ["//:__subpackages__"],
deps = ["//internal/cloud/cloudprovider"],
)
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
*/
// Package idkeydigest contains policies and type definitions
// for checking the ID Key Digest value in SEV-SNP attestation.
// Package idkeydigest provides type definitions for the `idkeydigest` value of SEV-SNP attestation.
package idkeydigest
import (
@ -14,59 +13,48 @@ import (
"errors"
"fmt"
"strings"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
)
// Config contains the configuration for ID Key Digest validation.
type Config struct {
IDKeyDigests IDKeyDigests `json:"idKeyDigests"`
EnforcementPolicy EnforceIDKeyDigest `json:"enforcementPolicy"`
MAAURL string `json:"maaURL,omitempty"`
}
//go:generate stringer -type=Enforcement
//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 (
// Unknown is reserved for invalid configurations.
Unknown EnforceIDKeyDigest = iota
// StrictChecking will return an error if the ID key digest is not found in the expected list.
StrictChecking
// MAAFallback attempts to verify the attestation using Microsoft Azure Attestation (MAA),
// if the ID key digest is not found in the expected list.
Unknown Enforcement = iota
// Equal will error if the reported signing key digest does not match any of the values in 'acceptedKeyDigests'.
Equal
// MAAFallback uses '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'.
MAAFallback
// WarnOnly logs a warning if the ID key digest is not found in the expected list.
// No error is returned.
// WarnOnly is the same as 'equal', but only prints a warning instead of returning an error if no match is found.
WarnOnly
)
// 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 json.Unmarshal(b, val)
})
}
// MarshalJSON implements the json.Marshaler interface.
func (e EnforceIDKeyDigest) MarshalJSON() ([]byte, error) {
func (e Enforcement) MarshalJSON() ([]byte, error) {
return json.Marshal(e.String())
}
// 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)
}
// MarshalYAML implements the yaml.Marshaler interface.
func (e EnforceIDKeyDigest) MarshalYAML() (any, error) {
func (e Enforcement) MarshalYAML() (any, error) {
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.
// If set to true, the value will be set to StrictChecking.
// 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)
if legacyErr == nil {
if legacyEnforce {
*e = StrictChecking
*e = Equal
} else {
*e = WarnOnly
}
@ -91,18 +79,18 @@ func (e *EnforceIDKeyDigest) unmarshal(unmarshalFunc func(any) error) error {
*e = EnforcePolicyFromString(enforce)
if *e == Unknown {
return fmt.Errorf("unknown EnforceIDKeyDigest value: %q", enforce)
return fmt.Errorf("unknown Enforcement value: %q", enforce)
}
return nil
}
// EnforcePolicyFromString returns EnforceIDKeyDigest from string.
func EnforcePolicyFromString(s string) EnforceIDKeyDigest {
// EnforcePolicyFromString returns Enforcement from string.
func EnforcePolicyFromString(s string) Enforcement {
s = strings.ToLower(s)
switch s {
case "strictchecking":
return StrictChecking
case "equal":
return Equal
case "maafallback":
return MAAFallback
case "warnonly":
@ -112,37 +100,32 @@ func EnforcePolicyFromString(s string) EnforceIDKeyDigest {
}
}
// IDKeyDigests is a list of trusted digest values for the ID key.
type IDKeyDigests [][]byte
// List is a list of trusted digest values for the ID key.
type List [][]byte
type encodedIDKeyDigests []string
type encodedList []string
// encodedDigestLength is the length of a digest in hex encoding.
const encodedDigestLength = 2 * 48
// NewIDKeyDigests creates a new IDKeyDigests from a list of digests.
func NewIDKeyDigests(digests [][]byte) IDKeyDigests {
idKeyDigests := make(IDKeyDigests, len(digests))
// NewList creates a new IDKeyDigests from a list of digests.
func NewList(digests [][]byte) List {
idKeyDigests := make(List, len(digests))
copy(idKeyDigests, digests)
return idKeyDigests
}
// DefaultsFor returns the default IDKeyDigests for the given cloud provider.
func DefaultsFor(csp cloudprovider.Provider) IDKeyDigests {
switch csp {
case cloudprovider.Azure:
return 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},
{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
// DefaultList returns the default list of accepted ID key digests.
func DefaultList() List {
return 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},
{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},
}
}
// MarshalYAML implements the yaml.Marshaler interface.
func (d IDKeyDigests) MarshalYAML() (any, error) {
func (d List) MarshalYAML() (any, error) {
encodedIDKeyDigests := []string{}
for _, digest := range d {
encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest))
@ -151,8 +134,8 @@ func (d IDKeyDigests) MarshalYAML() (any, error) {
}
// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (d *IDKeyDigests) UnmarshalYAML(unmarshal func(any) error) error {
var encodedDigests encodedIDKeyDigests
func (d *List) UnmarshalYAML(unmarshal func(any) error) error {
var encodedDigests encodedList
if err := unmarshal(&encodedDigests); err != nil {
// Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct.
var unmarshalledString string
@ -171,7 +154,7 @@ func (d *IDKeyDigests) UnmarshalYAML(unmarshal func(any) error) error {
}
// MarshalJSON implements the json.Marshaler interface.
func (d IDKeyDigests) MarshalJSON() ([]byte, error) {
func (d List) MarshalJSON() ([]byte, error) {
encodedIDKeyDigests := []string{}
for _, digest := range d {
encodedIDKeyDigests = append(encodedIDKeyDigests, hex.EncodeToString(digest))
@ -180,8 +163,8 @@ func (d IDKeyDigests) MarshalJSON() ([]byte, error) {
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *IDKeyDigests) UnmarshalJSON(b []byte) error {
var encodedDigests encodedIDKeyDigests
func (d *List) UnmarshalJSON(b []byte) error {
var encodedDigests encodedList
if err := json.Unmarshal(b, &encodedDigests); err != nil {
// Unmarshalling failed, IDKeyDigests might be a simple string instead of IDKeyDigests struct.
var unmarshalledString string
@ -200,7 +183,7 @@ func (d *IDKeyDigests) UnmarshalJSON(b []byte) error {
}
// 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 {
if len(encodedDigest) != encodedDigestLength {
return fmt.Errorf("invalid digest length: %d", len(encodedDigest))

View File

@ -17,12 +17,12 @@ import (
func TestMarshal(t *testing.T) {
testCases := map[string]struct {
dgst IDKeyDigests
dgst List
wantYAML string
wantJSON string
}{
"digest": {
dgst: IDKeyDigests{{0x01, 0x02, 0x03, 0x04}, {0xff, 0xff, 0xff, 0xff}},
dgst: List{{0x01, 0x02, 0x03, 0x04}, {0xff, 0xff, 0xff, 0xff}},
wantJSON: `["01020304","ffffffff"]`,
wantYAML: `
- "01020304"
@ -58,7 +58,7 @@ func TestUnmarshal(t *testing.T) {
testCases := map[string]struct {
yaml string
json string
wantDgst IDKeyDigests
wantDgst List
wantErr bool
}{
"digest struct": {
@ -66,20 +66,15 @@ func TestUnmarshal(t *testing.T) {
yaml: `
- "57486a447ec0f1958002a22a06b7673b9fd27d11e1c6527498056054c5fa92d23c50f9de44072760fe2b6fb89740b696"
- "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},
{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": {
json: `"010203"`,
yaml: `"010203"`,
wantDgst: IDKeyDigests{{}},
wantDgst: List{{}},
wantErr: true,
},
}
@ -91,7 +86,7 @@ func TestUnmarshal(t *testing.T) {
{
// YAML
var dgst IDKeyDigests
var dgst List
err := yaml.Unmarshal([]byte(tc.yaml), &dgst)
if tc.wantErr {
require.Error(err)
@ -104,7 +99,7 @@ func TestUnmarshal(t *testing.T) {
{
// JSON
var dgst IDKeyDigests
var dgst List
err := json.Unmarshal([]byte(tc.json), &dgst)
if tc.wantErr {
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 {
input EnforceIDKeyDigest
input Enforcement
wantJSON string
wantYAML string
}{
"strict": {
input: StrictChecking,
wantJSON: `"StrictChecking"`,
wantYAML: "StrictChecking",
input: Equal,
wantJSON: `"Equal"`,
wantYAML: "Equal",
},
"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 {
inputJSON string
inputYAML string
want EnforceIDKeyDigest
want Enforcement
wantErr bool
}{
"strict": {
inputJSON: `"StrictChecking"`,
inputYAML: "StrictChecking",
want: StrictChecking,
inputJSON: `"Equal"`,
inputYAML: "Equal",
want: Equal,
},
"maaFallback": {
inputJSON: `"MAAFallback"`,
@ -185,16 +180,6 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
inputYAML: "WarnOnly",
want: WarnOnly,
},
"legacyTrue": {
inputJSON: `true`,
inputYAML: "true",
want: StrictChecking,
},
"legacyFalse": {
inputJSON: `false`,
inputYAML: "false",
want: WarnOnly,
},
"invalid": {
inputJSON: `"invalid"`,
inputYAML: "invalid",
@ -214,7 +199,7 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
{
// YAML
var got EnforceIDKeyDigest
var got Enforcement
err := yaml.Unmarshal([]byte(tc.inputYAML), &got)
if tc.wantErr {
assert.Error(err)
@ -227,7 +212,7 @@ func TestEnforceIDKeyDigestUnmarshal(t *testing.T) {
{
// JSON
var got EnforceIDKeyDigest
var got Enforcement
err := json.Unmarshal([]byte(tc.inputJSON), &got)
if tc.wantErr {
assert.Error(err)

View File

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

View File

@ -10,8 +10,8 @@ import (
"context"
"crypto"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/attestation/vtpm"
"github.com/edgelesssys/constellation/v2/internal/config"
"github.com/edgelesssys/constellation/v2/internal/variant"
"github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2"
@ -24,10 +24,10 @@ type Validator struct {
}
// 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{
Validator: vtpm.NewValidator(
pcrs,
cfg.Measurements,
unconditionalTrust,
func(vtpm.AttestationDocument, *attest.MachineState) error { return nil },
log,

View File

@ -4,6 +4,7 @@ load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "config",
srcs = [
"attestation.go",
"config.go",
"config_doc.go",
# keep
@ -37,6 +38,7 @@ go_library(
go_test(
name = "config_test",
srcs = [
"attestation_test.go",
"config_test.go",
"validation_test.go",
],
@ -56,6 +58,7 @@ go_test(
"@com_github_spf13_afero//:afero",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
"@in_gopkg_yaml_v3//:yaml_v3",
"@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/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/variant"
"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
// types in other packages.
type Digests = idkeydigest.IDKeyDigests
type Digests = idkeydigest.List
const (
// 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"`
// description: |
// Enforce the specified idKeyDigest value during remote attestation.
EnforceIDKeyDigest idkeydigest.EnforceIDKeyDigest `yaml:"enforceIdKeyDigest" validate:"required"`
EnforceIDKeyDigest idkeydigest.Enforcement `yaml:"enforceIdKeyDigest" validate:"required"`
// description: |
// Expected confidential VM measurements.
Measurements Measurements `yaml:"measurements" validate:"required,no_placeholders"`
@ -314,7 +315,7 @@ func Default() *Config {
InstanceType: "Standard_DC4as_v5",
StateDiskType: "Premium_LRS",
DeployCSIDriver: toPtr(true),
IDKeyDigest: idkeydigest.DefaultsFor(cloudprovider.Azure),
IDKeyDigest: idkeydigest.DefaultList(),
EnforceIDKeyDigest: idkeydigest.MAAFallback,
SecureBoot: toPtr(false),
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.
func (c *Config) IDKeyDigestPolicy() idkeydigest.EnforceIDKeyDigest {
func (c *Config) IDKeyDigestPolicy() idkeydigest.Enforcement {
if c.Provider.Azure != nil {
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.
func (c *Config) IDKeyDigests() idkeydigest.IDKeyDigests {
func (c *Config) IDKeyDigests() idkeydigest.List {
if c.Provider.Azure != nil {
return c.Provider.Azure.IDKeyDigest
}
@ -651,6 +652,141 @@ func (c *Config) Validate(force bool) error {
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 {
return &v
}

View File

@ -11,13 +11,19 @@ import (
)
var (
ConfigDoc encoder.Doc
ProviderConfigDoc encoder.Doc
AWSConfigDoc encoder.Doc
AzureConfigDoc encoder.Doc
GCPConfigDoc encoder.Doc
OpenStackConfigDoc encoder.Doc
QEMUConfigDoc encoder.Doc
ConfigDoc encoder.Doc
ProviderConfigDoc encoder.Doc
AWSConfigDoc encoder.Doc
AzureConfigDoc encoder.Doc
GCPConfigDoc encoder.Doc
OpenStackConfigDoc 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() {
@ -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].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].Type = "EnforceIDKeyDigest"
AzureConfigDoc.Fields[13].Type = "Enforcement"
AzureConfigDoc.Fields[13].Note = ""
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."
@ -426,6 +432,112 @@ func init() {
QEMUConfigDoc.Fields[8].Note = ""
QEMUConfigDoc.Fields[8].Description = "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 {
@ -456,6 +568,30 @@ func (_ QEMUConfig) Doc() *encoder.Doc {
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.
func GetConfigurationDoc() *encoder.FileDoc {
return &encoder.FileDoc{
@ -469,6 +605,12 @@ func GetConfigurationDoc() *encoder.FileDoc {
&GCPConfigDoc,
&OpenStackConfigDoc,
&QEMUConfigDoc,
&AWSNitroTPMDoc,
&AzureSEVSNPDoc,
&SNPFirmwareSignerConfigDoc,
&AzureTrustedLaunchDoc,
&GCPSEVESDoc,
&QEMUVTPMDoc,
},
}
}

View File

@ -739,7 +739,7 @@ func TestConfigVersionCompatibility(t *testing.T) {
StateDiskType: "Premium_LRS",
ConfidentialVM: toPtr(true),
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,
SecureBoot: toPtr(false),
DeployCSIDriver: toPtr(true),
@ -768,7 +768,7 @@ func TestConfigVersionCompatibility(t *testing.T) {
StateDiskType: "Premium_LRS",
ConfidentialVM: toPtr(true),
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},
{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/idkeydigest",
"//internal/attestation/measurements",
"//internal/config",
"//internal/constants",
"//internal/file",
"//internal/logger",
@ -35,7 +36,7 @@ go_test(
"//internal/atls",
"//internal/attestation/idkeydigest",
"//internal/attestation/measurements",
"//internal/cloud/cloudprovider",
"//internal/config",
"//internal/constants",
"//internal/file",
"//internal/logger",

View File

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

View File

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