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.
This commit is contained in:
Otto Bittner 2023-06-09 15:41:02 +02:00 committed by GitHub
parent 947d0cb20a
commit 8f21972aec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
110 changed files with 993 additions and 215 deletions

View file

@ -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",
],
)

View file

@ -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

View file

@ -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",
],
)

View file

@ -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)
}

View file

@ -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
}

View file

@ -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

View file

@ -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"
)

View file

@ -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
}

View file

@ -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",
],
)

View file

@ -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)
}

View file

@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package aws
package snp
import (
"context"

View file

@ -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

View file

@ -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)
}

View file

@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package aws
package snp
import (
"context"

View file

@ -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",

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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",

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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",
],

View file

@ -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:

View file

@ -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{},
},

View file

@ -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",

View file

@ -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"
)

View file

@ -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"

View file

@ -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",

View file

@ -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",
],
)

View file

@ -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":

View file

@ -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()

View file

@ -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}}

View file

@ -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),

View file

@ -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) {

View file

@ -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",

View file

@ -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"
)

View file

@ -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"
)

View file

@ -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",

View file

@ -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"
)

View file

@ -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"
)

View file

@ -0,0 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "variant",
srcs = ["variant.go"],
importpath = "github.com/edgelesssys/constellation/v2/internal/attestation/variant",
visibility = ["//:__subpackages__"],
deps = ["//internal/cloud/cloudprovider"],
)

View file

