AWS Public Sector Blog

Verify software supply chain security using AWS Nitro cryptographic verification

As organizations increasingly adopt containerized workloads, verifying the integrity of the platform and pipeline infrastructure is critical to maintain a secure DevSecOps posture. For public sector organizations, this extends well beyond a best practice. Executive Order 14028 and subsequent federal guidance direct agencies to ensure the security and integrity of their software supply chain, and frameworks such as Supply-chain Levels for Software Artifacts (SLSA) establish verifiable build provenance as a key maturity benchmark. However, none of these controls can be fully satisfied without assurance that the underlying compute environment itself is trustworthy.

This post demonstrates how to use Amazon Elastic Compute Cloud (Amazon EC2) instance attestation to produce cryptographically verifiable Amazon Machine Images (AMIs) for your DevSecOps platform and pipeline—the software factory that builds and delivers your workloads.

Without cryptographic verification of the boot process, organizations can’t definitively prove that their infrastructure started from a trusted, unmodified state. This trust gap creates an opening where malicious actors could compromise systems before they begin running workloads.

EC2 instance attestation, powered by Nitro Trusted Platform Module (NitroTPM), provides a hardware-rooted cryptographic foundation. With it, you can verify that your container platforms and continuous integration and continuous delivery (CI/CD) pipelines booted from a trusted, unmodified state.

Most supply chain security controls operate above the platform layer, for example, container image scanning, software bill of materials (SBOMs), image signing, and admission controllers that enforce policies at deployment time. These controls all depend on the same unverified assumption: the hosting environment running the builds and workloads hasn’t been tampered with.

Your containers and CI/CD platform all run on top of the same foundation that includes firmware, a bootloader, a kernel, and a container runtime. If any of these components are compromised, the integrity of your software supply chain is threatened. Think of the EC2 instance as the factory floor and your CI/CD pipeline as the assembly line. If someone tampers with the factory floor, the integrity of everything coming off the assembly line can no longer be considered reliable.

The following graphic represents this structure.

Graphic illustrating the structure described in the text.

Figure 1: Graphic illustrating that container runtime, kernel, bootloader, and firmware are part of the host platform on which the CI/CD pipeline runs. The CI/CD pipeline, which is scanned, supports image scanning, SBOMs, image signing, and admission controllers.

Amazon Web Services (AWS) already protects AWS EC2 infrastructure at multiple levels. The Nitro Hypervisor uses Unified Extensible Firmware Interface (UEFI) Secure Boot, and AMIs are integrity-protected when stored. However, these protections focus on AMI integrity at rest—they don’t verify the runtime state. EC2 instance attestation addresses this gap by cryptographically confirming the integrity of the boot process and kernel before workloads begin running. An AMI ID identifies which image was launched, and attestation goes further by proving what executed during boot. EC2 instance attestation closes that gap by combining two capabilities:

  • NitroTPM – Provides tamper-resistant Platform Configuration Registers (PCRs) that capture cryptographic measurements of each stage of the boot process.
  • Attestable AMIs – Images built specifically for attestation, where the build process generates reference measurements (the expected PCR values for the firmware, bootloader, kernel, and filesystem of that AMI).

EC2 instance attestation currently supports Linux-based AMIs. EC2 instance attestation captures three PCR values that together validate the full boot chain:

  • PCR4 (boot manager code) – A hash of all binaries executed by the UEFI environment during boot. This measurement helps validate that the bootloader and kernel are unmodified.
  • PCR7 (Secure Boot policy) – A hash of the UEFI Secure Boot policy. This measurement helps validate that only binaries signed by a trusted certificate were permitted to execute.
  • PCR12 (boot command line) – A hash of the command line passed to the boot binary. This measurement helps validate that the kernel parameters weren’t altered.

These reference measurements represent your known-good baseline. At runtime, you compare the actual PCR values against these reference measurements to determine if anything has changed.

Closing the trust gap requires two complementary layers: verifying the infrastructure your workloads run on and verifying the software those workloads execute. Together, they establish an unbroken chain of trust from the moment an instance boots to when a container runs.

The following walkthrough covers two practical applications:

  • Attested CI/CD build hosts – Cryptographically proving your pipeline infrastructure boots from a verified, unmodified state.
  • Attested Amazon EKS worker nodes – Extending boot-time trust to the container workloads running on those nodes.

Build and use an attested CI/CD host

You build attestable AMIs using image building tools that produce a unified kernel image (UKI) with UEFI boot support. AWS provides sample image descriptions for both Amazon Linux 2023 (AL2023) and KIWI NG. The key requirements are UEFI boot mode and NitroTPM v2.0 support.

Use the following pattern to build an attestable AMI:

  1. Source the image configuration from a Git repository.
  2. Build the image on an EC2 instance.
  3. Register the result as an AMI with NitroTPM v2.0 and UEFI enabled.
  4. Store the AMI alongside its reference PCR measurements.

