mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
internal: use config to create attestation validators (#1561)
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
2b962598bf
commit
ec01c57661
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.",
|
||||||
|
@ -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 {
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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},
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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",
|
||||||
|
@ -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 {
|
||||||
|
@ -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
@ -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",
|
||||||
|
@ -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()
|
||||||
|
@ -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,
|
||||||
|
@ -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",
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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(
|
||||||
|
@ -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]]
|
|
||||||
}
|
|
26
internal/attestation/idkeydigest/enforcement_string.go
Normal file
26
internal/attestation/idkeydigest/enforcement_string.go
Normal 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]]
|
||||||
|
}
|
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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",
|
||||||
|
@ -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,
|
||||||
|
@ -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",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
75
internal/config/attestation.go
Normal file
75
internal/config/attestation.go
Normal 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
|
||||||
|
}
|
46
internal/config/attestation_test.go
Normal file
46
internal/config/attestation_test.go
Normal 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))
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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},
|
||||||
},
|
},
|
||||||
|
@ -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",
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user