@ -0,0 +1,294 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
Package variant defines Attestation variants for different CSPs.
Each variant defines an OID, a string representation, and a function to compare it to other OIDs.
The OID is used in attested TLS to distinguish the attestation documents.
OIDs beginning with 1.3.9900 are reserved and can be used without registration.
* The 1.3.9900.1 branch is reserved for placeholder values and testing.
* The 1.3.9900.2 branch is reserved for AWS.
* The 1.3.9900.3 branch is reserved for GCP.
* The 1.3.9900.4 branch is reserved for Azure.
* The 1.3.9900.5 branch is reserved for QEMU.
Deprecated OIDs should never be reused for different purposes.
Instead, new OIDs should be added in the appropriate branch at the next available index.
String representation should be lowercase and contain only letters, numbers, and hyphens.
They should be prefixed with the branch name, e.g. all variants in the 1.3.9900.2 (AWS) branch should start with "aws-".
Each variant should have a unique string representation.
*/
package variant
import (
"encoding/asn1"
"fmt"
"sort"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
)
const (
dummy = "dummy"
awsNitroTPM = "aws-nitro-tpm"
awsSEVSNP = "aws-sev-snp"
gcpSEVES = "gcp-sev-es"
azureSEVSNP = "azure-sev-snp"
azureTrustedLaunch = "azure-trustedlaunch"
qemuVTPM = "qemu-vtpm"
qemuTDX = "qemu-tdx"
)
var providerAttestationMapping = map[cloudprovider.Provider][]Variant{
cloudprovider.AWS: {AWSSEVSNP{}, AWSNitroTPM{}},
cloudprovider.Azure: {AzureSEVSNP{}, AzureTrustedLaunch{}},
cloudprovider.GCP: {GCPSEVES{}},
cloudprovider.QEMU: {QEMUVTPM{}},
cloudprovider.OpenStack: {QEMUVTPM{}},
}
// GetDefaultAttestation returns the default attestation type for the given provider. If not found, it returns the default variant.
func GetDefaultAttestation(provider cloudprovider.Provider) Variant {
res, ok := providerAttestationMapping[provider]
if ok {
return res[0]
}
return Dummy{}
}
// GetAvailableAttestationTypes returns the available attestation types.
func GetAvailableAttestationTypes() []Variant {
var res []Variant
// assumes that cloudprovider.Provider is a uint32 to sort the providers and get a consistent order
var keys []cloudprovider.Provider
for k := range providerAttestationMapping {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return uint(keys[i]) < uint(keys[j])
})
for _, k := range keys {
res = append(res, providerAttestationMapping[k]...)
}
return RemoveDuplicate(res)
}
// Getter returns an ASN.1 Object Identifier.
type Getter interface {
OID() asn1.ObjectIdentifier
}
// Variant describes an attestation variant.
type Variant interface {
Getter
String() string
Equal(other Getter) bool
}
// FromString returns the OID for the given string.
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:
return GCPSEVES{}, nil
case azureSEVSNP:
return AzureSEVSNP{}, nil
case azureTrustedLaunch:
return AzureTrustedLaunch{}, nil
case qemuVTPM:
return QEMUVTPM{}, nil
case qemuTDX:
return QEMUTDX{}, nil
}
return nil, fmt.Errorf("unknown OID: %q", oid)
}
// ValidProvider returns true if the attestation type is valid for the given provider.
func ValidProvider(provider cloudprovider.Provider, variant Variant) bool {
validTypes, ok := providerAttestationMapping[provider]
if ok {
for _, aType := range validTypes {
if variant.Equal(aType) {
return true
}
}
}
return false
}
// Dummy OID for testfing.
type Dummy struct{}
// OID returns the struct's object identifier.
func (Dummy) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 1, 1}
}
// String returns the string representation of the OID.
func (Dummy) String() string {
return dummy
}
// Equal returns true if the other variant is also a Default.
func (Dummy) Equal(other Getter) bool {
return other.OID().Equal(Dummy{}.OID())
}
// AWSNitroTPM holds the AWS nitro TPM OID.
type AWSNitroTPM struct{}
// OID returns the struct's object identifier.
func (AWSNitroTPM) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 2, 1}
}
// String returns the string representation of the OID.
func (AWSNitroTPM) String() string {
return awsNitroTPM
}
// Equal returns true if the other variant is also AWSNitroTPM.
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{}
// OID returns the struct's object identifier.
func (GCPSEVES) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 3, 1}
}
// String returns the string representation of the OID.
func (GCPSEVES) String() string {
return gcpSEVES
}
// Equal returns true if the other variant is also GCPSEVES.
func (GCPSEVES) Equal(other Getter) bool {
return other.OID().Equal(GCPSEVES{}.OID())
}
// AzureSEVSNP holds the OID for Azure SNP CVMs.
type AzureSEVSNP struct{}
// OID returns the struct's object identifier.
func (AzureSEVSNP) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 4, 1}
}
// String returns the string representation of the OID.
func (AzureSEVSNP) String() string {
return azureSEVSNP
}
// Equal returns true if the other variant is also AzureSEVSNP.
func (AzureSEVSNP) Equal(other Getter) bool {
return other.OID().Equal(AzureSEVSNP{}.OID())
}
// AzureTrustedLaunch holds the OID for Azure TrustedLaunch VMs.
type AzureTrustedLaunch struct{}
// OID returns the struct's object identifier.
func (AzureTrustedLaunch) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 4, 2}
}
// String returns the string representation of the OID.
func (AzureTrustedLaunch) String() string {
return azureTrustedLaunch
}
// Equal returns true if the other variant is also AzureTrustedLaunch.
func (AzureTrustedLaunch) Equal(other Getter) bool {
return other.OID().Equal(AzureTrustedLaunch{}.OID())
}
// QEMUVTPM holds the QEMUVTPM OID.
type QEMUVTPM struct{}
// OID returns the struct's object identifier.
func (QEMUVTPM) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 5, 1}
}
// String returns the string representation of the OID.
func (QEMUVTPM) String() string {
return qemuVTPM
}
// Equal returns true if the other variant is also QEMUVTPM.
func (QEMUVTPM) Equal(other Getter) bool {
return other.OID().Equal(QEMUVTPM{}.OID())
}
// QEMUTDX holds the QEMU TDX OID.
// Placeholder for dev-cloud integration.
type QEMUTDX struct{}
// OID returns the struct's object identifier.
// Placeholder for dev-cloud integration.
func (QEMUTDX) OID() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 9900, 5, 99}
}
// String returns the string representation of the OID.
func (QEMUTDX) String() string {
return qemuTDX
}
// Equal returns true if the other variant is also QEMUTDX.
func (QEMUTDX) Equal(other Getter) bool {
return other.OID().Equal(QEMUTDX{}.OID())
}
// RemoveDuplicate removes duplicate elements from a slice.
func RemoveDuplicate[T comparable](sliceList []T) []T {
allKeys := make(map[T]bool)
list := []T{}
for _, item := range sliceList {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}