The following diagram illustrates this pattern. Creation of attested AMIs with integrity verification is automated. Git users trigger builds using repository and pipeline triggers (Git push or scheduled), which feed to AWS CodeBuild. CodeBuild creates a raw disk image, stores it with PCR measurements, and registers it as an attestable AMI. The attested AMI serves as a base image for the CI/CD pipeline (clone, build, test, scan, SBOM or sign, push) with security scanning tools (Amazon Inspector), producing a container in Amazon Elastic Container Registry (Amazon ECR). The container deploys to a deployed app running on trusted runtime, with continuous scanning providing runtime verification.

Diagram illustrating the deployment pipeline described in the text.

Figure 2: Deployment pipeline

During the build, the nitro-tpm-pcr-compute utility generates reference measurements from the UKI. These are the known-good baseline values for built AMI.

The reference measurements generated during the AMI build can be stored in any secure location that your verification process can access, such as Amazon Simple Storage Service (Amazon S3), AWS Secrets Manager, or Parameter Store, a capability of AWS Systems Manager. The choice depends on your access control and operational requirements. What matters is that the reference store is managed independently from the build pipeline, so that a compromise of the pipeline alone can’t alter both the AMI and its expected measurements.

In this example using the KIWI NG build tool, the reference measurements are uploaded to Amazon S3:

aws s3 cp /tmp/kiwi-output/pcr_measurements.json \

  "s3://${ARTIFACT_BUCKET}/builds/${BUILD_ID}/pcr_measurements.json"

After an instance boots from the attested AMI, you can compare its actual PCR values against the stored reference measurements. The Nitro Hypervisor generates and signs a cryptographic attestation document containing the PCR values that NitroTPM recorded during boot. If the values match, the instance booted with the expected chain and the compute foundation is trusted. If the values differ—through tampering or an unauthorized AMI update—The instance should be treated as compromised and isolated immediately.

To perform this verification, read the actual PCR values from the instance’s NitroTPM and compare them against the reference measurements stored during the AMI build. Perform a case-insensitive comparison of the SHA-384 hexadecimal values. If PCR4 and PCR12 match the reference, standard boot is validated. If PCR7 matches, Secure Boot is validated. If any value differs, the boot chain was modified.

You can retrieve these values locally on the instance or remotely through AWS Systems Manager.

To read PCR values directly on the instance:

cat /sys/class/tpm/tpm0/pcr-sha384/4    # PCR4 — Boot Manager Code

 

cat /sys/class/tpm/tpm0/pcr-sha384/7    # PCR7 — Secure Boot Policy

 

cat /sys/class/tpm/tpm0/pcr-sha384/12   # PCR12 — Command Line

To remotely read PCR values using the Systems Manager Run Command:

aws ssm send-command \

  --instance-ids i-0123456789abcdef0 \

  --document-name "AWS-RunShellScript" \

  --parameters 'commands=["cat /sys/class/tpm/tpm0/pcr-sha384/4","cat /sys/class/tpm/tpm0/pcr-sha384/7","cat /sys/class/tpm/tpm0/pcr-sha384/12"]'

To automate this, you can schedule an AWS Lambda function that retrieves PCR values from your fleet through Systems Manager, compares them against the stored reference measurements, and performs downstream actions such as raising an alert or stopping instances whose measurements don’t match. To move beyond detection to enforcement with attested values, you can configure AWS Key Management Service (AWS KMS) key policies with AWS Identity and Access Management (IAM) condition keys that require matching PCR values. You can restrict cryptographic operations, such as decrypting secrets, to only instances that present a valid attestation document with matching PCR values. For example, a build agent or worker node that boots from a tampered AMI can’t access the secrets it needs to function.

The following example key policy allows the kms:Decrypt operation only when the request includes an attestation document with a matching PCR4 and PCR12 value:

{

  "Sid": "AllowOnlyAttestedInstances",

  "Effect": "Allow",

  "Principal": {

    "AWS": "arn:aws:iam::111122223333:role/workload-role"

  },

  "Action": "kms:Decrypt",

  "Resource": "*",

  "Condition": {

    "StringEqualsIgnoreCase": {

      "kms:RecipientAttestation:NitroTPMPCR4": "9378e9b913cb13b4...",

      "kms:RecipientAttestation:NitroTPMPCR12": "a1b2c3d4e5f6....."

    }

  }

}

Note that the PCR hash values must be written directly into the key policy, because AWS KMS checks the condition keys (such as kms:RecipientAttestation:NitroTPMPCR4) against the attestation document and can’t reference values stored in Amazon S3 or AWS Secrets Manager. These hashes are public by design: knowing them doesn’t grant access, because only an instance that actually booted the matching image can decrypt. With this policy, an instance must attach a valid NitroTPM attestation document to its AWS KMS request. AWS KMS validates the PCR values against the key policy. If the values match, the operation proceeds. If they differ or if no attestation document is provided, AWS KMS denies the request. This creates a cryptographic enforcement boundary without any manual verification step.

