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 report, 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 report from the AWS Nitro Hypervisor. An attestation report consists of three main components: an attestation key signature from the secure enclave platform, the measurements of the enclave, and optional application-provided data (called "user data").

Diagram mapping each component of the attestation report to its use
AWS refers to this data as an "attestation document". For other secure enclave platforms, it is called an "attestation report". Throughout the Anjuna documentation, the term "attestation report" will be used.

Attestation report components

Attestation key signature

The attestation report 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 report 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 report 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 report 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 report.

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

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.

User data

"User data" is arbitrary data provided by the application, which is included as part of the attestation report. It is optional to include user data.

The user data can be used to demonstrate the provenance of the data: since only the enclave application can generate a valid attestation report, the user data must have been processed by the enclave.

The user data can also be used to establish freshness, which protects against replay attacks. A client can send a request that includes a nonce to the enclave application. The enclave returns a response that includes the same nonce, which is verified by the client. This ensures that an attacker cannot replay an old attestation report in order to impersonate the enclave application.

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 an 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.

Anjuna Nitro Attestation Endpoint

The Anjuna Nitro Runtime also exposes an internal HTTP endpoint for generating attestation reports. Your application can call this endpoint to dynamically create new attestation reports to prove its identity to clients.

For more info on the Attestation Endpoint, see Github: anjuna-security/go-nitro-attestation.

The rest of this section will focus on the boot-time secrets functionality.

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.