Securing the AWS CloudFormation Supply Chain!

An overview on how the cloud industry can help secure the supply chain for AWS CloudFormation templates.

Posted by Steven Tan on 30th September 2024

Introduction

As an engineer working with AWS, you should be familiar with the concept of pull requests and peer reviews. These are generally quite simple to perform when given minor code changes or infrastructure as code changes to review.

But what happens when an entire AWS CloudFormation template is given to you to review and deploy to AWS? The engineer providing the CloudFormation template says it came from Vendor A, but how can you confirm this? Multiple risks can play out in this scenario:

  1. The vendor has given your engineer a template, and they have modified it
  2. The source of the template is not actually from the vendor
  3. The CloudFormation template has changed hands multiple times, and your engineer believes it is unmodified.

Supply Chain Attacks

This is an example of a simple supply chain attack, where the file you are receiving has been altered somewhere along the way and could now be malicious. This alteration could be done anywhere and as simple as:

  1. Changing the AWS Account ID for that cross-account role
  2. Changing a third-party code reference, like in AWS Lambda Layers
  3. Changing an AMI ID to point to a modified one

All of these could compromise your infrastructure, and it would be difficult to tell without deeply investigating each ID you have been provided. Even then, there is a chance that not all of these IDs are well-documented or even publicly available.

The Solution

GPG provides an effortless way to digitally sign files, solving the technical challenge of authenticating that the file you have received is unmodified. However, this method has trust issues, as anybody can sign a file and say it came from and was signed by "Vendor A.". A quick way to solve this is for "Vendor A" to publish their GPG public key on their main website and documentation for people to download the keys and verify the file's authenticity.

Testing and Proof of Concept

The quickest way to test this is to go to your local computer and generate a key. I use the GPG Suite application to manage my keys. Once you have generated a key, let's test this against a simple CloudFormation template:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'A simple cross-account role to allow sktan to access your AWS Account'
Resources:
  FullAdminRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: "sktan-full-admin"
      Policies:
          - PolicyName: "FullAdminAccess"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action: "*"
                  Resource: "*"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal: 
              "AWS": "arn:aws:iam::123456789012:root"
            Action:
              - sts:AssumeRole

Save this file as admin-iam-role-original.yml. You can now sign the file using the detached signature option to provide a separate .sig file for your CloudFormation template; this is done by running the following command on your CLI:

sktan ➜ ~/repos/aws-cfn-supplychain $ gpg --output admin-iam-role-original.sig --detach-sig admin-iam-role-original.yml 

You will notice a .sig file now exists in the same folder as your CloudFormation template. Since you are the one who created the key, you will be able to check the signature to see if it matches the file:

sktan ➜ ~/repos/aws-cfn-supplychain $ gpg --verify admin-iam-role-original.sig admin-iam-role-original.yml
gpg: Signature made Mon 30 Sep 23:19:38 2024 AEST
gpg:                using RSA key CA91DFD4A2B06482A8366AF0F3BA8FDA98FB5D7E
gpg: Good signature from "Steven Tan <[email protected]>" [ultimate]

To test this against an exported GPG key, you can export your public key and then check the signature from that:

sktan ➜ ~/repos/aws-cfn-supplychain $ gpg --dearmor sktan.asc 
sktan ➜ ~/repos/aws-cfn-supplychain $ gpg --batch --no-default-keyring --keyring ./sktan.asc.gpg --verify admin-iam-role-original.sig admin-iam-role-original.yml 
gpg: Signature made Mon 30 Sep 23:19:38 2024 AEST
gpg:                using RSA key CA91DFD4A2B06482A8366AF0F3BA8FDA98FB5D7E
gpg: Good signature from "Steven Tan <[email protected]>" [ultimate]

If you change the CloudFormation template (i.e the AWS Account ID to a different AWS account and try to re-verify with the original signature), the signature validation will fail:

sktan ➜ ~/repos/aws-cfn-supplychain $ gpg --batch --no-default-keyring --keyring ./sktan.gpg.gpg --verify admin-iam-role-original.sig admin-iam-role-modified.yml 
gpg: Signature made Mon 30 Sep 23:19:38 2024 AEST
gpg:                using RSA key CA91DFD4A2B06482A8366AF0F3BA8FDA98FB5D7E
gpg: BAD signature from "Steven Tan <[email protected]>" [ultimate]

Conclusion

After running the commands above, we can see that the supply chain for CloudFormation templates can be secured, and we can validate the origin of a template with less investigative research on the origins of a given template.

To further automate this process, GitHub Actions can be used to continuously run the GPG verification on each CloudFormation template provided by 3rd party vendors, providing assurance every time a pull request is raised.