The attested AMI serves as the foundational base image for the CI/CD pipeline. As the first step in each pipeline task, the system validates the integrity of the underlying base image before proceeding with any subsequent operations. This verification confirms that the AMI hasn’t been tampered with since attestation and that the compute environment remains in a known-good state.

By enforcing this check at the outset of every pipeline execution, organizations establish a continuous chain of trust that extends from the hardware root of trust through the operating system and into the build process itself. If the attestation validation fails, the pipeline halts immediately, preventing any workload from executing on a potentially compromised environment. This approach keeps the foundational security of the build infrastructure intact and trustworthy, providing auditable assurance that artifacts produced by the pipeline originate from a verified, unmodified compute environment.

Attest and verify Amazon EKS worker nodes

The same attestation process used to verify CI/CD build hosts applies directly to Amazon Elastic Kubernetes Service (Amazon EKS) worker nodes. If you use pre-hardened base images, those images address software-layer concerns like patching and Center for Internet Security (CIS) compliance, but they don’t cryptographically verify the boot process. EC2 instance attestation adds that infrastructure-layer proof regardless of which base image you choose.

Your worker nodes are EC2 instances, and they boot from AMIs using the same firmware, bootloader, and kernel chain. By building your self-managed EKS node AMIs as attestable images, you can cryptographically verify that every worker node in your cluster booted from a known-good, unmodified state before it joins the cluster and begins running pods.

This approach applies only to self-managed node groups, where you control the AMI. It does not apply to Amazon EKS Auto Mode, which runs on AWS vended Bottlerocket images that you can’t rebuild or customize, so attestable node AMIs can’t be produced for Auto Mode clusters. While attestation doesn’t apply to Auto Mode, its immutable Bottlerocket-based architecture, with a read-only root filesystem, provides equivalent supply chain integrity assurances by design, mitigating risks such as a modified bootloader, kernel, or runtime.

You’ll use the same pattern we described in the previous application, applied to your EKS worker nodes. There are three steps:

  1. Build the AMI with reference measurements –Construct the worker node AMI through a reproducible pipeline so that its firmware, bootloader, and kernel produce known, deterministic PCR values. These reference measurements become the baseline that defines a known-good node.
  2. Store the measurements independently – Upload the reference PCRs to a secure location outside the node, such as Amazon S3 or Parameter Store, managed independently from the node provisioning pipeline. This prevents a compromised node from presenting its own tampered values as the source of truth.
  3. Verify at node startup, before the node accepts workloads – Integrate the attestation check into the node’s bootstrap script so it runs during initialization, before the kubelet registers the node with the control plane. A node that fails verification never joins the cluster, avoiding wasted provisioning and eliminating windows where an untrusted node is a member of the cluster.

The following example bootstrap script retrieves the reference measurements and compares them against the node’s live PCR values before registering with the cluster:

# Read reference PCR values from Parameter Store

 

EXPECTED_PCR4=$(aws ssm get-parameter \

--name "/eks/worker-ami/pcr4" \

--query "Parameter.Value" --output text)

 

ACTUAL_PCR4=$(cat /sys/class/tpm/tpm0/pcr-sha384/4)

 

if [ "${EXPECTED_PCR4,,}" != "${ACTUAL_PCR4,,}" ]; then

 

echo "Attestation failed: PCR4 mismatch" | logger -t attestation

 

shutdown -h now

 

fi

 

# PCR values match — proceed with kubelet registration

 

/etc/eks/bootstrap.sh "${CLUSTER_NAME}"

The result is the same chain of trust you built in Application 1: your cluster only admits nodes that can cryptographically prove they booted from an unmodified, known-good state, pushing the trust boundary down to the host platform rather than the application layer.

Conclusion

Your CI/CD platform and pipeline, your software factory, rests on a foundation that most supply chain controls take on faith. For organizations pursuing the highest level of supply chain assurance, EC2 instance attestation removes that assumption by cryptographically verifying that your infrastructure started from a known-good state and remained unmodified.

To get started, explore the sample attestable AMI image descriptions and the EC2 instance attestation documentation.

Cheyenne Lopez

Cheyenne Lopez

Cheyenne Lopez is a Solutions Architect at Amazon Web Services (AWS) supporting Army customers and DoD cloud initiatives. She specializes in container and Kubernetes security, helping organizations design and deploy secure, scalable cloud-native architectures. With deep expertise in compliance-sensitive environments, Cheyenne works with customers to implement security best practices across their container workloads.

Bardan Khatri

Bardan Khatri

Bardan Khatri is a Solutions Architect at Amazon Web Services (AWS) supporting the U.S. Army’s adoption of cloud technologies at the tactical edge. He partnered closely with his ARMY customer to build their enterprise DevSecOps platform (DSOP), providing architectural recommendations that underpin secure software delivery at scale for the ARMY.

Hari Malayappan

Hari Malayappan

Hari is a senior solutions architect for the Department of Defense (DOD) at Amazon Web Services (AWS). Hari has more than 20 years of platform services experience and is interested in containers, secure software factory, and modern data architectures. He enjoys camping trips and playing basketball with his kids.