From 8f21972aecfd44b1efc8d8e917479feda58aed5c Mon Sep 17 00:00:00 2001 From: Otto Bittner Date: Fri, 9 Jun 2023 15:41:02 +0200 Subject: [PATCH] attestation: add `awsSEVSNP` as new variant (#1900) * variant: move into internal/attestation * attesation: move aws attesation into subfolder nitrotpm * config: add aws-sev-snp variant * cli: add tf option to enable AWS SNP For now the implementations in aws/nitrotpm and aws/snp are identical. They both contain the aws/nitrotpm impl. A separate commit will add the actual attestation logic. --- .../actions/constellation_create/action.yml | 8 +- .github/actions/e2e_test/action.yml | 2 +- bootstrapper/cmd/bootstrapper/BUILD.bazel | 2 +- bootstrapper/cmd/bootstrapper/main.go | 2 +- bootstrapper/internal/initserver/BUILD.bazel | 2 +- .../internal/initserver/initserver_test.go | 2 +- cli/internal/cloudcmd/BUILD.bazel | 4 +- cli/internal/cloudcmd/clients.go | 2 +- cli/internal/cloudcmd/clients_test.go | 2 +- cli/internal/cloudcmd/create.go | 3 +- cli/internal/cloudcmd/validators.go | 4 +- cli/internal/cmd/BUILD.bazel | 4 +- cli/internal/cmd/configgenerate.go | 2 +- cli/internal/cmd/configgenerate_test.go | 9 +- cli/internal/cmd/create.go | 2 +- cli/internal/cmd/init.go | 5 + cli/internal/cmd/init_test.go | 2 +- cli/internal/cmd/upgradeapply.go | 2 +- cli/internal/cmd/upgradeapply_test.go | 2 +- cli/internal/cmd/upgradecheck.go | 2 +- cli/internal/cmd/upgradecheck_test.go | 2 +- cli/internal/cmd/verify_test.go | 2 +- cli/internal/kubernetes/BUILD.bazel | 4 +- cli/internal/kubernetes/upgrade.go | 2 +- cli/internal/kubernetes/upgrade_test.go | 2 +- cli/internal/terraform/terraform/aws/main.tf | 2 + .../aws/modules/instance_group/main.tf | 5 + .../aws/modules/instance_group/variables.tf | 6 + .../terraform/terraform/aws/variables.tf | 6 + cli/internal/terraform/variables.go | 5 +- disk-mapper/cmd/BUILD.bazel | 2 +- disk-mapper/cmd/main.go | 2 +- .../internal/recoveryserver/BUILD.bazel | 2 +- .../recoveryserver/recoveryserver_test.go | 2 +- docs/docs/reference/cli.md | 2 +- e2e/internal/upgrade/BUILD.bazel | 2 +- e2e/internal/upgrade/image.go | 2 +- internal/api/attestationconfig/BUILD.bazel | 0 .../api/attestationconfig/client/BUILD.bazel | 0 internal/api/attestationconfigapi/BUILD.bazel | 2 +- internal/api/attestationconfigapi/azure.go | 2 +- internal/api/attestationconfigapi/client.go | 2 +- internal/atls/BUILD.bazel | 4 +- internal/atls/README.md | 2 +- internal/atls/atls.go | 2 +- internal/atls/atls_test.go | 2 +- internal/attestation/aws/BUILD.bazel | 45 +----- internal/attestation/aws/aws.go | 23 +-- internal/attestation/aws/nitrotpm/BUILD.bazel | 72 +++++++++ .../attestation/aws/{ => nitrotpm}/issuer.go | 18 +-- .../attestation/aws/nitrotpm/issuer_test.go | 118 ++++++++++++++ internal/attestation/aws/nitrotpm/nitrotpm.go | 29 ++++ .../aws/{ => nitrotpm}/validator.go | 4 +- .../aws/nitrotpm/validator_test.go | 146 ++++++++++++++++++ internal/attestation/aws/snp/BUILD.bazel | 51 ++++++ internal/attestation/aws/snp/issuer.go | 66 ++++++++ .../attestation/aws/{ => snp}/issuer_test.go | 2 +- internal/attestation/aws/snp/snp.go | 52 +++++++ internal/attestation/aws/snp/validator.go | 101 ++++++++++++ .../aws/{ => snp}/validator_test.go | 2 +- internal/attestation/azure/snp/BUILD.bazel | 2 +- internal/attestation/azure/snp/issuer.go | 2 +- internal/attestation/azure/snp/validator.go | 2 +- .../azure/trustedlaunch/BUILD.bazel | 2 +- .../attestation/azure/trustedlaunch/issuer.go | 2 +- .../azure/trustedlaunch/validator.go | 2 +- internal/attestation/choose/BUILD.bazel | 7 +- internal/attestation/choose/choose.go | 19 ++- internal/attestation/choose/choose_test.go | 5 +- internal/attestation/gcp/BUILD.bazel | 2 +- internal/attestation/gcp/issuer.go | 2 +- internal/attestation/gcp/validator.go | 2 +- internal/attestation/measurements/BUILD.bazel | 4 +- .../measurement-generator/BUILD.bazel | 2 +- .../measurement-generator/generate.go | 4 +- .../attestation/measurements/measurements.go | 9 +- .../measurements/measurements_enterprise.go | 1 + .../measurements/measurements_oss.go | 11 ++ .../measurements/measurements_test.go | 2 +- internal/attestation/qemu/BUILD.bazel | 2 +- internal/attestation/qemu/issuer.go | 2 +- internal/attestation/qemu/validator.go | 2 +- internal/attestation/tdx/BUILD.bazel | 2 +- internal/attestation/tdx/issuer.go | 2 +- internal/attestation/tdx/validator.go | 2 +- .../{ => attestation}/variant/BUILD.bazel | 2 +- internal/{ => attestation}/variant/variant.go | 23 ++- internal/config/BUILD.bazel | 4 +- internal/config/attestation.go | 4 +- internal/config/attestation_test.go | 5 +- internal/config/config.go | 56 ++++++- internal/config/config_doc.go | 82 +++++++--- internal/config/config_test.go | 8 +- internal/config/migration/BUILD.bazel | 2 +- internal/config/migration/migration.go | 2 +- internal/config/validation.go | 34 +++- internal/grpc/dialer/BUILD.bazel | 2 +- internal/grpc/dialer/dialer_test.go | 2 +- internal/imagefetcher/BUILD.bazel | 4 +- internal/imagefetcher/imagefetcher.go | 2 +- internal/imagefetcher/imagefetcher_test.go | 2 +- internal/watcher/BUILD.bazel | 4 +- internal/watcher/validator.go | 2 +- internal/watcher/validator_test.go | 2 +- joinservice/cmd/BUILD.bazel | 2 +- joinservice/cmd/main.go | 2 +- measurement-reader/cmd/BUILD.bazel | 2 +- measurement-reader/cmd/main.go | 4 +- verify/cmd/BUILD.bazel | 2 +- verify/cmd/main.go | 2 +- 110 files changed, 993 insertions(+), 215 deletions(-) create mode 100644 internal/api/attestationconfig/BUILD.bazel create mode 100644 internal/api/attestationconfig/client/BUILD.bazel create mode 100644 internal/attestation/aws/nitrotpm/BUILD.bazel rename internal/attestation/aws/{ => nitrotpm}/issuer.go (77%) create mode 100644 internal/attestation/aws/nitrotpm/issuer_test.go create mode 100644 internal/attestation/aws/nitrotpm/nitrotpm.go rename internal/attestation/aws/{ => nitrotpm}/validator.go (97%) create mode 100644 internal/attestation/aws/nitrotpm/validator_test.go create mode 100644 internal/attestation/aws/snp/BUILD.bazel create mode 100644 internal/attestation/aws/snp/issuer.go rename internal/attestation/aws/{ => snp}/issuer_test.go (99%) create mode 100644 internal/attestation/aws/snp/snp.go create mode 100644 internal/attestation/aws/snp/validator.go rename internal/attestation/aws/{ => snp}/validator_test.go (99%) rename internal/{ => attestation}/variant/BUILD.bazel (91%) rename internal/{ => attestation}/variant/variant.go (92%) diff --git a/.github/actions/constellation_create/action.yml b/.github/actions/constellation_create/action.yml index cd0e83e5f..8907a2eb1 100644 --- a/.github/actions/constellation_create/action.yml +++ b/.github/actions/constellation_create/action.yml @@ -107,8 +107,8 @@ runs: constellation-conf.yaml yq eval -i \ - "(.provider | select(. | has(\"aws\")).aws.region) = \"eu-central-1\" | - (.provider | select(. | has(\"aws\")).aws.zone) = \"eu-central-1c\" | + "(.provider | select(. | has(\"aws\")).aws.region) = \"eu-west-1\" | + (.provider | select(. | has(\"aws\")).aws.zone) = \"eu-west-1c\" | (.provider | select(. | has(\"aws\")).aws.iamProfileControlPlane) = \"e2e_test_control_plane_instance_profile\" | (.provider | select(. | has(\"aws\")).aws.iamProfileWorkerNodes) = \"e2e_test_worker_node_instance_profile\"" \ constellation-conf.yaml @@ -143,6 +143,10 @@ runs: "(.attestation | select(. | has(\"awsNitroTPM\")).awsNitroTPM.measurements) = {15:{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":false}}" \ constellation-conf.yaml + yq eval -i \ + "(.attestation | select(. | has(\"awsSEVSNP\")).awsSEVSNP.measurements) = {15:{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":false}}" \ + constellation-conf.yaml + yq eval -i \ "(.attestation | select(. | has(\"azureSEVSNP\")).azureSEVSNP.measurements) = {15:{\"expected\":\"0000000000000000000000000000000000000000000000000000000000000000\",\"warnOnly\":false}}" \ constellation-conf.yaml diff --git a/.github/actions/e2e_test/action.yml b/.github/actions/e2e_test/action.yml index 51cabcef1..e663ce74c 100644 --- a/.github/actions/e2e_test/action.yml +++ b/.github/actions/e2e_test/action.yml @@ -203,7 +203,7 @@ runs: with: cloudProvider: ${{ inputs.cloudProvider }} namePrefix: ${{ steps.create-prefix.outputs.prefix }} - awsZone: eu-central-1c + awsZone: eu-west-1c azureRegion: northeurope gcpProjectID: ${{ inputs.gcpProject }} gcpZone: europe-west3-b diff --git a/bootstrapper/cmd/bootstrapper/BUILD.bazel b/bootstrapper/cmd/bootstrapper/BUILD.bazel index 19dbc3285..144a9403f 100644 --- a/bootstrapper/cmd/bootstrapper/BUILD.bazel +++ b/bootstrapper/cmd/bootstrapper/BUILD.bazel @@ -26,6 +26,7 @@ go_library( "//internal/attestation/initialize", "//internal/attestation/simulator", "//internal/attestation/tdx", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/cloud/aws", "//internal/cloud/azure", @@ -40,7 +41,6 @@ go_library( "//internal/kubernetes/kubectl", "//internal/logger", "//internal/role", - "//internal/variant", "//internal/versions/components", "@com_github_spf13_afero//:afero", "@io_k8s_kubernetes//cmd/kubeadm/app/apis/kubeadm/v1beta3", diff --git a/bootstrapper/cmd/bootstrapper/main.go b/bootstrapper/cmd/bootstrapper/main.go index 986cc9e47..0151703d3 100644 --- a/bootstrapper/cmd/bootstrapper/main.go +++ b/bootstrapper/cmd/bootstrapper/main.go @@ -24,6 +24,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/simulator" "github.com/edgelesssys/constellation/v2/internal/attestation/tdx" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" awscloud "github.com/edgelesssys/constellation/v2/internal/cloud/aws" azurecloud "github.com/edgelesssys/constellation/v2/internal/cloud/azure" @@ -35,7 +36,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" ) const ( diff --git a/bootstrapper/internal/initserver/BUILD.bazel b/bootstrapper/internal/initserver/BUILD.bazel index c8cfe0025..634c06155 100644 --- a/bootstrapper/internal/initserver/BUILD.bazel +++ b/bootstrapper/internal/initserver/BUILD.bazel @@ -40,12 +40,12 @@ go_test( deps = [ "//bootstrapper/initproto", "//internal/atls", + "//internal/attestation/variant", "//internal/crypto/testvector", "//internal/file", "//internal/kms/setup", "//internal/kms/uri", "//internal/logger", - "//internal/variant", "//internal/versions/components", "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", diff --git a/bootstrapper/internal/initserver/initserver_test.go b/bootstrapper/internal/initserver/initserver_test.go index 4ee0511c8..461bcd91c 100644 --- a/bootstrapper/internal/initserver/initserver_test.go +++ b/bootstrapper/internal/initserver/initserver_test.go @@ -19,12 +19,12 @@ import ( "github.com/edgelesssys/constellation/v2/bootstrapper/initproto" "github.com/edgelesssys/constellation/v2/internal/atls" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/crypto/testvector" "github.com/edgelesssys/constellation/v2/internal/file" kmssetup "github.com/edgelesssys/constellation/v2/internal/kms/setup" "github.com/edgelesssys/constellation/v2/internal/kms/uri" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions/components" "github.com/spf13/afero" "github.com/stretchr/testify/assert" diff --git a/cli/internal/cloudcmd/BUILD.bazel b/cli/internal/cloudcmd/BUILD.bazel index 7ae0cd03c..d21a3796a 100644 --- a/cli/internal/cloudcmd/BUILD.bazel +++ b/cli/internal/cloudcmd/BUILD.bazel @@ -23,12 +23,12 @@ go_library( "//internal/atls", "//internal/attestation/choose", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/cloud/gcpshared", "//internal/config", "//internal/constants", "//internal/imagefetcher", - "//internal/variant", "@com_github_azure_azure_sdk_for_go//profiles/latest/attestation/attestation", "@com_github_azure_azure_sdk_for_go_sdk_azcore//policy", "@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity", @@ -53,10 +53,10 @@ go_test( "//cli/internal/iamid", "//cli/internal/terraform", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/cloud/gcpshared", "//internal/config", - "//internal/variant", "@com_github_hashicorp_terraform_json//:terraform-json", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/cli/internal/cloudcmd/clients.go b/cli/internal/cloudcmd/clients.go index e5064bb4a..9c591e57e 100644 --- a/cli/internal/cloudcmd/clients.go +++ b/cli/internal/cloudcmd/clients.go @@ -11,8 +11,8 @@ import ( "io" "github.com/edgelesssys/constellation/v2/cli/internal/terraform" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/variant" tfjson "github.com/hashicorp/terraform-json" ) diff --git a/cli/internal/cloudcmd/clients_test.go b/cli/internal/cloudcmd/clients_test.go index 927cc315a..c5478e9e1 100644 --- a/cli/internal/cloudcmd/clients_test.go +++ b/cli/internal/cloudcmd/clients_test.go @@ -12,8 +12,8 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/cli/internal/terraform" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/variant" tfjson "github.com/hashicorp/terraform-json" "go.uber.org/goleak" diff --git a/cli/internal/cloudcmd/create.go b/cli/internal/cloudcmd/create.go index 1da77f01d..6b38a38e1 100644 --- a/cli/internal/cloudcmd/create.go +++ b/cli/internal/cloudcmd/create.go @@ -21,11 +21,11 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/clusterid" "github.com/edgelesssys/constellation/v2/cli/internal/libvirt" "github.com/edgelesssys/constellation/v2/cli/internal/terraform" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "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/imagefetcher" - "github.com/edgelesssys/constellation/v2/internal/variant" ) // Creator creates cloud resources. @@ -143,6 +143,7 @@ func (c *Creator) createAWS(ctx context.Context, cl terraformClient, opts Create IAMProfileControlPlane: opts.Config.Provider.AWS.IAMProfileControlPlane, IAMProfileWorkerNodes: opts.Config.Provider.AWS.IAMProfileWorkerNodes, Debug: opts.Config.IsDebugCluster(), + EnableSNP: opts.Config.GetAttestationConfig().GetVariant().Equal(variant.AWSSEVSNP{}), } if err := cl.PrepareWorkspace(path.Join("terraform", strings.ToLower(cloudprovider.AWS.String())), &vars); err != nil { diff --git a/cli/internal/cloudcmd/validators.go b/cli/internal/cloudcmd/validators.go index 68796a825..343170ff1 100644 --- a/cli/internal/cloudcmd/validators.go +++ b/cli/internal/cloudcmd/validators.go @@ -16,8 +16,8 @@ import ( "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/cobra" ) @@ -31,7 +31,7 @@ func UpdateInitMeasurements(config config.AttestationCfg, ownerID, clusterID str m := config.GetMeasurements() switch config.GetVariant() { - case variant.AWSNitroTPM{}, variant.AzureTrustedLaunch{}, variant.AzureSEVSNP{}, variant.GCPSEVES{}, variant.QEMUVTPM{}: + case variant.AWSNitroTPM{}, variant.AWSSEVSNP{}, variant.AzureTrustedLaunch{}, variant.AzureSEVSNP{}, variant.GCPSEVES{}, variant.QEMUVTPM{}: if err := updateMeasurementTPM(m, uint32(measurements.PCRIndexOwnerID), ownerID); err != nil { return err } diff --git a/cli/internal/cmd/BUILD.bazel b/cli/internal/cmd/BUILD.bazel index fc6452e62..d3e540db7 100644 --- a/cli/internal/cmd/BUILD.bazel +++ b/cli/internal/cmd/BUILD.bazel @@ -53,6 +53,7 @@ go_library( "//internal/api/versionsapi", "//internal/atls", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/azureshared", "//internal/cloud/cloudprovider", "//internal/cloud/gcpshared", @@ -74,7 +75,6 @@ go_library( "//internal/retry", "//internal/semver", "//internal/sigstore", - "//internal/variant", "//internal/versions", "//operators/constellation-node-operator/api/v1alpha1", "//verify/verifyproto", @@ -140,6 +140,7 @@ go_test( "//internal/api/versionsapi", "//internal/atls", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/cloud/gcpshared", "//internal/config", @@ -152,7 +153,6 @@ go_test( "//internal/kms/uri", "//internal/license", "//internal/logger", - "//internal/variant", "//internal/versions", "//operators/constellation-node-operator/api/v1alpha1", "//verify/verifyproto", diff --git a/cli/internal/cmd/configgenerate.go b/cli/internal/cmd/configgenerate.go index f5d8af592..01f1ac25f 100644 --- a/cli/internal/cmd/configgenerate.go +++ b/cli/internal/cmd/configgenerate.go @@ -10,12 +10,12 @@ import ( "fmt" "strings" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/siderolabs/talos/pkg/machinery/config/encoder" "github.com/spf13/afero" diff --git a/cli/internal/cmd/configgenerate_test.go b/cli/internal/cmd/configgenerate_test.go index 9e38b26cc..f245d419e 100644 --- a/cli/internal/cmd/configgenerate_test.go +++ b/cli/internal/cmd/configgenerate_test.go @@ -11,12 +11,12 @@ import ( "fmt" "testing" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/spf13/afero" "github.com/spf13/cobra" @@ -216,7 +216,11 @@ func TestValidProviderAttestationCombination(t *testing.T) { variant.AzureSEVSNP{}, config.AttestationConfig{AzureSEVSNP: defaultAttestation.AzureSEVSNP}, }, - + { + cloudprovider.AWS, + variant.AWSSEVSNP{}, + config.AttestationConfig{AWSSEVSNP: defaultAttestation.AWSSEVSNP}, + }, { cloudprovider.AWS, variant.AWSNitroTPM{}, @@ -227,7 +231,6 @@ func TestValidProviderAttestationCombination(t *testing.T) { variant.GCPSEVES{}, config.AttestationConfig{GCPSEVES: defaultAttestation.GCPSEVES}, }, - { cloudprovider.QEMU, variant.QEMUVTPM{}, diff --git a/cli/internal/cmd/create.go b/cli/internal/cmd/create.go index 0e33afbc6..cd67ceeb2 100644 --- a/cli/internal/cmd/create.go +++ b/cli/internal/cmd/create.go @@ -14,11 +14,11 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd" "github.com/edgelesssys/constellation/v2/cli/internal/terraform" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "github.com/spf13/cobra" ) diff --git a/cli/internal/cmd/init.go b/cli/internal/cmd/init.go index 891b3f5ca..35659c3d8 100644 --- a/cli/internal/cmd/init.go +++ b/cli/internal/cmd/init.go @@ -21,6 +21,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" "github.com/edgelesssys/constellation/v2/internal/atls" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/spf13/afero" @@ -121,6 +122,10 @@ func (i *initCmd) initialize(cmd *cobra.Command, newDialer func(validator atls.V return err } + if conf.GetAttestationConfig().GetVariant().Equal(variant.AWSSEVSNP{}) { + cmd.PrintErrln("WARNING: SNP based attestation is still under active development. Please do not use in production.") + } + i.log.Debugf("Checking cluster ID file") var idFile clusterid.File if err := fileHandler.ReadJSON(constants.ClusterIDsFileName, &idFile); err != nil { diff --git a/cli/internal/cmd/init_test.go b/cli/internal/cmd/init_test.go index 632e5d9c1..5f868ab03 100644 --- a/cli/internal/cmd/init_test.go +++ b/cli/internal/cmd/init_test.go @@ -23,6 +23,7 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/clusterid" "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/cloud/gcpshared" "github.com/edgelesssys/constellation/v2/internal/config" @@ -34,7 +35,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/kms/uri" "github.com/edgelesssys/constellation/v2/internal/license" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/spf13/afero" "github.com/stretchr/testify/assert" diff --git a/cli/internal/cmd/upgradeapply.go b/cli/internal/cmd/upgradeapply.go index 54ec65431..4701b2174 100644 --- a/cli/internal/cmd/upgradeapply.go +++ b/cli/internal/cmd/upgradeapply.go @@ -20,13 +20,13 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/terraform" "github.com/edgelesssys/constellation/v2/cli/internal/upgrade" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/imagefetcher" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/spf13/afero" "github.com/spf13/cobra" diff --git a/cli/internal/cmd/upgradeapply_test.go b/cli/internal/cmd/upgradeapply_test.go index f4e8318b7..6edf07655 100644 --- a/cli/internal/cmd/upgradeapply_test.go +++ b/cli/internal/cmd/upgradeapply_test.go @@ -16,12 +16,12 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/clusterid" "github.com/edgelesssys/constellation/v2/cli/internal/kubernetes" "github.com/edgelesssys/constellation/v2/cli/internal/upgrade" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/cli/internal/cmd/upgradecheck.go b/cli/internal/cmd/upgradecheck.go index 97aa7da40..0a8ea1f6f 100644 --- a/cli/internal/cmd/upgradecheck.go +++ b/cli/internal/cmd/upgradecheck.go @@ -22,6 +22,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/fetcher" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config" @@ -30,7 +31,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl" conSemver "github.com/edgelesssys/constellation/v2/internal/semver" "github.com/edgelesssys/constellation/v2/internal/sigstore" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/siderolabs/talos/pkg/machinery/config/encoder" "github.com/spf13/afero" diff --git a/cli/internal/cmd/upgradecheck_test.go b/cli/internal/cmd/upgradecheck_test.go index 5c70409c1..04402e788 100644 --- a/cli/internal/cmd/upgradecheck_test.go +++ b/cli/internal/cmd/upgradecheck_test.go @@ -17,12 +17,12 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/cli/internal/cmd/verify_test.go b/cli/internal/cmd/verify_test.go index e92548f51..a74fd7d07 100644 --- a/cli/internal/cmd/verify_test.go +++ b/cli/internal/cmd/verify_test.go @@ -20,6 +20,7 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/clusterid" "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" @@ -27,7 +28,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/grpc/dialer" "github.com/edgelesssys/constellation/v2/internal/grpc/testdialer" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/verify/verifyproto" "github.com/spf13/afero" "github.com/stretchr/testify/assert" diff --git a/cli/internal/kubernetes/BUILD.bazel b/cli/internal/kubernetes/BUILD.bazel index cfa2a80c1..b63851de5 100644 --- a/cli/internal/kubernetes/BUILD.bazel +++ b/cli/internal/kubernetes/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "//cli/internal/upgrade", "//internal/api/versionsapi", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/compatibility", "//internal/config", @@ -24,7 +25,6 @@ go_library( "//internal/imagefetcher", "//internal/kubernetes", "//internal/kubernetes/kubectl", - "//internal/variant", "//internal/versions", "//internal/versions/components", "//operators/constellation-node-operator/api/v1alpha1", @@ -46,12 +46,12 @@ go_test( embed = [":kubernetes"], deps = [ "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/compatibility", "//internal/config", "//internal/constants", "//internal/logger", - "//internal/variant", "//internal/versions", "//internal/versions/components", "//operators/constellation-node-operator/api/v1alpha1", diff --git a/cli/internal/kubernetes/upgrade.go b/cli/internal/kubernetes/upgrade.go index 68ac42d87..9c3db1416 100644 --- a/cli/internal/kubernetes/upgrade.go +++ b/cli/internal/kubernetes/upgrade.go @@ -21,6 +21,7 @@ import ( "github.com/edgelesssys/constellation/v2/cli/internal/upgrade" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config" @@ -29,7 +30,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/imagefetcher" internalk8s "github.com/edgelesssys/constellation/v2/internal/kubernetes" "github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1" diff --git a/cli/internal/kubernetes/upgrade_test.go b/cli/internal/kubernetes/upgrade_test.go index af068803a..cbd7e10b5 100644 --- a/cli/internal/kubernetes/upgrade_test.go +++ b/cli/internal/kubernetes/upgrade_test.go @@ -14,12 +14,12 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components" updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1" diff --git a/cli/internal/terraform/terraform/aws/main.tf b/cli/internal/terraform/terraform/aws/main.tf index b7d24bc1a..3403acc57 100644 --- a/cli/internal/terraform/terraform/aws/main.tf +++ b/cli/internal/terraform/terraform/aws/main.tf @@ -237,6 +237,7 @@ module "instance_group_control_plane" { security_groups = [aws_security_group.security_group.id] subnetwork = module.public_private_subnet.private_subnet_id iam_instance_profile = var.iam_instance_profile_control_plane + enable_snp = var.enable_snp tags = merge( local.tags, { Name = local.name }, @@ -261,6 +262,7 @@ module "instance_group_worker_nodes" { target_group_arns = [] security_groups = [aws_security_group.security_group.id] iam_instance_profile = var.iam_instance_profile_worker_nodes + enable_snp = var.enable_snp tags = merge( local.tags, { Name = local.name }, diff --git a/cli/internal/terraform/terraform/aws/modules/instance_group/main.tf b/cli/internal/terraform/terraform/aws/modules/instance_group/main.tf index 354b54653..a4517b96f 100644 --- a/cli/internal/terraform/terraform/aws/modules/instance_group/main.tf +++ b/cli/internal/terraform/terraform/aws/modules/instance_group/main.tf @@ -44,6 +44,11 @@ resource "aws_launch_template" "launch_template" { image_id, # required. update procedure modifies the image id externally ] } + + # See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template#cpu-options + cpu_options { + amd_sev_snp = var.enable_snp ? "enabled" : "disabled" + } } resource "aws_autoscaling_group" "autoscaling_group" { diff --git a/cli/internal/terraform/terraform/aws/modules/instance_group/variables.tf b/cli/internal/terraform/terraform/aws/modules/instance_group/variables.tf index 444265f48..266446841 100644 --- a/cli/internal/terraform/terraform/aws/modules/instance_group/variables.tf +++ b/cli/internal/terraform/terraform/aws/modules/instance_group/variables.tf @@ -62,3 +62,9 @@ variable "tags" { type = map(string) description = "The tags to add to the instance group." } + +variable "enable_snp" { + type = bool + default = true + description = "Enable AMD SEV SNP. Setting this to true sets the cpu-option AmdSevSnp to enable." +} diff --git a/cli/internal/terraform/terraform/aws/variables.tf b/cli/internal/terraform/terraform/aws/variables.tf index 6f8588873..e14b994f9 100644 --- a/cli/internal/terraform/terraform/aws/variables.tf +++ b/cli/internal/terraform/terraform/aws/variables.tf @@ -69,3 +69,9 @@ variable "debug" { default = false description = "Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." } + +variable "enable_snp" { + type = bool + default = true + description = "Enable AMD SEV SNP. Setting this to true sets the cpu-option AmdSevSnp to enable." +} diff --git a/cli/internal/terraform/variables.go b/cli/internal/terraform/variables.go index b474295ee..81bfb2af0 100644 --- a/cli/internal/terraform/variables.go +++ b/cli/internal/terraform/variables.go @@ -39,7 +39,7 @@ func (v *CommonVariables) String() string { return b.String() } -// AWSClusterVariables is user configuration for creating a cluster with Terraform on GCP. +// AWSClusterVariables is user configuration for creating a cluster with Terraform on AWS. type AWSClusterVariables struct { // CommonVariables contains common variables. CommonVariables @@ -59,6 +59,8 @@ type AWSClusterVariables struct { IAMProfileWorkerNodes string // Debug is true if debug mode is enabled. Debug bool + // EnableSNP controls enablement of the EC2 cpu-option "AmdSevSnp". + EnableSNP bool } func (v *AWSClusterVariables) String() string { @@ -72,6 +74,7 @@ func (v *AWSClusterVariables) String() string { writeLinef(b, "iam_instance_profile_control_plane = %q", v.IAMProfileControlPlane) writeLinef(b, "iam_instance_profile_worker_nodes = %q", v.IAMProfileWorkerNodes) writeLinef(b, "debug = %t", v.Debug) + writeLinef(b, "enable_snp = %t", v.EnableSNP) return b.String() } diff --git a/disk-mapper/cmd/BUILD.bazel b/disk-mapper/cmd/BUILD.bazel index 0c886620f..6bb99eb8e 100644 --- a/disk-mapper/cmd/BUILD.bazel +++ b/disk-mapper/cmd/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "//disk-mapper/internal/setup", "//internal/attestation/choose", "//internal/attestation/tdx", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/cloud/aws", "//internal/cloud/azure", @@ -26,7 +27,6 @@ go_library( "//internal/kms/setup", "//internal/logger", "//internal/role", - "//internal/variant", "@com_github_spf13_afero//:afero", "@org_uber_go_zap//:zap", ], diff --git a/disk-mapper/cmd/main.go b/disk-mapper/cmd/main.go index 2696a4795..9069412be 100644 --- a/disk-mapper/cmd/main.go +++ b/disk-mapper/cmd/main.go @@ -20,6 +20,7 @@ import ( "github.com/edgelesssys/constellation/v2/disk-mapper/internal/setup" "github.com/edgelesssys/constellation/v2/internal/attestation/choose" "github.com/edgelesssys/constellation/v2/internal/attestation/tdx" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" awscloud "github.com/edgelesssys/constellation/v2/internal/cloud/aws" azurecloud "github.com/edgelesssys/constellation/v2/internal/cloud/azure" @@ -33,7 +34,6 @@ import ( kmssetup "github.com/edgelesssys/constellation/v2/internal/kms/setup" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/role" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "go.uber.org/zap" ) diff --git a/disk-mapper/internal/recoveryserver/BUILD.bazel b/disk-mapper/internal/recoveryserver/BUILD.bazel index efd4a5b3c..ce81e8c39 100644 --- a/disk-mapper/internal/recoveryserver/BUILD.bazel +++ b/disk-mapper/internal/recoveryserver/BUILD.bazel @@ -28,11 +28,11 @@ go_test( deps = [ "//disk-mapper/recoverproto", "//internal/atls", + "//internal/attestation/variant", "//internal/grpc/dialer", "//internal/grpc/testdialer", "//internal/kms/kms", "//internal/logger", - "//internal/variant", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", "@org_uber_go_goleak//:goleak", diff --git a/disk-mapper/internal/recoveryserver/recoveryserver_test.go b/disk-mapper/internal/recoveryserver/recoveryserver_test.go index 386770080..4673c1137 100644 --- a/disk-mapper/internal/recoveryserver/recoveryserver_test.go +++ b/disk-mapper/internal/recoveryserver/recoveryserver_test.go @@ -15,11 +15,11 @@ import ( "github.com/edgelesssys/constellation/v2/disk-mapper/recoverproto" "github.com/edgelesssys/constellation/v2/internal/atls" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/grpc/dialer" "github.com/edgelesssys/constellation/v2/internal/grpc/testdialer" "github.com/edgelesssys/constellation/v2/internal/kms/kms" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" diff --git a/docs/docs/reference/cli.md b/docs/docs/reference/cli.md index a6698eadd..c8322273d 100644 --- a/docs/docs/reference/cli.md +++ b/docs/docs/reference/cli.md @@ -75,7 +75,7 @@ constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags] ### Options ``` - -a, --attestation string attestation variant to use {aws-nitro-tpm|azure-sev-snp|azure-trustedlaunch|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used + -a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-trustedlaunch|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used -f, --file string path to output file, or '-' for stdout (default "constellation-conf.yaml") -h, --help help for generate -k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.26") diff --git a/e2e/internal/upgrade/BUILD.bazel b/e2e/internal/upgrade/BUILD.bazel index f0c3c897b..a86eab72f 100644 --- a/e2e/internal/upgrade/BUILD.bazel +++ b/e2e/internal/upgrade/BUILD.bazel @@ -13,11 +13,11 @@ go_library( deps = [ "//internal/api/versionsapi", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/constants", "//internal/imagefetcher", "//internal/logger", - "//internal/variant", "@sh_helm_helm_v3//pkg/action", "@sh_helm_helm_v3//pkg/cli", ], diff --git a/e2e/internal/upgrade/image.go b/e2e/internal/upgrade/image.go index 3fe0c4884..b6330eb13 100644 --- a/e2e/internal/upgrade/image.go +++ b/e2e/internal/upgrade/image.go @@ -14,9 +14,9 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/imagefetcher" - "github.com/edgelesssys/constellation/v2/internal/variant" ) type upgradeInfo struct { diff --git a/internal/api/attestationconfig/BUILD.bazel b/internal/api/attestationconfig/BUILD.bazel new file mode 100644 index 000000000..e69de29bb diff --git a/internal/api/attestationconfig/client/BUILD.bazel b/internal/api/attestationconfig/client/BUILD.bazel new file mode 100644 index 000000000..e69de29bb diff --git a/internal/api/attestationconfigapi/BUILD.bazel b/internal/api/attestationconfigapi/BUILD.bazel index ec6f55fe4..145ff6461 100644 --- a/internal/api/attestationconfigapi/BUILD.bazel +++ b/internal/api/attestationconfigapi/BUILD.bazel @@ -14,11 +14,11 @@ go_library( deps = [ "//internal/api/client", "//internal/api/fetcher", + "//internal/attestation/variant", "//internal/constants", "//internal/logger", "//internal/sigstore", "//internal/staticupload", - "//internal/variant", ], ) diff --git a/internal/api/attestationconfigapi/azure.go b/internal/api/attestationconfigapi/azure.go index a350ceffd..e8e109ee7 100644 --- a/internal/api/attestationconfigapi/azure.go +++ b/internal/api/attestationconfigapi/azure.go @@ -13,8 +13,8 @@ import ( "sort" "strings" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/constants" - "github.com/edgelesssys/constellation/v2/internal/variant" ) // attestationURLPath is the URL path to the attestation versions. diff --git a/internal/api/attestationconfigapi/client.go b/internal/api/attestationconfigapi/client.go index 98f8c01a8..136da1cbd 100644 --- a/internal/api/attestationconfigapi/client.go +++ b/internal/api/attestationconfigapi/client.go @@ -12,10 +12,10 @@ import ( "time" apiclient "github.com/edgelesssys/constellation/v2/internal/api/client" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/edgelesssys/constellation/v2/internal/staticupload" - "github.com/edgelesssys/constellation/v2/internal/variant" ) // Client manages (modifies) the version information for the attestation variants. diff --git a/internal/atls/BUILD.bazel b/internal/atls/BUILD.bazel index d345dab71..6133ee5ac 100644 --- a/internal/atls/BUILD.bazel +++ b/internal/atls/BUILD.bazel @@ -7,8 +7,8 @@ go_library( importpath = "github.com/edgelesssys/constellation/v2/internal/atls", visibility = ["//:__subpackages__"], deps = [ + "//internal/attestation/variant", "//internal/crypto", - "//internal/variant", ], ) @@ -17,7 +17,7 @@ go_test( srcs = ["atls_test.go"], embed = [":atls"], deps = [ - "//internal/variant", + "//internal/attestation/variant", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", "@org_uber_go_goleak//:goleak", diff --git a/internal/atls/README.md b/internal/atls/README.md index 24a52f364..760aa684e 100644 --- a/internal/atls/README.md +++ b/internal/atls/README.md @@ -12,7 +12,7 @@ The protocol can be used by clients to verify a server certificate, by a server 1. The client sends a ClientHello message, setting ServerName to a random nonce. 2. The server generates an attestation statement using the clients nonce and its CC capabilities. - * The attestation is embedded in the server certificate using x509 certificate extensions with an object identifier (OID) to identify the CC attestation type. Take a look at the [`variant`](../variant/variant.go) package for implementation details. + * The attestation is embedded in the server certificate using x509 certificate extensions with an object identifier (OID) to identify the CC attestation type. Take a look at the [`variant`](../attestation/variant/variant.go) package for implementation details. 3. The client verifies the attestation statement. diff --git a/internal/atls/atls.go b/internal/atls/atls.go index 12521c705..06fc38cb0 100644 --- a/internal/atls/atls.go +++ b/internal/atls/atls.go @@ -25,8 +25,8 @@ import ( "math/big" "time" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/crypto" - "github.com/edgelesssys/constellation/v2/internal/variant" ) const attestationTimeout = 30 * time.Second diff --git a/internal/atls/atls_test.go b/internal/atls/atls_test.go index 7f78f2745..063304fcf 100644 --- a/internal/atls/atls_test.go +++ b/internal/atls/atls_test.go @@ -15,7 +15,7 @@ import ( "net/http/httptest" "testing" - "github.com/edgelesssys/constellation/v2/internal/variant" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" diff --git a/internal/attestation/aws/BUILD.bazel b/internal/attestation/aws/BUILD.bazel index 730e93615..cc4f8f272 100644 --- a/internal/attestation/aws/BUILD.bazel +++ b/internal/attestation/aws/BUILD.bazel @@ -1,51 +1,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("//bazel/go:go_test.bzl", "go_test") go_library( name = "aws", - srcs = [ - "aws.go", - "issuer.go", - "validator.go", - ], + srcs = ["aws.go"], importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws", visibility = ["//:__subpackages__"], - deps = [ - "//internal/attestation", - "//internal/attestation/vtpm", - "//internal/config", - "//internal/variant", - "@com_github_aws_aws_sdk_go_v2_config//:config", - "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", - "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", - "@com_github_google_go_tpm//tpm2", - "@com_github_google_go_tpm_tools//client", - "@com_github_google_go_tpm_tools//proto/attest", - ], -) - -go_test( - name = "aws_test", - srcs = [ - "issuer_test.go", - "validator_test.go", - ], - embed = [":aws"], - # keep - gotags = select({ - "//bazel/settings:tpm_simulator_enabled": [], - "//conditions:default": ["disable_tpm_simulator"], - }), - deps = [ - "//internal/attestation/simulator", - "//internal/attestation/vtpm", - "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", - "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", - "@com_github_aws_aws_sdk_go_v2_service_ec2//types", - "@com_github_aws_smithy_go//middleware", - "@com_github_google_go_tpm_tools//client", - "@com_github_google_go_tpm_tools//proto/attest", - "@com_github_stretchr_testify//assert", - "@com_github_stretchr_testify//require", - ], ) diff --git a/internal/attestation/aws/aws.go b/internal/attestation/aws/aws.go index de73ed99c..80806eccd 100644 --- a/internal/attestation/aws/aws.go +++ b/internal/attestation/aws/aws.go @@ -7,24 +7,17 @@ SPDX-License-Identifier: AGPL-3.0-only /* # Amazon Web Services attestation -Attestation for AWS using [NitroTPM]. +Constellation supports multiple attestation technologies on AWS. -AWS currently does not support confidential VMs, but offers a TPM 2.0 compliant vTPM integration. -We use this to enable a TPM based measured boot Constellation deployment. + - SEV - Secure Nested Paging (SEV-SNP) -# Issuer + TPM attestation verified using an SEV-SNP attestation statement. + The TPM runs outside the confidential context. + The initial firmware measurement included in the SNP report can be calculated idependently. + The source code of the firmware is publicly available. -The TPM attestation is signed by the NitroTPM's RSA attestation key. -Additionally to the TPM attestation, we attach a node's [instance identity document] to the attestation document. + - NitroTPM -# Validator - -Currently, the NitroTPM provides no endorsement certificate for its attestation key, nor does AWS offer a secondary of of verifying it. -For now we have to blindly trust the key. - -Additionally to verifying the TPM attestation, we also check the instance identity document for consistency. - -[NitroTPM]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html -[instance identity document]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html + No confidential computing. Attestation via a TPM 2.0 compliant vTPM. */ package aws diff --git a/internal/attestation/aws/nitrotpm/BUILD.bazel b/internal/attestation/aws/nitrotpm/BUILD.bazel new file mode 100644 index 000000000..3e1a292dc --- /dev/null +++ b/internal/attestation/aws/nitrotpm/BUILD.bazel @@ -0,0 +1,72 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("//bazel/go:go_test.bzl", "go_test") + +go_library( + name = "nitrotpm", + srcs = [ + "issuer.go", + "nitrotpm.go", + "validator.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws/nitrotpm", + visibility = ["//:__subpackages__"], + deps = [ + "//internal/attestation", + "//internal/attestation/variant", + "//internal/attestation/vtpm", + "//internal/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_service_ec2//:ec2", + "@com_github_google_go_tpm//tpm2", + "@com_github_google_go_tpm_tools//client", + "@com_github_google_go_tpm_tools//proto/attest", + ], +) + +go_test( + name = "nitro_test", + srcs = [ + "issuer_test.go", + "validator_test.go", + ], + embed = [":nitrotpm"], + # keep + gotags = select({ + "//bazel/settings:tpm_simulator_enabled": [], + "//conditions:default": ["disable_tpm_simulator"], + }), + deps = [ + "//internal/attestation/simulator", + "//internal/attestation/vtpm", + "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", + "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", + "@com_github_aws_aws_sdk_go_v2_service_ec2//types", + "@com_github_aws_smithy_go//middleware", + "@com_github_google_go_tpm_tools//client", + "@com_github_google_go_tpm_tools//proto/attest", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) + +go_test( + name = "nitrotpm_test", + srcs = [ + "issuer_test.go", + "validator_test.go", + ], + embed = [":nitrotpm"], + deps = [ + "//internal/attestation/simulator", + "//internal/attestation/vtpm", + "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", + "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", + "@com_github_aws_aws_sdk_go_v2_service_ec2//types", + "@com_github_aws_smithy_go//middleware", + "@com_github_google_go_tpm_tools//client", + "@com_github_google_go_tpm_tools//proto/attest", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) diff --git a/internal/attestation/aws/issuer.go b/internal/attestation/aws/nitrotpm/issuer.go similarity index 77% rename from internal/attestation/aws/issuer.go rename to internal/attestation/aws/nitrotpm/issuer.go index ae8f51200..e95b72d06 100644 --- a/internal/attestation/aws/issuer.go +++ b/internal/attestation/aws/nitrotpm/issuer.go @@ -4,19 +4,18 @@ Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ -package aws +package nitrotpm import ( "context" "encoding/json" - "errors" + "fmt" "io" - "log" "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/client" tpmclient "github.com/google/go-tpm-tools/client" @@ -28,7 +27,7 @@ type Issuer struct { *vtpm.Issuer } -// NewIssuer creates a new OpenVTPM based issuer for AWS. +// NewIssuer creates a TPM based issuer for AWS. func NewIssuer(log attestation.Logger) *Issuer { return &Issuer{ Issuer: vtpm.NewIssuer( @@ -44,8 +43,7 @@ func NewIssuer(log attestation.Logger) *Issuer { func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) { tpmAk, err := client.AttestationKeyRSA(tpm) if err != nil { - log.Fatalf("error creating RSA Endorsement key!") - return nil, err + return nil, fmt.Errorf("error creating RSA Endorsement key: %w", err) } return tpmAk, nil @@ -54,10 +52,10 @@ func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) { // getInstanceInfo returns information about the current instance using the aws Metadata SDK. // The returned bytes will be written into the attestation document. func getInstanceInfo(client awsMetaData) func(context.Context, io.ReadWriteCloser, []byte) ([]byte, error) { - return func(context.Context, io.ReadWriteCloser, []byte) ([]byte, error) { - ec2InstanceIdentityOutput, err := client.GetInstanceIdentityDocument(context.Background(), &imds.GetInstanceIdentityDocumentInput{}) + return func(ctx context.Context, _ io.ReadWriteCloser, _ []byte) ([]byte, error) { + ec2InstanceIdentityOutput, err := client.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}) if err != nil { - return nil, errors.New("unable to fetch instance identity document") + return nil, fmt.Errorf("fetching instance identity document: %w", err) } return json.Marshal(ec2InstanceIdentityOutput.InstanceIdentityDocument) } diff --git a/internal/attestation/aws/nitrotpm/issuer_test.go b/internal/attestation/aws/nitrotpm/issuer_test.go new file mode 100644 index 000000000..d1a00439d --- /dev/null +++ b/internal/attestation/aws/nitrotpm/issuer_test.go @@ -0,0 +1,118 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package nitrotpm + +import ( + "context" + "errors" + "testing" + + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + "github.com/aws/smithy-go/middleware" + "github.com/edgelesssys/constellation/v2/internal/attestation/simulator" + tpmclient "github.com/google/go-tpm-tools/client" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetAttestationKey(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + + tpm, err := simulator.OpenSimulatedTPM() + require.NoError(err) + defer tpm.Close() + + // create the attestation ket in RSA format + tpmAk, err := tpmclient.AttestationKeyRSA(tpm) + assert.NoError(err) + assert.NotNil(tpmAk) + + // get the cached, already created key + getAk, err := getAttestationKey(tpm) + assert.NoError(err) + assert.NotNil(getAk) + + // if everything worked fine, tpmAk and getAk are the same key + assert.Equal(tpmAk, getAk) +} + +func TestGetInstanceInfo(t *testing.T) { + testCases := map[string]struct { + client stubMetadataAPI + wantErr bool + }{ + "invalid region": { + client: stubMetadataAPI{ + instanceDoc: imds.InstanceIdentityDocument{ + Region: "invalid-region", + }, + instanceErr: errors.New("failed"), + }, + wantErr: true, + }, + "valid region": { + client: stubMetadataAPI{ + instanceDoc: imds.InstanceIdentityDocument{ + Region: "us-east-2", + }, + }, + }, + "invalid imageID": { + client: stubMetadataAPI{ + instanceDoc: imds.InstanceIdentityDocument{ + ImageID: "ami-fail", + }, + instanceErr: errors.New("failed"), + }, + wantErr: true, + }, + "valid imageID": { + client: stubMetadataAPI{ + instanceDoc: imds.InstanceIdentityDocument{ + ImageID: "ami-09e7c7f5617a47830", + }, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + + tpm, err := simulator.OpenSimulatedTPM() + assert.NoError(err) + defer tpm.Close() + + instanceInfoFunc := getInstanceInfo(&tc.client) + assert.NotNil(instanceInfoFunc) + + info, err := instanceInfoFunc(context.Background(), tpm, nil) + if tc.wantErr { + assert.Error(err) + assert.Nil(info) + } else { + assert.Nil(err) + assert.NotNil(info) + } + }) + } +} + +type stubMetadataAPI struct { + instanceDoc imds.InstanceIdentityDocument + instanceErr error +} + +func (c *stubMetadataAPI) GetInstanceIdentityDocument(context.Context, *imds.GetInstanceIdentityDocumentInput, ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) { + output := &imds.InstanceIdentityDocument{} + + return &imds.GetInstanceIdentityDocumentOutput{ + InstanceIdentityDocument: *output, + ResultMetadata: middleware.Metadata{}, + }, c.instanceErr +} diff --git a/internal/attestation/aws/nitrotpm/nitrotpm.go b/internal/attestation/aws/nitrotpm/nitrotpm.go new file mode 100644 index 000000000..47c59db9b --- /dev/null +++ b/internal/attestation/aws/nitrotpm/nitrotpm.go @@ -0,0 +1,29 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +/* +# NitroTPM Attestation. + +Uses NitroTPM to enable a TPM based measured boot Constellation deployment. +The origin of the attesation statement can not be verified. + +# Issuer + +The TPM attestation is signed by the NitroTPM's RSA attestation key. +Additionally to the TPM attestation, we attach a node's [instance identity document] to the attestation document. + +# Validator + +Currently, the NitroTPM provides no endorsement certificate for its attestation key, nor does AWS offer an alternative way of verifying it. +For now we have to blindly trust the key. + +Additionally to verifying the TPM attestation, we also check the instance identity document for consistency. + +[instance identity document]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html + +[NitroTPM]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html +*/ +package nitrotpm diff --git a/internal/attestation/aws/validator.go b/internal/attestation/aws/nitrotpm/validator.go similarity index 97% rename from internal/attestation/aws/validator.go rename to internal/attestation/aws/nitrotpm/validator.go index 28c162820..40dd9523c 100644 --- a/internal/attestation/aws/validator.go +++ b/internal/attestation/aws/nitrotpm/validator.go @@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ -package aws +package nitrotpm import ( "context" @@ -16,9 +16,9 @@ import ( "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm/tpm2" ) diff --git a/internal/attestation/aws/nitrotpm/validator_test.go b/internal/attestation/aws/nitrotpm/validator_test.go new file mode 100644 index 000000000..0e6d086cd --- /dev/null +++ b/internal/attestation/aws/nitrotpm/validator_test.go @@ -0,0 +1,146 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package nitrotpm + +import ( + "context" + "encoding/json" + "errors" + "testing" + + "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/types" + "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" + "github.com/google/go-tpm-tools/proto/attest" + "github.com/stretchr/testify/assert" +) + +func TestGeTrustedKey(t *testing.T) { + testCases := map[string]struct { + akPub []byte + info []byte + wantErr bool + }{ + "nul byte docs": { + akPub: []byte{0x00, 0x00, 0x00, 0x00}, + info: []byte{0x00, 0x00, 0x00, 0x00}, + wantErr: true, + }, + "nil": { + akPub: nil, + info: nil, + wantErr: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + out, err := getTrustedKey( + context.Background(), + vtpm.AttestationDocument{ + Attestation: &attest.Attestation{ + AkPub: tc.akPub, + }, + InstanceInfo: tc.info, + }, + nil, + ) + + if tc.wantErr { + assert.Error(err) + } else { + assert.NoError(err) + } + + assert.Nil(out) + }) + } +} + +func TestTpmEnabled(t *testing.T) { + idDocNoTPM := imds.InstanceIdentityDocument{ + ImageID: "ami-tpm-disabled", + } + userDataNoTPM, _ := json.Marshal(idDocNoTPM) + attDocNoTPM := vtpm.AttestationDocument{ + InstanceInfo: userDataNoTPM, + } + + idDocTPM := imds.InstanceIdentityDocument{ + ImageID: "ami-tpm-enabled", + } + userDataTPM, _ := json.Marshal(idDocTPM) + attDocTPM := vtpm.AttestationDocument{ + InstanceInfo: userDataTPM, + } + + testCases := map[string]struct { + attDoc vtpm.AttestationDocument + awsAPI awsMetadataAPI + wantErr bool + }{ + "ami with tpm": { + attDoc: attDocNoTPM, + awsAPI: &stubDescribeAPI{describeImagesTPMSupport: "v2.0"}, + }, + "ami without tpm": { + attDoc: attDocTPM, + awsAPI: &stubDescribeAPI{describeImagesTPMSupport: "v1.0"}, + wantErr: true, + }, + "ami undefined": { + attDoc: vtpm.AttestationDocument{}, + awsAPI: &stubDescribeAPI{describeImagesErr: errors.New("failed")}, + wantErr: true, + }, + "invalid json instanceIdentityDocument": { + attDoc: vtpm.AttestationDocument{ + UserData: []byte("{invalid}"), + }, + awsAPI: &stubDescribeAPI{describeImagesErr: errors.New("failed")}, + wantErr: true, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + assert := assert.New(t) + + v := Validator{ + getDescribeClient: func(context.Context, string) (awsMetadataAPI, error) { + return tc.awsAPI, nil + }, + } + + err := v.tpmEnabled(tc.attDoc, nil) + if tc.wantErr { + assert.Error(err) + } else { + assert.Nil(err) + } + }) + } +} + +type stubDescribeAPI struct { + describeImagesErr error + describeImagesTPMSupport string +} + +func (a *stubDescribeAPI) DescribeImages( + _ context.Context, _ *ec2.DescribeImagesInput, _ ...func(*ec2.Options), +) (*ec2.DescribeImagesOutput, error) { + output := &ec2.DescribeImagesOutput{ + Images: []types.Image{ + {TpmSupport: types.TpmSupportValues(a.describeImagesTPMSupport)}, + }, + } + + return output, a.describeImagesErr +} diff --git a/internal/attestation/aws/snp/BUILD.bazel b/internal/attestation/aws/snp/BUILD.bazel new file mode 100644 index 000000000..959be7151 --- /dev/null +++ b/internal/attestation/aws/snp/BUILD.bazel @@ -0,0 +1,51 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("//bazel/go:go_test.bzl", "go_test") + +go_library( + name = "snp", + srcs = [ + "issuer.go", + "snp.go", + "validator.go", + ], + importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/aws/snp", + visibility = ["//:__subpackages__"], + deps = [ + "//internal/attestation", + "//internal/attestation/variant", + "//internal/attestation/vtpm", + "//internal/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_service_ec2//:ec2", + "@com_github_google_go_tpm//tpm2", + "@com_github_google_go_tpm_tools//client", + "@com_github_google_go_tpm_tools//proto/attest", + ], +) + +go_test( + name = "snp_test", + srcs = [ + "issuer_test.go", + "validator_test.go", + ], + embed = [":snp"], + # keep + gotags = select({ + "//bazel/settings:tpm_simulator_enabled": [], + "//conditions:default": ["disable_tpm_simulator"], + }), + deps = [ + "//internal/attestation/simulator", + "//internal/attestation/vtpm", + "@com_github_aws_aws_sdk_go_v2_feature_ec2_imds//:imds", + "@com_github_aws_aws_sdk_go_v2_service_ec2//:ec2", + "@com_github_aws_aws_sdk_go_v2_service_ec2//types", + "@com_github_aws_smithy_go//middleware", + "@com_github_google_go_tpm_tools//client", + "@com_github_google_go_tpm_tools//proto/attest", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) diff --git a/internal/attestation/aws/snp/issuer.go b/internal/attestation/aws/snp/issuer.go new file mode 100644 index 000000000..067b309b5 --- /dev/null +++ b/internal/attestation/aws/snp/issuer.go @@ -0,0 +1,66 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package snp + +import ( + "context" + "encoding/json" + "fmt" + "io" + + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" + + "github.com/google/go-tpm-tools/client" + tpmclient "github.com/google/go-tpm-tools/client" +) + +// Issuer for AWS SNP attestation. +type Issuer struct { + variant.AWSSEVSNP + *vtpm.Issuer +} + +// NewIssuer creates a SEV-SNP based issuer for AWS. +func NewIssuer(log attestation.Logger) *Issuer { + return &Issuer{ + Issuer: vtpm.NewIssuer( + vtpm.OpenVTPM, + getAttestationKey, + getInstanceInfo(imds.New(imds.Options{})), + log, + ), + } +} + +// getAttestationKey returns a new attestation key. +func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) { + tpmAk, err := client.AttestationKeyRSA(tpm) + if err != nil { + return nil, fmt.Errorf("error creating RSA Endorsement key: %w", err) + } + + return tpmAk, nil +} + +// getInstanceInfo returns information about the current instance using the aws Metadata SDK. +// The returned bytes will be written into the attestation document. +func getInstanceInfo(client awsMetaData) func(context.Context, io.ReadWriteCloser, []byte) ([]byte, error) { + return func(ctx context.Context, _ io.ReadWriteCloser, _ []byte) ([]byte, error) { + ec2InstanceIdentityOutput, err := client.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}) + if err != nil { + return nil, fmt.Errorf("fetching instance identity document: %w", err) + } + return json.Marshal(ec2InstanceIdentityOutput.InstanceIdentityDocument) + } +} + +type awsMetaData interface { + GetInstanceIdentityDocument(context.Context, *imds.GetInstanceIdentityDocumentInput, ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) +} diff --git a/internal/attestation/aws/issuer_test.go b/internal/attestation/aws/snp/issuer_test.go similarity index 99% rename from internal/attestation/aws/issuer_test.go rename to internal/attestation/aws/snp/issuer_test.go index 07884e81c..29d17b5e1 100644 --- a/internal/attestation/aws/issuer_test.go +++ b/internal/attestation/aws/snp/issuer_test.go @@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ -package aws +package snp import ( "context" diff --git a/internal/attestation/aws/snp/snp.go b/internal/attestation/aws/snp/snp.go new file mode 100644 index 000000000..4085f50bb --- /dev/null +++ b/internal/attestation/aws/snp/snp.go @@ -0,0 +1,52 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +/* +--------- WARNING! --------- + +THIS PACKAGE DOES CURRENTLY NOT IMPLEMENT ANY SNP ATTESTATION. +It exists to implement required interfaces while implementing other parts of the AWS SNP attestation variant within Constellation. + +---------------------------- + +# SNP + +Attestation based on TPMs and AMD SEV-SNP. +The TPM is used to generate runtime measurements and sign them with an attestation key. +The TPM currently runs outside the confidential context. This is a limitation imposed by the AWS implementation. + +# Issuer + +Generates a TPM attestation using an attestation key saved inside the TPM. +Additionally loads the SEV-SNP attestation report and AMD VLEK certificate chain, and adds them to the attestation document. +The SNP report includes a measurement of the initial firmware inside the CVM, which can be precalculated independently for verification. +The report also includes the attestation key. + +# Validator + +Verifies the SNP report by verifying the VLEK certificate chain and the report's signature. +This estabilishes trust in the attestation key and the CVM's initial firmware. +However, since the TPM is outside the confidential context, it has to be trusted without verification. +Thus, the hypervisor is still included in the trusted computing base. + +# Glossary + +This section explains abbreviations used in SNP implementation. + + - Attestation Key (AK) + + - AMD Root Key (ARK) + + - AMD Signing Key (ASK) + + - Versioned Chip Endorsement Key (VCEK) + + - Versioned Loaded Endorsement Key (VLEK) + For more information see [SNP WhitePaper] + +[SNP WhitePaper]: https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf +*/ +package snp diff --git a/internal/attestation/aws/snp/validator.go b/internal/attestation/aws/snp/validator.go new file mode 100644 index 000000000..d1db3dfae --- /dev/null +++ b/internal/attestation/aws/snp/validator.go @@ -0,0 +1,101 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package snp + +import ( + "context" + "crypto" + "encoding/json" + "fmt" + + awsConfig "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" + "github.com/edgelesssys/constellation/v2/internal/config" + "github.com/google/go-tpm-tools/proto/attest" + "github.com/google/go-tpm/tpm2" +) + +// Validator for AWS TPM attestation. +type Validator struct { + variant.AWSSEVSNP + *vtpm.Validator + getDescribeClient func(context.Context, string) (awsMetadataAPI, error) +} + +// NewValidator create a new Validator structure and returns it. +func NewValidator(cfg *config.AWSSEVSNP, log attestation.Logger) *Validator { + v := &Validator{} + v.Validator = vtpm.NewValidator( + cfg.Measurements, + getTrustedKey, + v.tpmEnabled, + log, + ) + v.getDescribeClient = getEC2Client + return v +} + +// getTrustedKeys return the public area of the provides attestation key. +// Normally, here the trust of this key should be verified, but currently AWS does not provide this feature. +func getTrustedKey(_ context.Context, attDoc vtpm.AttestationDocument, _ []byte) (crypto.PublicKey, error) { + // Copied from https://github.com/edgelesssys/constellation/blob/main/internal/attestation/qemu/validator.go + pubArea, err := tpm2.DecodePublic(attDoc.Attestation.AkPub) + if err != nil { + return nil, err + } + + return pubArea.Key() +} + +// tpmEnabled verifies if the virtual machine has the tpm2.0 feature enabled. +func (v *Validator) tpmEnabled(attestation vtpm.AttestationDocument, _ *attest.MachineState) error { + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/verify-nitrotpm-support-on-ami.html + // 1. Get the vm's ami (from IdentiTyDocument.imageId) + // 2. Check the value of key "TpmSupport": {"Value": "v2.0"}" + ctx := context.Background() + + idDocument := imds.InstanceIdentityDocument{} + err := json.Unmarshal(attestation.InstanceInfo, &idDocument) + if err != nil { + return err + } + + imageID := idDocument.ImageID + + client, err := v.getDescribeClient(ctx, idDocument.Region) + if err != nil { + return err + } + // Currently, there seems to be a problem with retrieving image attributes directly. + // Alternatively, parse it from the general output. + imageOutput, err := client.DescribeImages(ctx, &ec2.DescribeImagesInput{ImageIds: []string{imageID}}) + if err != nil { + return err + } + + if imageOutput.Images[0].TpmSupport == "v2.0" { + return nil + } + + return fmt.Errorf("iam image %s does not support TPM v2.0", imageID) +} + +func getEC2Client(ctx context.Context, region string) (awsMetadataAPI, error) { + client, err := awsConfig.LoadDefaultConfig(ctx, awsConfig.WithRegion(region)) + if err != nil { + return nil, err + } + return ec2.NewFromConfig(client), nil +} + +type awsMetadataAPI interface { + DescribeImages(ctx context.Context, params *ec2.DescribeImagesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error) +} diff --git a/internal/attestation/aws/validator_test.go b/internal/attestation/aws/snp/validator_test.go similarity index 99% rename from internal/attestation/aws/validator_test.go rename to internal/attestation/aws/snp/validator_test.go index 0ee5d2032..0eeb826e3 100644 --- a/internal/attestation/aws/validator_test.go +++ b/internal/attestation/aws/snp/validator_test.go @@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH SPDX-License-Identifier: AGPL-3.0-only */ -package aws +package snp import ( "context" diff --git a/internal/attestation/azure/snp/BUILD.bazel b/internal/attestation/azure/snp/BUILD.bazel index 90769735e..b67c9555f 100644 --- a/internal/attestation/azure/snp/BUILD.bazel +++ b/internal/attestation/azure/snp/BUILD.bazel @@ -16,11 +16,11 @@ go_library( deps = [ "//internal/attestation", "//internal/attestation/idkeydigest", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/cloud/azure", "//internal/config", "//internal/crypto", - "//internal/variant", "@com_github_edgelesssys_go_azguestattestation//maa", "@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm_tools//client", diff --git a/internal/attestation/azure/snp/issuer.go b/internal/attestation/azure/snp/issuer.go index 38b4855be..418d823ad 100644 --- a/internal/attestation/azure/snp/issuer.go +++ b/internal/attestation/azure/snp/issuer.go @@ -13,8 +13,8 @@ import ( "io" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/go-azguestattestation/maa" tpmclient "github.com/google/go-tpm-tools/client" ) diff --git a/internal/attestation/azure/snp/validator.go b/internal/attestation/azure/snp/validator.go index 40a40d15e..cfbc50403 100644 --- a/internal/attestation/azure/snp/validator.go +++ b/internal/attestation/azure/snp/validator.go @@ -22,10 +22,10 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/config" internalCrypto "github.com/edgelesssys/constellation/v2/internal/crypto" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm/tpm2" ) diff --git a/internal/attestation/azure/trustedlaunch/BUILD.bazel b/internal/attestation/azure/trustedlaunch/BUILD.bazel index ae4621941..805c05a92 100644 --- a/internal/attestation/azure/trustedlaunch/BUILD.bazel +++ b/internal/attestation/azure/trustedlaunch/BUILD.bazel @@ -12,10 +12,10 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "//internal/attestation", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/config", "//internal/crypto", - "//internal/variant", "@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm_tools//client", "@com_github_google_go_tpm_tools//proto/attest", diff --git a/internal/attestation/azure/trustedlaunch/issuer.go b/internal/attestation/azure/trustedlaunch/issuer.go index d848c3451..fda489ec2 100644 --- a/internal/attestation/azure/trustedlaunch/issuer.go +++ b/internal/attestation/azure/trustedlaunch/issuer.go @@ -16,8 +16,8 @@ import ( "net/http" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" - "github.com/edgelesssys/constellation/v2/internal/variant" tpmclient "github.com/google/go-tpm-tools/client" "github.com/google/go-tpm/tpm2" ) diff --git a/internal/attestation/azure/trustedlaunch/validator.go b/internal/attestation/azure/trustedlaunch/validator.go index 4ccc9b6d5..c8349954d 100644 --- a/internal/attestation/azure/trustedlaunch/validator.go +++ b/internal/attestation/azure/trustedlaunch/validator.go @@ -16,10 +16,10 @@ import ( "fmt" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/config" certutil "github.com/edgelesssys/constellation/v2/internal/crypto" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm/tpm2" ) diff --git a/internal/attestation/choose/BUILD.bazel b/internal/attestation/choose/BUILD.bazel index 705c52bc4..f57356c50 100644 --- a/internal/attestation/choose/BUILD.bazel +++ b/internal/attestation/choose/BUILD.bazel @@ -9,14 +9,15 @@ go_library( deps = [ "//internal/atls", "//internal/attestation", - "//internal/attestation/aws", + "//internal/attestation/aws/nitrotpm", + "//internal/attestation/aws/snp", "//internal/attestation/azure/snp", "//internal/attestation/azure/trustedlaunch", "//internal/attestation/gcp", "//internal/attestation/qemu", "//internal/attestation/tdx", + "//internal/attestation/variant", "//internal/config", - "//internal/variant", ], ) @@ -26,8 +27,8 @@ go_test( embed = [":choose"], deps = [ "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/config", - "//internal/variant", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", ], diff --git a/internal/attestation/choose/choose.go b/internal/attestation/choose/choose.go index 0a3419ee1..965645b3c 100644 --- a/internal/attestation/choose/choose.go +++ b/internal/attestation/choose/choose.go @@ -11,25 +11,28 @@ import ( "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation" - "github.com/edgelesssys/constellation/v2/internal/attestation/aws" - "github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp" + "github.com/edgelesssys/constellation/v2/internal/attestation/aws/nitrotpm" + awssnp "github.com/edgelesssys/constellation/v2/internal/attestation/aws/snp" + azuresnp "github.com/edgelesssys/constellation/v2/internal/attestation/azure/snp" "github.com/edgelesssys/constellation/v2/internal/attestation/azure/trustedlaunch" "github.com/edgelesssys/constellation/v2/internal/attestation/gcp" "github.com/edgelesssys/constellation/v2/internal/attestation/qemu" "github.com/edgelesssys/constellation/v2/internal/attestation/tdx" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" ) // Issuer returns the issuer for the given variant. func Issuer(attestationVariant variant.Variant, log attestation.Logger) (atls.Issuer, error) { switch attestationVariant { + case variant.AWSSEVSNP{}: + return awssnp.NewIssuer(log), nil case variant.AWSNitroTPM{}: - return aws.NewIssuer(log), nil + return nitrotpm.NewIssuer(log), nil case variant.AzureTrustedLaunch{}: return trustedlaunch.NewIssuer(log), nil case variant.AzureSEVSNP{}: - return snp.NewIssuer(log), nil + return azuresnp.NewIssuer(log), nil case variant.GCPSEVES{}: return gcp.NewIssuer(log), nil case variant.QEMUVTPM{}: @@ -46,12 +49,14 @@ func Issuer(attestationVariant variant.Variant, log attestation.Logger) (atls.Is // Validator returns the validator for the given variant. func Validator(cfg config.AttestationCfg, log attestation.Logger) (atls.Validator, error) { switch cfg := cfg.(type) { + case *config.AWSSEVSNP: + return awssnp.NewValidator(cfg, log), nil case *config.AWSNitroTPM: - return aws.NewValidator(cfg, log), nil + return nitrotpm.NewValidator(cfg, log), nil case *config.AzureTrustedLaunch: return trustedlaunch.NewValidator(cfg, log), nil case *config.AzureSEVSNP: - return snp.NewValidator(cfg, log), nil + return azuresnp.NewValidator(cfg, log), nil case *config.GCPSEVES: return gcp.NewValidator(cfg, log), nil case *config.QEMUVTPM: diff --git a/internal/attestation/choose/choose_test.go b/internal/attestation/choose/choose_test.go index fe61c66df..95d4184fc 100644 --- a/internal/attestation/choose/choose_test.go +++ b/internal/attestation/choose/choose_test.go @@ -11,8 +11,8 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -22,6 +22,9 @@ func TestIssuer(t *testing.T) { variant variant.Variant wantErr bool }{ + "aws-sev-snp": { + variant: variant.AWSSEVSNP{}, + }, "aws-nitro-tpm": { variant: variant.AWSNitroTPM{}, }, diff --git a/internal/attestation/gcp/BUILD.bazel b/internal/attestation/gcp/BUILD.bazel index 299804ddf..7cabb294b 100644 --- a/internal/attestation/gcp/BUILD.bazel +++ b/internal/attestation/gcp/BUILD.bazel @@ -12,9 +12,9 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "//internal/attestation", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/config", - "//internal/variant", "@com_github_google_go_tpm_tools//client", "@com_github_google_go_tpm_tools//proto/attest", "@com_github_googleapis_gax_go_v2//:gax-go", diff --git a/internal/attestation/gcp/issuer.go b/internal/attestation/gcp/issuer.go index 4ea1a66d6..22d9c805a 100644 --- a/internal/attestation/gcp/issuer.go +++ b/internal/attestation/gcp/issuer.go @@ -14,8 +14,8 @@ import ( "cloud.google.com/go/compute/metadata" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" - "github.com/edgelesssys/constellation/v2/internal/variant" tpmclient "github.com/google/go-tpm-tools/client" "github.com/google/go-tpm-tools/proto/attest" ) diff --git a/internal/attestation/gcp/validator.go b/internal/attestation/gcp/validator.go index 43b8d428c..310a33b55 100644 --- a/internal/attestation/gcp/validator.go +++ b/internal/attestation/gcp/validator.go @@ -17,9 +17,9 @@ import ( compute "cloud.google.com/go/compute/apiv1" "cloud.google.com/go/compute/apiv1/computepb" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/proto/attest" "github.com/googleapis/gax-go/v2" "google.golang.org/api/option" diff --git a/internal/attestation/measurements/BUILD.bazel b/internal/attestation/measurements/BUILD.bazel index 7cb3766d7..2de254aa7 100644 --- a/internal/attestation/measurements/BUILD.bazel +++ b/internal/attestation/measurements/BUILD.bazel @@ -14,9 +14,9 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "//internal/api/versionsapi", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/sigstore", - "//internal/variant", "@com_github_google_go_tpm//tpmutil", "@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@in_gopkg_yaml_v3//:yaml_v3", @@ -29,9 +29,9 @@ go_test( embed = [":measurements"], deps = [ "//internal/api/versionsapi", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/sigstore", - "//internal/variant", "@com_github_siderolabs_talos_pkg_machinery//config/encoder", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/internal/attestation/measurements/measurement-generator/BUILD.bazel b/internal/attestation/measurements/measurement-generator/BUILD.bazel index 51d02ca59..80b8aaa28 100644 --- a/internal/attestation/measurements/measurement-generator/BUILD.bazel +++ b/internal/attestation/measurements/measurement-generator/BUILD.bazel @@ -9,9 +9,9 @@ go_library( deps = [ "//internal/api/versionsapi", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/sigstore", - "//internal/variant", "@org_golang_x_tools//go/ast/astutil", ], ) diff --git a/internal/attestation/measurements/measurement-generator/generate.go b/internal/attestation/measurements/measurement-generator/generate.go index e0b6ebec1..670dead4a 100644 --- a/internal/attestation/measurements/measurement-generator/generate.go +++ b/internal/attestation/measurements/measurement-generator/generate.go @@ -25,9 +25,9 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/sigstore" - "github.com/edgelesssys/constellation/v2/internal/variant" "golang.org/x/tools/go/ast/astutil" ) @@ -249,6 +249,8 @@ func attestationVariantFromGoIdentifier(identifier string) (variant.Variant, err switch identifier { case "Dummy": return variant.Dummy{}, nil + case "AWSSEVSNP": + return variant.AWSSEVSNP{}, nil case "AWSNitroTPM": return variant.AWSNitroTPM{}, nil case "GCPSEVES": diff --git a/internal/attestation/measurements/measurements.go b/internal/attestation/measurements/measurements.go index bf8aa1ba7..f3908bf56 100644 --- a/internal/attestation/measurements/measurements.go +++ b/internal/attestation/measurements/measurements.go @@ -27,14 +27,14 @@ import ( "sort" "strconv" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" + "github.com/edgelesssys/constellation/v2/internal/sigstore" "github.com/google/go-tpm/tpmutil" "github.com/siderolabs/talos/pkg/machinery/config/encoder" "gopkg.in/yaml.v3" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" - "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/sigstore" - "github.com/edgelesssys/constellation/v2/internal/variant" ) //go:generate measurement-generator @@ -467,6 +467,9 @@ func DefaultsFor(provider cloudprovider.Provider, attestationVariant variant.Var case provider == cloudprovider.AWS && attestationVariant == variant.AWSNitroTPM{}: return aws_AWSNitroTPM.Copy() + case provider == cloudprovider.AWS && attestationVariant == variant.AWSSEVSNP{}: + return aws_AWSSEVSNP.Copy() + case provider == cloudprovider.Azure && attestationVariant == variant.AzureSEVSNP{}: return azure_AzureSEVSNP.Copy() diff --git a/internal/attestation/measurements/measurements_enterprise.go b/internal/attestation/measurements/measurements_enterprise.go index df7d4d40e..f4d71945e 100644 --- a/internal/attestation/measurements/measurements_enterprise.go +++ b/internal/attestation/measurements/measurements_enterprise.go @@ -17,6 +17,7 @@ package measurements // revive:disable:var-naming var ( aws_AWSNitroTPM = M{0: {Expected: []byte{0x73, 0x7f, 0x76, 0x7a, 0x12, 0xf5, 0x4e, 0x70, 0xee, 0xcb, 0xc8, 0x68, 0x40, 0x11, 0x32, 0x3a, 0xe2, 0xfe, 0x2d, 0xd9, 0xf9, 0x07, 0x85, 0x57, 0x79, 0x69, 0xd7, 0xa2, 0x01, 0x3e, 0x8c, 0x12}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xe0, 0x6b, 0x6d, 0x04, 0x8c, 0x0f, 0x0f, 0x39, 0x66, 0x0f, 0x0b, 0xd5, 0xff, 0xb9, 0xc6, 0xf1, 0x44, 0xf2, 0x05, 0x0b, 0x9d, 0x57, 0xe9, 0xed, 0xb9, 0x63, 0x45, 0x60, 0x20, 0x73, 0x7c, 0x2d}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 7: {Expected: []byte{0x12, 0x0e, 0x49, 0x8d, 0xb2, 0xa2, 0x24, 0xbd, 0x51, 0x2b, 0x6e, 0xfc, 0x9b, 0x02, 0x34, 0xf8, 0x43, 0xe1, 0x0b, 0xf0, 0x61, 0xeb, 0x7a, 0x76, 0xec, 0xca, 0x55, 0x09, 0xa2, 0x23, 0x89, 0x01}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x9e, 0x31, 0x6d, 0x07, 0x03, 0xde, 0xc5, 0x56, 0x30, 0x67, 0x29, 0x42, 0x65, 0x15, 0x07, 0x9e, 0xd9, 0xba, 0x6f, 0x21, 0x8d, 0x65, 0x92, 0xfb, 0xa9, 0x69, 0xd0, 0xca, 0x6f, 0x91, 0x9a, 0x82}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 12: {Expected: []byte{0xda, 0xc1, 0x49, 0x8b, 0x42, 0xd3, 0x77, 0x49, 0x69, 0xba, 0xdd, 0xa8, 0xa0, 0x1a, 0xe4, 0x94, 0xbc, 0x5c, 0x3f, 0x9d, 0x08, 0x09, 0x64, 0xc1, 0x60, 0xff, 0xac, 0x45, 0x17, 0xe6, 0x5e, 0xba}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0xd7, 0xc4, 0xcc, 0x7f, 0xf7, 0x93, 0x30, 0x22, 0xf0, 0x13, 0xe0, 0x3b, 0xde, 0xe8, 0x75, 0xb9, 0x17, 0x20, 0xb5, 0xb8, 0x6c, 0xf1, 0x75, 0x3c, 0xad, 0x83, 0x0f, 0x95, 0xe7, 0x91, 0x92, 0x6f}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} + aws_AWSSEVSNP = M{0: {Expected: []byte{0x73, 0x7f, 0x76, 0x7a, 0x12, 0xf5, 0x4e, 0x70, 0xee, 0xcb, 0xc8, 0x68, 0x40, 0x11, 0x32, 0x3a, 0xe2, 0xfe, 0x2d, 0xd9, 0xf9, 0x07, 0x85, 0x57, 0x79, 0x69, 0xd7, 0xa2, 0x01, 0x3e, 0x8c, 0x12}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xf4, 0xe9, 0x30, 0x3d, 0xf3, 0x34, 0x41, 0x55, 0xdd, 0x14, 0x2d, 0x4d, 0xd8, 0xef, 0xfa, 0x20, 0xf4, 0x21, 0x39, 0x09, 0x9c, 0xc5, 0x2b, 0xca, 0x25, 0xd2, 0x86, 0xe9, 0x26, 0xbd, 0x61, 0x51}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 7: {Expected: []byte{0x12, 0x0e, 0x49, 0x8d, 0xb2, 0xa2, 0x24, 0xbd, 0x51, 0x2b, 0x6e, 0xfc, 0x9b, 0x02, 0x34, 0xf8, 0x43, 0xe1, 0x0b, 0xf0, 0x61, 0xeb, 0x7a, 0x76, 0xec, 0xca, 0x55, 0x09, 0xa2, 0x23, 0x89, 0x01}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x9e, 0x31, 0x6d, 0x07, 0x03, 0xde, 0xc5, 0x56, 0x30, 0x67, 0x29, 0x42, 0x65, 0x15, 0x07, 0x9e, 0xd9, 0xba, 0x6f, 0x21, 0x8d, 0x65, 0x92, 0xfb, 0xa9, 0x69, 0xd0, 0xca, 0x6f, 0x91, 0x9a, 0x82}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 12: {Expected: []byte{0xbb, 0xa3, 0x3c, 0xc6, 0xe8, 0xa9, 0xfd, 0xef, 0xb4, 0x56, 0x8a, 0x04, 0x7d, 0xad, 0x27, 0x96, 0xcc, 0x81, 0x6d, 0x1a, 0x50, 0x57, 0xc5, 0xe7, 0x31, 0xe4, 0x5d, 0xa2, 0x8a, 0x56, 0xf0, 0xfa}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0xd7, 0xc4, 0xcc, 0x7f, 0xf7, 0x93, 0x30, 0x22, 0xf0, 0x13, 0xe0, 0x3b, 0xde, 0xe8, 0x75, 0xb9, 0x17, 0x20, 0xb5, 0xb8, 0x6c, 0xf1, 0x75, 0x3c, 0xad, 0x83, 0x0f, 0x95, 0xe7, 0x91, 0x92, 0x6f}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} azure_AzureSEVSNP = M{1: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0x25, 0xf8, 0x89, 0x54, 0x69, 0xac, 0xbf, 0x28, 0x64, 0x48, 0xe4, 0x80, 0xdc, 0x33, 0x74, 0x80, 0x47, 0xd7, 0x56, 0x75, 0xaa, 0x83, 0x8b, 0xfd, 0x85, 0x58, 0xd4, 0xd7, 0x0c, 0x69, 0x13, 0xb5}, ValidationOpt: Enforce}, 7: {Expected: []byte{0x34, 0x65, 0x47, 0xa8, 0xce, 0x59, 0x57, 0xaf, 0x27, 0xe5, 0x52, 0x42, 0x7d, 0x6b, 0x9e, 0x6d, 0x9c, 0xb5, 0x02, 0xf0, 0x15, 0x6e, 0x91, 0x55, 0x38, 0x04, 0x51, 0xee, 0xa1, 0xb3, 0xf0, 0xed}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x99, 0x35, 0x5b, 0xbe, 0xb0, 0xa6, 0xff, 0x67, 0x6c, 0x51, 0x0a, 0xfb, 0xab, 0xe0, 0x5f, 0x84, 0x26, 0x17, 0x7b, 0xc7, 0xd6, 0x5c, 0xb7, 0xc1, 0xc3, 0xda, 0x8b, 0x00, 0xa2, 0x29, 0x57, 0x54}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 12: {Expected: []byte{0x0f, 0xdb, 0x9d, 0xb0, 0x1a, 0x73, 0x9d, 0xa2, 0x3e, 0xd9, 0xbe, 0x68, 0xff, 0x86, 0xbd, 0x8c, 0xfc, 0x48, 0x54, 0x32, 0x13, 0x8c, 0xf3, 0xba, 0x77, 0x10, 0xff, 0x40, 0x35, 0xea, 0x10, 0x74}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0xd7, 0xc4, 0xcc, 0x7f, 0xf7, 0x93, 0x30, 0x22, 0xf0, 0x13, 0xe0, 0x3b, 0xde, 0xe8, 0x75, 0xb9, 0x17, 0x20, 0xb5, 0xb8, 0x6c, 0xf1, 0x75, 0x3c, 0xad, 0x83, 0x0f, 0x95, 0xe7, 0x91, 0x92, 0x6f}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} azure_AzureTrustedLaunch M gcp_GCPSEVES = M{1: {Expected: []byte{0x74, 0x5f, 0x2f, 0xb4, 0x23, 0x5e, 0x46, 0x47, 0xaa, 0x0a, 0xd5, 0xac, 0xe7, 0x81, 0xcd, 0x92, 0x9e, 0xb6, 0x8c, 0x28, 0x87, 0x0e, 0x7d, 0xd5, 0xd1, 0xa1, 0x53, 0x58, 0x54, 0x32, 0x5e, 0x56}, ValidationOpt: WarnOnly}, 2: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 3: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 4: {Expected: []byte{0xf8, 0xd7, 0x95, 0xe3, 0x27, 0x4d, 0x8d, 0x32, 0x78, 0xe2, 0xcc, 0xb5, 0x29, 0xfd, 0x7b, 0xce, 0x70, 0xef, 0x0e, 0x67, 0x99, 0xe4, 0xaa, 0x21, 0x7e, 0xac, 0x17, 0x42, 0xdf, 0xfc, 0x1d, 0xce}, ValidationOpt: Enforce}, 6: {Expected: []byte{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea, 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d, 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a, 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69}, ValidationOpt: WarnOnly}, 7: {Expected: []byte{0xb1, 0xe9, 0xb3, 0x05, 0x32, 0x5c, 0x51, 0xb9, 0x3d, 0xa5, 0x8c, 0xbf, 0x7f, 0x92, 0x51, 0x2d, 0x8e, 0xeb, 0xfa, 0x01, 0x14, 0x3e, 0x4d, 0x88, 0x44, 0xe4, 0x0e, 0x06, 0x2e, 0x9b, 0x6c, 0xd5}, ValidationOpt: WarnOnly}, 8: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 9: {Expected: []byte{0x99, 0x35, 0x5b, 0xbe, 0xb0, 0xa6, 0xff, 0x67, 0x6c, 0x51, 0x0a, 0xfb, 0xab, 0xe0, 0x5f, 0x84, 0x26, 0x17, 0x7b, 0xc7, 0xd6, 0x5c, 0xb7, 0xc1, 0xc3, 0xda, 0x8b, 0x00, 0xa2, 0x29, 0x57, 0x54}, ValidationOpt: Enforce}, 11: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 12: {Expected: []byte{0xab, 0x50, 0x0c, 0x4b, 0xc9, 0x4b, 0xb3, 0xa8, 0x7c, 0x47, 0x92, 0x23, 0x58, 0x1f, 0xcd, 0x03, 0xae, 0xb1, 0xc6, 0x87, 0xa4, 0x6a, 0x6b, 0x98, 0xaf, 0xce, 0x1c, 0x52, 0x43, 0x87, 0xd8, 0xed}, ValidationOpt: Enforce}, 13: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}, 14: {Expected: []byte{0xd7, 0xc4, 0xcc, 0x7f, 0xf7, 0x93, 0x30, 0x22, 0xf0, 0x13, 0xe0, 0x3b, 0xde, 0xe8, 0x75, 0xb9, 0x17, 0x20, 0xb5, 0xb8, 0x6c, 0xf1, 0x75, 0x3c, 0xad, 0x83, 0x0f, 0x95, 0xe7, 0x91, 0x92, 0x6f}, ValidationOpt: WarnOnly}, 15: {Expected: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, ValidationOpt: Enforce}} diff --git a/internal/attestation/measurements/measurements_oss.go b/internal/attestation/measurements/measurements_oss.go index 329de7575..9cb5f2a70 100644 --- a/internal/attestation/measurements/measurements_oss.go +++ b/internal/attestation/measurements/measurements_oss.go @@ -19,6 +19,17 @@ var ( 13: WithAllBytes(0x00, Enforce, PCRMeasurementLength), uint32(PCRIndexClusterID): WithAllBytes(0x00, Enforce, PCRMeasurementLength), } + + aws_AWSSEVSNP = M{ + 4: PlaceHolderMeasurement(PCRMeasurementLength), + 8: WithAllBytes(0x00, Enforce, PCRMeasurementLength), + 9: PlaceHolderMeasurement(PCRMeasurementLength), + 11: WithAllBytes(0x00, Enforce, PCRMeasurementLength), + 12: PlaceHolderMeasurement(PCRMeasurementLength), + 13: WithAllBytes(0x00, Enforce, PCRMeasurementLength), + uint32(PCRIndexClusterID): WithAllBytes(0x00, Enforce, PCRMeasurementLength), + } + azure_AzureSEVSNP = M{ 4: PlaceHolderMeasurement(PCRMeasurementLength), 8: WithAllBytes(0x00, Enforce, PCRMeasurementLength), diff --git a/internal/attestation/measurements/measurements_test.go b/internal/attestation/measurements/measurements_test.go index c10db6c40..57a064b00 100644 --- a/internal/attestation/measurements/measurements_test.go +++ b/internal/attestation/measurements/measurements_test.go @@ -21,9 +21,9 @@ import ( "gopkg.in/yaml.v3" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/sigstore" - "github.com/edgelesssys/constellation/v2/internal/variant" ) func TestMarshal(t *testing.T) { diff --git a/internal/attestation/qemu/BUILD.bazel b/internal/attestation/qemu/BUILD.bazel index 1d57eebb8..aae7a3615 100644 --- a/internal/attestation/qemu/BUILD.bazel +++ b/internal/attestation/qemu/BUILD.bazel @@ -11,9 +11,9 @@ go_library( visibility = ["//:__subpackages__"], deps = [ "//internal/attestation", + "//internal/attestation/variant", "//internal/attestation/vtpm", "//internal/config", - "//internal/variant", "@com_github_google_go_tpm//tpm2", "@com_github_google_go_tpm_tools//client", "@com_github_google_go_tpm_tools//proto/attest", diff --git a/internal/attestation/qemu/issuer.go b/internal/attestation/qemu/issuer.go index 915ce97a7..8214e8a27 100644 --- a/internal/attestation/qemu/issuer.go +++ b/internal/attestation/qemu/issuer.go @@ -11,8 +11,8 @@ import ( "io" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" - "github.com/edgelesssys/constellation/v2/internal/variant" tpmclient "github.com/google/go-tpm-tools/client" ) diff --git a/internal/attestation/qemu/validator.go b/internal/attestation/qemu/validator.go index 2fc599c78..bcea28fa5 100644 --- a/internal/attestation/qemu/validator.go +++ b/internal/attestation/qemu/validator.go @@ -11,9 +11,9 @@ import ( "crypto" "github.com/edgelesssys/constellation/v2/internal/attestation" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/attestation/vtpm" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/google/go-tpm-tools/proto/attest" "github.com/google/go-tpm/tpm2" ) diff --git a/internal/attestation/tdx/BUILD.bazel b/internal/attestation/tdx/BUILD.bazel index 629518d3c..ddcdf68c7 100644 --- a/internal/attestation/tdx/BUILD.bazel +++ b/internal/attestation/tdx/BUILD.bazel @@ -12,8 +12,8 @@ go_library( deps = [ "//internal/attestation", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/config", - "//internal/variant", "@com_github_edgelesssys_go_tdx_qpl//tdx", "@com_github_edgelesssys_go_tdx_qpl//verification", "@com_github_edgelesssys_go_tdx_qpl//verification/types", diff --git a/internal/attestation/tdx/issuer.go b/internal/attestation/tdx/issuer.go index 9ccc56c1a..4bee70065 100644 --- a/internal/attestation/tdx/issuer.go +++ b/internal/attestation/tdx/issuer.go @@ -12,7 +12,7 @@ import ( "fmt" "github.com/edgelesssys/constellation/v2/internal/attestation" - "github.com/edgelesssys/constellation/v2/internal/variant" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/go-tdx-qpl/tdx" ) diff --git a/internal/attestation/tdx/validator.go b/internal/attestation/tdx/validator.go index 8385e24e8..ea1172170 100644 --- a/internal/attestation/tdx/validator.go +++ b/internal/attestation/tdx/validator.go @@ -14,8 +14,8 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/go-tdx-qpl/verification" "github.com/edgelesssys/go-tdx-qpl/verification/types" ) diff --git a/internal/variant/BUILD.bazel b/internal/attestation/variant/BUILD.bazel similarity index 91% rename from internal/variant/BUILD.bazel rename to internal/attestation/variant/BUILD.bazel index 1251c7192..dc9f97da7 100644 --- a/internal/variant/BUILD.bazel +++ b/internal/attestation/variant/BUILD.bazel @@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "variant", srcs = ["variant.go"], - importpath = "github.com/edgelesssys/constellation/v2/internal/variant", + importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/variant", visibility = ["//:__subpackages__"], deps = ["//internal/cloud/cloudprovider"], ) diff --git a/internal/variant/variant.go b/internal/attestation/variant/variant.go similarity index 92% rename from internal/variant/variant.go rename to internal/attestation/variant/variant.go index 2cfe113f6..3ab672257 100644 --- a/internal/variant/variant.go +++ b/internal/attestation/variant/variant.go @@ -42,6 +42,7 @@ import ( const ( dummy = "dummy" awsNitroTPM = "aws-nitro-tpm" + awsSEVSNP = "aws-sev-snp" gcpSEVES = "gcp-sev-es" azureSEVSNP = "azure-sev-snp" azureTrustedLaunch = "azure-trustedlaunch" @@ -50,7 +51,7 @@ const ( ) var providerAttestationMapping = map[cloudprovider.Provider][]Variant{ - cloudprovider.AWS: {AWSNitroTPM{}}, + cloudprovider.AWS: {AWSSEVSNP{}, AWSNitroTPM{}}, cloudprovider.Azure: {AzureSEVSNP{}, AzureTrustedLaunch{}}, cloudprovider.GCP: {GCPSEVES{}}, cloudprovider.QEMU: {QEMUVTPM{}}, @@ -102,6 +103,8 @@ func FromString(oid string) (Variant, error) { switch oid { case dummy: return Dummy{}, nil + case awsSEVSNP: + return AWSSEVSNP{}, nil case awsNitroTPM: return AWSNitroTPM{}, nil case gcpSEVES: @@ -167,6 +170,24 @@ func (AWSNitroTPM) Equal(other Getter) bool { return other.OID().Equal(AWSNitroTPM{}.OID()) } +// AWSSEVSNP holds the AWS nitro TPM OID. +type AWSSEVSNP struct{} + +// OID returns the struct's object identifier. +func (AWSSEVSNP) OID() asn1.ObjectIdentifier { + return asn1.ObjectIdentifier{1, 3, 9900, 2, 2} +} + +// String returns the string representation of the OID. +func (AWSSEVSNP) String() string { + return awsSEVSNP +} + +// Equal returns true if the other variant is also AWSSEVSNP. +func (AWSSEVSNP) Equal(other Getter) bool { + return other.OID().Equal(AWSSEVSNP{}.OID()) +} + // GCPSEVES holds the GCP SEV-ES OID. type GCPSEVES struct{} diff --git a/internal/config/BUILD.bazel b/internal/config/BUILD.bazel index b1cb80761..c3ec3d496 100644 --- a/internal/config/BUILD.bazel +++ b/internal/config/BUILD.bazel @@ -21,13 +21,13 @@ go_library( "//internal/api/versionsapi", "//internal/attestation/idkeydigest", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/compatibility", "//internal/config/imageversion", "//internal/config/instancetypes", "//internal/constants", "//internal/file", - "//internal/variant", "//internal/versions", "@com_github_go_playground_locales//en", "@com_github_go_playground_universal_translator//:universal-translator", @@ -51,12 +51,12 @@ go_test( deps = [ "//internal/api/attestationconfigapi", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/config/instancetypes", "//internal/constants", "//internal/file", "//internal/semver", - "//internal/variant", "//internal/versions", "@com_github_go_playground_locales//en", "@com_github_go_playground_universal_translator//:universal-translator", diff --git a/internal/config/attestation.go b/internal/config/attestation.go index b393f6bf2..03e301c57 100644 --- a/internal/config/attestation.go +++ b/internal/config/attestation.go @@ -13,7 +13,7 @@ import ( "fmt" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" - "github.com/edgelesssys/constellation/v2/internal/variant" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" ) // AttestationCfg is the common interface for passing attestation configs. @@ -33,6 +33,8 @@ func UnmarshalAttestationConfig(data []byte, attestVariant variant.Variant) (Att switch attestVariant { case variant.AWSNitroTPM{}: return unmarshalTypedConfig[*AWSNitroTPM](data) + case variant.AWSSEVSNP{}: + return unmarshalTypedConfig[*AWSSEVSNP](data) case variant.AzureSEVSNP{}: return unmarshalTypedConfig[*AzureSEVSNP](data) case variant.AzureTrustedLaunch{}: diff --git a/internal/config/attestation_test.go b/internal/config/attestation_test.go index 1a42ee38b..650fef866 100644 --- a/internal/config/attestation_test.go +++ b/internal/config/attestation_test.go @@ -12,8 +12,8 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" @@ -26,6 +26,9 @@ func TestUnmarshalAttestationConfig(t *testing.T) { testCases := map[string]struct { cfg AttestationCfg }{ + "AWSSEVSNP": { + cfg: &AWSSEVSNP{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSSEVSNP{}), LaunchMeasurement: measurements.PlaceHolderMeasurement(48)}, + }, "AWSNitroTPM": { cfg: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})}, }, diff --git a/internal/config/config.go b/internal/config/config.go index 562d59a11..5f6baebf8 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -37,12 +37,12 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config/imageversion" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" ) @@ -279,6 +279,9 @@ type QEMUConfig struct { // Fields should remain pointer-types so custom specific configs can nil them // if not required. type AttestationConfig struct { + // description: | + // AWS SEV-SNP attestation. WARNING: NOT PRODUCTION READY, TESTING ONLY, NO MEANINGFUL ATTESTATION. + AWSSEVSNP *AWSSEVSNP `yaml:"awsSEVSNP,omitempty" validate:"omitempty,dive"` // description: | // AWS Nitro TPM attestation. AWSNitroTPM *AWSNitroTPM `yaml:"awsNitroTPM,omitempty" validate:"omitempty,dive"` @@ -359,6 +362,7 @@ func Default() *Config { // AWS uses aws-nitro-tpm as attestation variant // AWS will have aws-sev-snp as attestation variant Attestation: AttestationConfig{ + AWSSEVSNP: &AWSSEVSNP{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSSEVSNP{}), LaunchMeasurement: measurements.WithAllBytes(0x00, measurements.Enforce, measurements.PCRMeasurementLength)}, AWSNitroTPM: &AWSNitroTPM{Measurements: measurements.DefaultsFor(cloudprovider.AWS, variant.AWSNitroTPM{})}, AzureSEVSNP: DefaultForAzureSEVSNP(), AzureTrustedLaunch: &AzureTrustedLaunch{Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTrustedLaunch{})}, @@ -447,6 +451,9 @@ func (c *Config) HasProvider(provider cloudprovider.Provider) bool { // UpdateMeasurements overwrites measurements in config with the provided ones. func (c *Config) UpdateMeasurements(newMeasurements measurements.M) { + if c.Attestation.AWSSEVSNP != nil { + c.Attestation.AWSSEVSNP.Measurements.CopyFrom(newMeasurements) + } if c.Attestation.AWSNitroTPM != nil { c.Attestation.AWSNitroTPM.Measurements.CopyFrom(newMeasurements) } @@ -500,6 +507,8 @@ func (c *Config) SetAttestation(attestation variant.Variant) { switch attestation.(type) { case variant.AzureSEVSNP: c.Attestation = AttestationConfig{AzureSEVSNP: currentAttetationConfigs.AzureSEVSNP} + case variant.AWSSEVSNP: + c.Attestation = AttestationConfig{AWSSEVSNP: currentAttetationConfigs.AWSSEVSNP} case variant.AWSNitroTPM: c.Attestation = AttestationConfig{AWSNitroTPM: currentAttetationConfigs.AWSNitroTPM} case variant.AzureTrustedLaunch: @@ -546,6 +555,9 @@ func (c *Config) GetProvider() cloudprovider.Provider { // GetAttestationConfig returns the configured attestation config. func (c *Config) GetAttestationConfig() AttestationCfg { + if c.Attestation.AWSSEVSNP != nil { + return c.Attestation.AWSSEVSNP + } if c.Attestation.AWSNitroTPM != nil { return c.Attestation.AWSNitroTPM } @@ -708,6 +720,7 @@ func (c *Config) Validate(force bool) error { return err } + validate.RegisterStructValidation(validateMeasurement, measurements.Measurement{}) validate.RegisterStructValidation(validateAttestation, AttestationConfig{}) err := validate.Struct(c) @@ -751,6 +764,47 @@ func (c *Config) WithOpenStackProviderDefaults(openStackProvider string) *Config return c } +// AWSSEVSNP is the configuration for AWS SEV-SNP attestation. +type AWSSEVSNP struct { + // description: | + // Expected TPM measurements. + Measurements measurements.M `json:"measurements" yaml:"measurements" validate:"required,no_placeholders"` + // description: | + // Expected launch measurement in SNP report. + LaunchMeasurement measurements.Measurement `json:"launchMeasurement" yaml:"launchMeasurement" validate:"required"` +} + +// GetVariant returns aws-sev-snp as the variant. +func (AWSSEVSNP) GetVariant() variant.Variant { + return variant.AWSSEVSNP{} +} + +// GetMeasurements returns the measurements used for attestation. +func (c AWSSEVSNP) GetMeasurements() measurements.M { + return c.Measurements +} + +// SetMeasurements updates a config's measurements using the given measurements. +func (c *AWSSEVSNP) SetMeasurements(m measurements.M) { + c.Measurements = m +} + +// EqualTo returns true if the config is equal to the given config. +func (c AWSSEVSNP) EqualTo(other AttestationCfg) (bool, error) { + otherCfg, ok := other.(*AWSSEVSNP) + if !ok { + return false, fmt.Errorf("cannot compare %T with %T", c, other) + } + if !bytes.Equal(c.LaunchMeasurement.Expected, otherCfg.LaunchMeasurement.Expected) { + return false, nil + } + if c.LaunchMeasurement.ValidationOpt != otherCfg.LaunchMeasurement.ValidationOpt { + return false, nil + } + + return c.Measurements.EqualTo(otherCfg.Measurements), nil +} + // AWSNitroTPM is the configuration for AWS Nitro TPM attestation. type AWSNitroTPM struct { // description: | diff --git a/internal/config/config_doc.go b/internal/config/config_doc.go index 1fc24ff53..4ed2f9932 100644 --- a/internal/config/config_doc.go +++ b/internal/config/config_doc.go @@ -19,6 +19,7 @@ var ( OpenStackConfigDoc encoder.Doc QEMUConfigDoc encoder.Doc AttestationConfigDoc encoder.Doc + AWSSEVSNPDoc encoder.Doc AWSNitroTPMDoc encoder.Doc SNPFirmwareSignerConfigDoc encoder.Doc GCPSEVESDoc encoder.Doc @@ -429,37 +430,63 @@ func init() { FieldName: "attestation", }, } - AttestationConfigDoc.Fields = make([]encoder.Doc, 6) - AttestationConfigDoc.Fields[0].Name = "awsNitroTPM" - AttestationConfigDoc.Fields[0].Type = "AWSNitroTPM" + AttestationConfigDoc.Fields = make([]encoder.Doc, 7) + AttestationConfigDoc.Fields[0].Name = "awsSEVSNP" + AttestationConfigDoc.Fields[0].Type = "AWSSEVSNP" AttestationConfigDoc.Fields[0].Note = "" - AttestationConfigDoc.Fields[0].Description = "AWS Nitro TPM attestation." - AttestationConfigDoc.Fields[0].Comments[encoder.LineComment] = "AWS Nitro TPM attestation." - AttestationConfigDoc.Fields[1].Name = "azureSEVSNP" - AttestationConfigDoc.Fields[1].Type = "AzureSEVSNP" + AttestationConfigDoc.Fields[0].Description = "AWS SEV-SNP attestation. WARNING: NOT PRODUCTION READY, TESTING ONLY, NO MEANINGFUL ATTESTATION." + AttestationConfigDoc.Fields[0].Comments[encoder.LineComment] = "AWS SEV-SNP attestation. WARNING: NOT PRODUCTION READY, TESTING ONLY, NO MEANINGFUL ATTESTATION." + AttestationConfigDoc.Fields[1].Name = "awsNitroTPM" + AttestationConfigDoc.Fields[1].Type = "AWSNitroTPM" AttestationConfigDoc.Fields[1].Note = "" - AttestationConfigDoc.Fields[1].Description = "Azure SEV-SNP attestation.\nFor details see: https://docs.edgeless.systems/constellation/architecture/attestation#cvm-verification" - AttestationConfigDoc.Fields[1].Comments[encoder.LineComment] = "Azure SEV-SNP attestation.\nFor details see: https://docs.edgeless.systems/constellation/architecture/attestation#cvm-verification" - AttestationConfigDoc.Fields[2].Name = "azureTrustedLaunch" - AttestationConfigDoc.Fields[2].Type = "AzureTrustedLaunch" + AttestationConfigDoc.Fields[1].Description = "AWS Nitro TPM attestation." + AttestationConfigDoc.Fields[1].Comments[encoder.LineComment] = "AWS Nitro TPM attestation." + AttestationConfigDoc.Fields[2].Name = "azureSEVSNP" + AttestationConfigDoc.Fields[2].Type = "AzureSEVSNP" AttestationConfigDoc.Fields[2].Note = "" - AttestationConfigDoc.Fields[2].Description = "Azure TPM attestation (Trusted Launch)." - AttestationConfigDoc.Fields[2].Comments[encoder.LineComment] = "Azure TPM attestation (Trusted Launch)." - AttestationConfigDoc.Fields[3].Name = "gcpSEVES" - AttestationConfigDoc.Fields[3].Type = "GCPSEVES" + AttestationConfigDoc.Fields[2].Description = "Azure SEV-SNP attestation.\nFor details see: https://docs.edgeless.systems/constellation/architecture/attestation#cvm-verification" + AttestationConfigDoc.Fields[2].Comments[encoder.LineComment] = "Azure SEV-SNP attestation.\nFor details see: https://docs.edgeless.systems/constellation/architecture/attestation#cvm-verification" + AttestationConfigDoc.Fields[3].Name = "azureTrustedLaunch" + AttestationConfigDoc.Fields[3].Type = "AzureTrustedLaunch" AttestationConfigDoc.Fields[3].Note = "" - AttestationConfigDoc.Fields[3].Description = "GCP SEV-ES attestation." - AttestationConfigDoc.Fields[3].Comments[encoder.LineComment] = "GCP SEV-ES attestation." - AttestationConfigDoc.Fields[4].Name = "qemuTDX" - AttestationConfigDoc.Fields[4].Type = "QEMUTDX" + AttestationConfigDoc.Fields[3].Description = "Azure TPM attestation (Trusted Launch)." + AttestationConfigDoc.Fields[3].Comments[encoder.LineComment] = "Azure TPM attestation (Trusted Launch)." + AttestationConfigDoc.Fields[4].Name = "gcpSEVES" + AttestationConfigDoc.Fields[4].Type = "GCPSEVES" AttestationConfigDoc.Fields[4].Note = "" - AttestationConfigDoc.Fields[4].Description = "QEMU tdx attestation." - AttestationConfigDoc.Fields[4].Comments[encoder.LineComment] = "QEMU tdx attestation." - AttestationConfigDoc.Fields[5].Name = "qemuVTPM" - AttestationConfigDoc.Fields[5].Type = "QEMUVTPM" + AttestationConfigDoc.Fields[4].Description = "GCP SEV-ES attestation." + AttestationConfigDoc.Fields[4].Comments[encoder.LineComment] = "GCP SEV-ES attestation." + AttestationConfigDoc.Fields[5].Name = "qemuTDX" + AttestationConfigDoc.Fields[5].Type = "QEMUTDX" AttestationConfigDoc.Fields[5].Note = "" - AttestationConfigDoc.Fields[5].Description = "QEMU vTPM attestation." - AttestationConfigDoc.Fields[5].Comments[encoder.LineComment] = "QEMU vTPM attestation." + AttestationConfigDoc.Fields[5].Description = "QEMU tdx attestation." + AttestationConfigDoc.Fields[5].Comments[encoder.LineComment] = "QEMU tdx attestation." + AttestationConfigDoc.Fields[6].Name = "qemuVTPM" + AttestationConfigDoc.Fields[6].Type = "QEMUVTPM" + AttestationConfigDoc.Fields[6].Note = "" + AttestationConfigDoc.Fields[6].Description = "QEMU vTPM attestation." + AttestationConfigDoc.Fields[6].Comments[encoder.LineComment] = "QEMU vTPM attestation." + + AWSSEVSNPDoc.Type = "AWSSEVSNP" + AWSSEVSNPDoc.Comments[encoder.LineComment] = "AWSSEVSNP is the configuration for AWS SEV-SNP attestation." + AWSSEVSNPDoc.Description = "AWSSEVSNP is the configuration for AWS SEV-SNP attestation." + AWSSEVSNPDoc.AppearsIn = []encoder.Appearance{ + { + TypeName: "AttestationConfig", + FieldName: "awsSEVSNP", + }, + } + AWSSEVSNPDoc.Fields = make([]encoder.Doc, 2) + AWSSEVSNPDoc.Fields[0].Name = "measurements" + AWSSEVSNPDoc.Fields[0].Type = "M" + AWSSEVSNPDoc.Fields[0].Note = "" + AWSSEVSNPDoc.Fields[0].Description = "Expected TPM measurements." + AWSSEVSNPDoc.Fields[0].Comments[encoder.LineComment] = "Expected TPM measurements." + AWSSEVSNPDoc.Fields[1].Name = "launchMeasurement" + AWSSEVSNPDoc.Fields[1].Type = "Measurement" + AWSSEVSNPDoc.Fields[1].Note = "" + AWSSEVSNPDoc.Fields[1].Description = "Expected launch measurement in SNP report." + AWSSEVSNPDoc.Fields[1].Comments[encoder.LineComment] = "Expected launch measurement in SNP report." AWSNitroTPMDoc.Type = "AWSNitroTPM" AWSNitroTPMDoc.Comments[encoder.LineComment] = "AWSNitroTPM is the configuration for AWS Nitro TPM attestation." @@ -646,6 +673,10 @@ func (_ AttestationConfig) Doc() *encoder.Doc { return &AttestationConfigDoc } +func (_ AWSSEVSNP) Doc() *encoder.Doc { + return &AWSSEVSNPDoc +} + func (_ AWSNitroTPM) Doc() *encoder.Doc { return &AWSNitroTPMDoc } @@ -688,6 +719,7 @@ func GetConfigurationDoc() *encoder.FileDoc { &OpenStackConfigDoc, &QEMUConfigDoc, &AttestationConfigDoc, + &AWSSEVSNPDoc, &AWSNitroTPMDoc, &SNPFirmwareSignerConfigDoc, &GCPSEVESDoc, diff --git a/internal/config/config_test.go b/internal/config/config_test.go index a03ed6b99..1e9a211ed 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -276,7 +276,7 @@ func TestNewWithDefaultOptions(t *testing.T) { } func TestValidate(t *testing.T) { - const defaultErrCount = 32 // expect this number of error messages by default because user-specific values are not set and multiple providers are defined by default + const defaultErrCount = 33 // expect this number of error messages by default because user-specific values are not set and multiple providers are defined by default const azErrCount = 7 const gcpErrCount = 6 @@ -499,11 +499,11 @@ func TestConfig_UpdateMeasurements(t *testing.T) { { // AWS conf := Default() conf.RemoveProviderAndAttestationExcept(cloudprovider.AWS) - for k := range conf.Attestation.AWSNitroTPM.Measurements { - delete(conf.Attestation.AWSNitroTPM.Measurements, k) + for k := range conf.Attestation.AWSSEVSNP.Measurements { + delete(conf.Attestation.AWSSEVSNP.Measurements, k) } conf.UpdateMeasurements(newMeasurements) - assert.Equal(newMeasurements, conf.Attestation.AWSNitroTPM.Measurements) + assert.Equal(newMeasurements, conf.Attestation.AWSSEVSNP.Measurements) } { // Azure conf := Default() diff --git a/internal/config/migration/BUILD.bazel b/internal/config/migration/BUILD.bazel index 5299203c4..e6946ba62 100644 --- a/internal/config/migration/BUILD.bazel +++ b/internal/config/migration/BUILD.bazel @@ -8,8 +8,8 @@ go_library( deps = [ "//internal/attestation/idkeydigest", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/config", "//internal/file", - "//internal/variant", ], ) diff --git a/internal/config/migration/migration.go b/internal/config/migration/migration.go index a7dca266f..4d089d0a4 100644 --- a/internal/config/migration/migration.go +++ b/internal/config/migration/migration.go @@ -15,9 +15,9 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/file" - "github.com/edgelesssys/constellation/v2/internal/variant" ) const ( diff --git a/internal/config/validation.go b/internal/config/validation.go index 7386b79ed..099b15302 100644 --- a/internal/config/validation.go +++ b/internal/config/validation.go @@ -21,11 +21,11 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/compatibility" "github.com/edgelesssys/constellation/v2/internal/config/instancetypes" "github.com/edgelesssys/constellation/v2/internal/constants" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/versions" ) @@ -144,6 +144,9 @@ func validateAttestation(sl validator.StructLevel) { attestation := sl.Current().Interface().(AttestationConfig) attestationCount := 0 + if attestation.AWSSEVSNP != nil { + attestationCount++ + } if attestation.AWSNitroTPM != nil { attestationCount++ } @@ -174,7 +177,7 @@ func translateNoAttestationError(ut ut.Translator, fe validator.FieldError) stri } func registerNoAttestationError(ut ut.Translator) error { - return ut.Add("no_attestation", "{0}: No attestation has been defined (requires either AWSNitroTPM, AzureSEVSNP, AzureTrustedLaunch, GCPSEVES, or QEMUVTPM)", true) + return ut.Add("no_attestation", "{0}: No attestation has been defined (requires either awsSEVSNP, awsNitroTPM, azureSEVSNP, azureTrustedLaunch, gcpSEVES, or qemuVTPM)", true) } func registerMoreThanOneAttestationError(ut ut.Translator) error { @@ -187,6 +190,9 @@ func (c *Config) translateMoreThanOneAttestationError(ut ut.Translator, fe valid if c.Attestation.AWSNitroTPM != nil { definedAttestations = append(definedAttestations, "AWSNitroTPM") } + if c.Attestation.AWSSEVSNP != nil { + definedAttestations = append(definedAttestations, "AWSSEVSNP") + } if c.Attestation.AzureSEVSNP != nil { definedAttestations = append(definedAttestations, "AzureSEVSNP") } @@ -360,15 +366,31 @@ func validateNoPlaceholder(fl validator.FieldLevel) bool { return len(getPlaceholderEntries(fl.Field().Interface().(measurements.M))) == 0 } +// validateMeasurement acts like validateNoPlaceholder, but is used for the measurements.Measurement type. +func validateMeasurement(sl validator.StructLevel) { + measurement := sl.Current().Interface().(measurements.Measurement) + actual := measurement.Expected + placeHolder := measurements.PlaceHolderMeasurement(measurements.PCRMeasurementLength).Expected + if bytes.Equal(actual, placeHolder) { + sl.ReportError(measurement, "launchMeasurement", "launchMeasurement", "no_placeholders", "") + } +} + func registerContainsPlaceholderError(ut ut.Translator) error { return ut.Add("no_placeholders", "{0} placeholder values (repeated 1234...)", true) } func translateContainsPlaceholderError(ut ut.Translator, fe validator.FieldError) string { - placeholders := getPlaceholderEntries(fe.Value().(measurements.M)) - msg := fmt.Sprintf("Measurements %v contain", placeholders) - if len(placeholders) == 1 { - msg = fmt.Sprintf("Measurement %v contains", placeholders) + var msg string + switch fe.Field() { + case "launchMeasurement": + msg = "launchMeasurement contains" + case "measurements": + placeholders := getPlaceholderEntries(fe.Value().(measurements.M)) + msg = fmt.Sprintf("measurements %v contain", placeholders) + if len(placeholders) == 1 { + msg = fmt.Sprintf("measurement %v contains", placeholders) + } } t, _ := ut.T("no_placeholders", msg) diff --git a/internal/grpc/dialer/BUILD.bazel b/internal/grpc/dialer/BUILD.bazel index c0c07e2df..b8428ba2d 100644 --- a/internal/grpc/dialer/BUILD.bazel +++ b/internal/grpc/dialer/BUILD.bazel @@ -20,9 +20,9 @@ go_test( embed = [":dialer"], deps = [ "//internal/atls", + "//internal/attestation/variant", "//internal/grpc/atlscredentials", "//internal/grpc/testdialer", - "//internal/variant", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", "@org_golang_google_grpc//:go_default_library", diff --git a/internal/grpc/dialer/dialer_test.go b/internal/grpc/dialer/dialer_test.go index a5e805873..4e152bd56 100644 --- a/internal/grpc/dialer/dialer_test.go +++ b/internal/grpc/dialer/dialer_test.go @@ -11,9 +11,9 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/internal/atls" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/grpc/atlscredentials" "github.com/edgelesssys/constellation/v2/internal/grpc/testdialer" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/goleak" diff --git a/internal/imagefetcher/BUILD.bazel b/internal/imagefetcher/BUILD.bazel index 0b1236db5..b72941b71 100644 --- a/internal/imagefetcher/BUILD.bazel +++ b/internal/imagefetcher/BUILD.bazel @@ -12,8 +12,8 @@ go_library( deps = [ "//internal/api/fetcher", "//internal/api/versionsapi", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", - "//internal/variant", "@com_github_schollz_progressbar_v3//:progressbar", "@com_github_spf13_afero//:afero", ], @@ -28,9 +28,9 @@ go_test( embed = [":imagefetcher"], deps = [ "//internal/api/versionsapi", + "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/file", - "//internal/variant", "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", "@com_github_stretchr_testify//require", diff --git a/internal/imagefetcher/imagefetcher.go b/internal/imagefetcher/imagefetcher.go index 81f236a15..4cab9bc47 100644 --- a/internal/imagefetcher/imagefetcher.go +++ b/internal/imagefetcher/imagefetcher.go @@ -21,8 +21,8 @@ import ( "github.com/edgelesssys/constellation/v2/internal/api/fetcher" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" ) diff --git a/internal/imagefetcher/imagefetcher_test.go b/internal/imagefetcher/imagefetcher_test.go index 5543e17f8..ef47514d3 100644 --- a/internal/imagefetcher/imagefetcher_test.go +++ b/internal/imagefetcher/imagefetcher_test.go @@ -14,9 +14,9 @@ import ( "testing" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/file" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/internal/watcher/BUILD.bazel b/internal/watcher/BUILD.bazel index ae2ad8ffb..e86d9ccdf 100644 --- a/internal/watcher/BUILD.bazel +++ b/internal/watcher/BUILD.bazel @@ -12,11 +12,11 @@ go_library( deps = [ "//internal/atls", "//internal/attestation/choose", + "//internal/attestation/variant", "//internal/config", "//internal/constants", "//internal/file", "//internal/logger", - "//internal/variant", "@com_github_fsnotify_fsnotify//:fsnotify", "@org_uber_go_zap//:zap", ], @@ -32,11 +32,11 @@ go_test( deps = [ "//internal/atls", "//internal/attestation/measurements", + "//internal/attestation/variant", "//internal/config", "//internal/constants", "//internal/file", "//internal/logger", - "//internal/variant", "@com_github_fsnotify_fsnotify//:fsnotify", "@com_github_spf13_afero//:afero", "@com_github_stretchr_testify//assert", diff --git a/internal/watcher/validator.go b/internal/watcher/validator.go index 1a3c448b9..505a6e49c 100644 --- a/internal/watcher/validator.go +++ b/internal/watcher/validator.go @@ -15,11 +15,11 @@ import ( "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/choose" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" ) // Updatable implements an updatable atls.Validator. diff --git a/internal/watcher/validator_test.go b/internal/watcher/validator_test.go index 044d295b1..c0ff4b145 100644 --- a/internal/watcher/validator_test.go +++ b/internal/watcher/validator_test.go @@ -19,11 +19,11 @@ import ( "github.com/edgelesssys/constellation/v2/internal/atls" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/spf13/afero" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/joinservice/cmd/BUILD.bazel b/joinservice/cmd/BUILD.bazel index 5dbb56f43..a49068fd9 100644 --- a/joinservice/cmd/BUILD.bazel +++ b/joinservice/cmd/BUILD.bazel @@ -9,6 +9,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "//internal/atls", + "//internal/attestation/variant", "//internal/cloud/aws", "//internal/cloud/azure", "//internal/cloud/cloudprovider", @@ -20,7 +21,6 @@ go_library( "//internal/file", "//internal/grpc/atlscredentials", "//internal/logger", - "//internal/variant", "//internal/watcher", "//joinservice/internal/kms", "//joinservice/internal/kubeadm", diff --git a/joinservice/cmd/main.go b/joinservice/cmd/main.go index 31892a2aa..779fe7250 100644 --- a/joinservice/cmd/main.go +++ b/joinservice/cmd/main.go @@ -16,6 +16,7 @@ import ( "time" "github.com/edgelesssys/constellation/v2/internal/atls" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" awscloud "github.com/edgelesssys/constellation/v2/internal/cloud/aws" azurecloud "github.com/edgelesssys/constellation/v2/internal/cloud/azure" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" @@ -27,7 +28,6 @@ import ( "github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/grpc/atlscredentials" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/internal/watcher" "github.com/edgelesssys/constellation/v2/joinservice/internal/kms" "github.com/edgelesssys/constellation/v2/joinservice/internal/kubeadm" diff --git a/measurement-reader/cmd/BUILD.bazel b/measurement-reader/cmd/BUILD.bazel index 0b68b810a..a99e20886 100644 --- a/measurement-reader/cmd/BUILD.bazel +++ b/measurement-reader/cmd/BUILD.bazel @@ -7,9 +7,9 @@ go_library( importpath = "github.com/edgelesssys/constellation/v2/measurement-reader/cmd", visibility = ["//visibility:private"], deps = [ + "//internal/attestation/variant", "//internal/constants", "//internal/logger", - "//internal/variant", "//measurement-reader/internal/sorted", "//measurement-reader/internal/tdx", "//measurement-reader/internal/tpm", diff --git a/measurement-reader/cmd/main.go b/measurement-reader/cmd/main.go index dc0e68c49..7fb96a3b1 100644 --- a/measurement-reader/cmd/main.go +++ b/measurement-reader/cmd/main.go @@ -10,9 +10,9 @@ import ( "fmt" "os" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/measurement-reader/internal/sorted" "github.com/edgelesssys/constellation/v2/measurement-reader/internal/tdx" "github.com/edgelesssys/constellation/v2/measurement-reader/internal/tpm" @@ -30,7 +30,7 @@ func main() { var m []sorted.Measurement switch attestationVariant { - case variant.AWSNitroTPM{}, variant.AzureSEVSNP{}, variant.AzureTrustedLaunch{}, variant.GCPSEVES{}, variant.QEMUVTPM{}: + case variant.AWSNitroTPM{}, variant.AWSSEVSNP{}, variant.AzureSEVSNP{}, variant.AzureTrustedLaunch{}, variant.GCPSEVES{}, variant.QEMUVTPM{}: m, err = tpm.Measurements() if err != nil { log.With(zap.Error(err)).Fatalf("Failed to read TPM measurements") diff --git a/verify/cmd/BUILD.bazel b/verify/cmd/BUILD.bazel index c90eb9777..062084ffc 100644 --- a/verify/cmd/BUILD.bazel +++ b/verify/cmd/BUILD.bazel @@ -9,9 +9,9 @@ go_library( visibility = ["//visibility:private"], deps = [ "//internal/attestation/choose", + "//internal/attestation/variant", "//internal/constants", "//internal/logger", - "//internal/variant", "//verify/server", "@org_uber_go_zap//:zap", ], diff --git a/verify/cmd/main.go b/verify/cmd/main.go index 54055a16d..9dcbd7159 100644 --- a/verify/cmd/main.go +++ b/verify/cmd/main.go @@ -12,9 +12,9 @@ import ( "strconv" "github.com/edgelesssys/constellation/v2/internal/attestation/choose" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/logger" - "github.com/edgelesssys/constellation/v2/internal/variant" "github.com/edgelesssys/constellation/v2/verify/server" "go.uber.org/zap" )