Attestation with Anjuna for AWS Nitro Enclaves

This section is a conceptual overview of how attestation, a critical security feature, is used in AWS Nitro Enclaves and the Anjuna Nitro Runtime.

Attestation for AWS Nitro Enclaves

Secure enclaves have the ability to generate an attestation document, a piece of data which cryptographically proves that an enclave is running with particular code inside.

Applications running in AWS Nitro Enclaves can request a signed attestation document from the AWS Nitro Hypervisor. An attestation document consists of two main components: an attestation key signature from the secure enclave platform, and the measurements of the enclave.

Diagram mapping each component of the attestation document to its use

Attestation document components

Attestation key signature

The attestation document contains a signature created by the secure enclave hardware platform’s attestation key. This cryptographic signing key is a private key in the enclave platform, in this case AWS Nitro. The secure enclave hardware enforces that this key is only accessible from legitimate secure enclaves.

A client can validate the signature on the attestation document using the corresponding public key, which is provided by the enclave platform operator, AWS. For instructions, see AWS documentation: Verifying the root of trust for AWS Nitro Enclaves.

An attestation document with a valid signature must originate from a secure enclave, because only secure enclaves have access to an attestation key. If any part of the attestation document has been modified, the signature will fail to validate because it was only valid for the original content. This means that it is not possible for an attacker to forge a fraudulent attestation document.

Measurements

Conceptually, a measurement is a cryptographic hash of the contents of an enclave. Because the entire enclave contents are an input to the hash function, if any part of the enclave changes - even a single bit in your code - the measurement will completely change. You can think of the measurements as a set of “fingerprints” for the identity of the enclave.

AWS Nitro Enclaves generate measurements for different parts of the enclave, like the full enclave, the IAM role for the instance, or a user-provided signing key. These measurements are stored in platform configuration registers (PCRs). See AWS documentation for descriptions of the different PCRs available for AWS Nitro Enclaves.

The following table describes the measurements (or "PCR values") included in the attestation document:

PCR Hash of Description

PCR0

Enclave image file

A contiguous measure of the contents of the image file, without the section data.

PCR1

Linux kernel and bootstrap

A contiguous measurement of the kernel and boot ramfs data.

PCR2

Application

A contiguous, in-order measurement of the user applications, without the boot ramfs .

PCR3

IAM role assigned to the parent instance

A contiguous measurement of the IAM role assigned to the parent instance. Ensures that the attestation process succeeds only when the parent instance has the correct IAM role.

PCR4

Instance ID of the parent instance

A contiguous measurement of the ID of the parent instance. Ensures that the process succeeds only when the parent instance has a specific instance ID.

PCR8

Enclave image file signing certificate

A measure of the signing certificate specified for the enclave image file. Ensures that the attestation process succeeds only when the enclave was booted from an enclave image file signed by a specific certificate.

A policy using any combinations of the PCR values above can be created to precisely define the enclaves that are allowed to perform operations on a specific AWS KMS key object.

AWS KMS integration

An authorized user can attach a policy to a specific AWS KMS key and restrict the usage of that key to AWS Nitro Enclaves with specific measurements. This mechanism ensures that sensitive data, when encrypted by correctly-configured AWS KMS keys, can only be decrypted by approved applications running in AWS Nitro Enclaves.

The following diagram shows three different applications trying to access a key in AWS KMS. After a cloud administrator in your organization configures the key to require attestation, AWS KMS will only grant access to your specific application running in an AWS Nitro Enclave.

Your cloud admin configures a KMS key to require an enclave with XYZ measurements. Only an enclave with XYZ measurements can access the key; other enclaves or applications outside enclaves cannot access it.

Anjuna Nitro Runtime boot-time secrets

The Anjuna Nitro Runtime builds on the AWS KMS integration for Nitro Enclaves to securely deliver secrets to your application at boot time. No changes to the application code are needed to use this feature.

At boot time, the Anjuna Nitro Runtime fetches the "Encrypted Configuration”, which is stored in an S3 bucket or local file. It is decrypted using an AWS KMS key that only the enclave can access. Then, the contents of the encrypted configuration are injected into the enclave as environment variables or files.

The encrypted configuration process fetches an encrypted blob from AWS S3, decrypts the blob using AWS KMS, and makes its contents available to the container as environment variables or files.

Each step in this process is protected by various forms of encryption, so the secret is never accessible by AWS or any party outside of the enclave. TLS 1.2 is used to protect data in transit. Additionally, client-side encryption ensures that the plaintext data is never visible to AWS or any other party outside of the enclave.

Using the Anjuna Nitro Runtime for this capability is more secure than traditional secret delivery using regular IAM policies and IAM roles. Consider a scenario where an attacker gains access to your application’s EC2 instance. If your application uses a service like AWS Secrets Manager, authenticated using only the IAM role, the attacker has the same permissions and is able to exfiltrate secrets. If your application uses the Anjuna Nitro Runtime boot-time secrets, the attacker is unable to generate a valid attestation quote, so they cannot exfiltrate those secrets - even though they have access to the parent instance and its IAM role.

Setting up an encrypted configuration

Anjuna provides a tool, anjuna-nitro-encrypt, which encrypts a configuration file and uploads the encrypted blob to an S3 bucket or stores it to a local file.

It uses the Amazon S3 Encryption Client to perform client-side encryption, which ensures that the plaintext data is never visible to AWS or entities with access to the S3 bucket or local data file.

Data is encrypted client-side using a wrapping key from AWS KMS, then uploaded to the provided S3 URI.

The following diagram shows how the client-side encryption (sometimes called “envelope encryption”) works:

An AWS KMS key generates a data encryption key (DEK). The plaintext data is encrypted using the DEK. The DEK itself is encrypted using the KMS key. The final encrypted blob is the combination of the KMS-encrypted DEK and the DEK-encrypted data.

The final encrypted blob is what is uploaded to the S3 bucket or alternatively stored to a local file.

After creating and uploading the blob, you can add its S3 URI to the uri of a s3 type encryptedConfig entry of the enclave configuration file and build an Enclave Image File (EIF).

You can set uri even if the S3 object does not exist yet, as long as the S3 object exists when you start the enclave.
An EIF is built from a Docker image, an optional signing key, and the enclave configuration file. The enclave configuration file contains an `attestedConfURL`.

Once you have an EIF, you can take its measurements and use them to restrict the usage of the AWS KMS key to only this specific enclave.

An AWS KMS key is configured by setting the `kms:RecipientAttestation:PCR0` Condition to match the EIF’s PCR0 measurement, '80cabd56…​'

Sequence diagram at boot time

At boot time, the Anjuna Nitro Runtime fetches the encrypted configuration file from S3, generates an attestation quote, decrypts the encrypted configuration file, and injects the given configuration to the container instance.

In the diagram below, E_k represents encryption with key k, and x || y represents the concatenation of x and y.

The Anjuna Nitro Runtime fetches an encrypted blob from S3 and unwraps several layers of encryption using KMS before injecting the configuration to the container instance.

Next steps

In the following sections, you will encrypt and upload secrets in an encrypted configuration file. Then, you will create an enclave configuration file so that your enclave will fetch and decrypt the secrets at boot time.