2022-09-05 03:06:08 -04:00
|
|
|
/*
|
|
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
*/
|
|
|
|
|
2022-03-22 11:03:15 -04:00
|
|
|
package aws
|
|
|
|
|
|
|
|
import (
|
2022-10-27 05:04:23 -04:00
|
|
|
"context"
|
|
|
|
"crypto"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
|
2022-11-15 09:40:49 -05:00
|
|
|
awsConfig "github.com/aws/aws-sdk-go-v2/config"
|
2022-10-27 05:04:23 -04:00
|
|
|
"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/vtpm"
|
2023-04-06 11:00:56 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/internal/config"
|
2023-03-29 03:30:13 -04:00
|
|
|
"github.com/edgelesssys/constellation/v2/internal/variant"
|
2023-03-06 03:15:52 -05:00
|
|
|
"github.com/google/go-tpm-tools/proto/attest"
|
2022-10-27 05:04:23 -04:00
|
|
|
"github.com/google/go-tpm/tpm2"
|
2022-03-22 11:03:15 -04:00
|
|
|
)
|
|
|
|
|
2022-10-27 05:04:23 -04:00
|
|
|
// Validator for AWS TPM attestation.
|
2022-03-22 11:03:15 -04:00
|
|
|
type Validator struct {
|
2023-03-29 03:30:13 -04:00
|
|
|
variant.AWSNitroTPM
|
2022-10-27 05:04:23 -04:00
|
|
|
*vtpm.Validator
|
2022-11-02 10:19:13 -04:00
|
|
|
getDescribeClient func(context.Context, string) (awsMetadataAPI, error)
|
2022-10-27 05:04:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewValidator create a new Validator structure and returns it.
|
2023-05-03 05:11:53 -04:00
|
|
|
func NewValidator(cfg *config.AWSNitroTPM, log vtpm.AttestationLogger) *Validator {
|
2022-10-27 05:04:23 -04:00
|
|
|
v := &Validator{}
|
|
|
|
v.Validator = vtpm.NewValidator(
|
2023-04-06 11:00:56 -04:00
|
|
|
cfg.Measurements,
|
2022-10-27 05:04:23 -04:00
|
|
|
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.
|
2023-03-21 07:46:49 -04:00
|
|
|
func getTrustedKey(_ context.Context, attDoc vtpm.AttestationDocument, _ []byte) (crypto.PublicKey, error) {
|
2022-10-27 05:04:23 -04:00
|
|
|
// Copied from https://github.com/edgelesssys/constellation/blob/main/internal/attestation/qemu/validator.go
|
2023-03-21 07:46:49 -04:00
|
|
|
pubArea, err := tpm2.DecodePublic(attDoc.Attestation.AkPub)
|
2022-10-27 05:04:23 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return pubArea.Key()
|
|
|
|
}
|
|
|
|
|
|
|
|
// tpmEnabled verifies if the virtual machine has the tpm2.0 feature enabled.
|
2023-03-06 03:15:52 -05:00
|
|
|
func (v *Validator) tpmEnabled(attestation vtpm.AttestationDocument, _ *attest.MachineState) error {
|
2022-10-27 05:04:23 -04:00
|
|
|
// 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{}
|
2022-11-02 10:19:13 -04:00
|
|
|
err := json.Unmarshal(attestation.InstanceInfo, &idDocument)
|
2022-10-27 05:04:23 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
imageID := idDocument.ImageID
|
|
|
|
|
2022-11-02 10:19:13 -04:00
|
|
|
client, err := v.getDescribeClient(ctx, idDocument.Region)
|
2022-10-27 05:04:23 -04:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2022-11-02 10:19:13 -04:00
|
|
|
func getEC2Client(ctx context.Context, region string) (awsMetadataAPI, error) {
|
2022-11-15 09:40:49 -05:00
|
|
|
client, err := awsConfig.LoadDefaultConfig(ctx, awsConfig.WithRegion(region))
|
2022-10-27 05:04:23 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return ec2.NewFromConfig(client), nil
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|
|
|
|
|
2022-10-27 05:04:23 -04:00
|
|
|
type awsMetadataAPI interface {
|
|
|
|
DescribeImages(ctx context.Context, params *ec2.DescribeImagesInput, optFns ...func(*ec2.Options)) (*ec2.DescribeImagesOutput, error)
|
2022-03-22 11:03:15 -04:00
|
|
|
}
|