DEV Community

Cover image for Do not use default SAM CloudFormation Role for Production
Gabriel Koo for AWS Community Builders

Posted on

Do not use default SAM CloudFormation Role for Production

AWS CI/CD tools are simply cool, as they allow you to deploy your application within a few clicks, with a lot of supporting integrations and resources created for you.

I could still recall how fascinated I was when I provisioned my first SAM project that includes a Rest API and an AWS Lambda backend within a few clicks ⚡️ - you have an API endpoint hosted already without the need to setup a web server by yourself.

For most of the cases, when you are creating a hello world project from the documentation, guides, some blogs or articles, it usually suggests you to use their suggested roles - which is actually very risky 🔓.

A potential trap with using Infrastructure as Code tools like SAM

Let’s say I am creating a CD pipeline for deploying an AWS Serverless Application Model (SAM) with sam pipeline bootstrap, following this piece of documentation.

The guide is handy, as with a single command you can setup the entire CI/CD pipeline quickly, and you can also enjoy the benefit of having the latest features in your git branch deployed within a few minutes!

My focus here would be one of the arguments:

--cloudformation-execution-role TEXT The ARN of the IAM role to be assumed by the AWS CloudFormation service while deploying the application's stack. Provide only if you want to use your own role, otherwise the command will create one.

The description doesn't really warn you to use your own role, as well as any potential issues with leaving a default there. It will create a default role for you with the “default” permissions. This is actually disastrous for a production project, why? 🤔


When you run sam pipeline bootstrap / sam pipeline init, a CloudFormation template is generated and deployed and it contains several resources to make your CI/CD pipeline provisioned for you.

I created one with my Cloud9 shell, and it would look like this:
Resources created with sam cli

Among which, the CloudFormationExecutionRole is VERY DANGEROUS:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "*",
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

If you are not familiar with AWS IAM statements, it means this CloudFormation role can perform literally EVERYTHING, Including deleting everything in your account, or even provisioning any admin users, on your behalf; de facto an AWS version of sudo 🗝.

Say when your source control is compromised (say if you are using GitHub and you leaked your personal access token), bad actors can commit any bad code into your SAM template and they can create whatever resource as defined in the CloudFormation role as they want - that's how Infrastructure as Code (IaC) works!

One of these would be simply be define an IAM user with hardcoded password.

Does this sound too bad to be true? Let me demonstrate it now.

A quick proof of concept

It’s easy to ignore such hidden traps until a disaster really occurs - and you will surely regret.

Say for your repository, you forgot to setup default branch protection. Any colleague having access to your repo has push access to the main branch. Now let me try to use this vulnerability add an IAM user, with AdministratorAccess.

It’s as easy as adding the following CloudFormation / SAM resources in template.yml:

# template.yml

Resources:
  NewAdminUser:
    Type: AWS::IAM::User
    Properties:
      LoginProfile:
        # SECURITY WARNING: DO NOT COPY!
        Password: 'I-am-a-hardcoded-password'
        PasswordResetRequired: false
      Policies:
        - PolicyName: AdminRight
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Sid: Whatever
                Effect: Allow
                Action: '*'
                Resource: '*'
Enter fullscreen mode Exit fullscreen mode

Once this change is committed to git and picked by CodePipeline automatically 🤖, as part of the “legit” CI/CD process,
CI Pipeline doesn't check for malicious code by default

The new admin user would be created:
Malicious admin user created with ease

And of course, the hacker would be able to login and do whatever they want with your account:

Backdoor to your organization, thanks to unhardened CloudFormation role

Now your organization’s AWS account is at risk, could it be leaked data of data loss, or even being injected any further vulnerabilities 💸.


Remediations?

Any one of the following four remediations could help avoid the vulnerability I illustrated above, but of course it would be best if every one of them are fulfilled ☔️:

Locate the places in the workflow that are vulnerable

  1. Protect your version control repository (e.g. git) well, setup branch protection, enforce code reviews before merging into your primary branch, setup proper permissions with least privilege, etc.

  2. To be super secure, add an approval step if your are using CodePipeline. Conduct manual check again before every deployment in CI. Such a feature is also available for CircleCI, and CI providers like GitLab and Jenkins are also be catching up too.

  3. Continuously monitor and tweak your CI/CD roles with services IAM Access Advisor or IAM Access Analyzer. It's okay to have a vulnerable role when you first provision the pipeline, but when your pipeline runs for a while these tool will help you to refine the necessary permission that you only need. In my example, I can tell from Access Advisor that the CloudFormation role only needs permissions for Lambda, CloudFormation, S3 and IAM:
    Access Advisor tells your what your role exactly does

  4. Also as a general good practice, always look up the documentation, or try the IAM policy JSON editor in AWS Console. It will guide through you, for each IAM action, which kind of restrictions you can apply to your IAM Policy / Role. Always adopt the concept of least privilege to CI/CD users/roles to avoid any hacks from happening. For example if your pipeline needs to provision an SQS queue, you can try to allow only sqs:CreateQueue and sqs:DeleteQueue with specific queue names only. It will avoid the pipeline from being able to modify your other existing SQS queues:
    Refining IAM statements to only the necessary resources


P.S. If you are looking for a more "official" quick start for a CloudFormation role for SAM pipeline, the following example from AWS Samples might help:

https://github.com/aws-samples/aws-serverless-samfarm/blob/474489cdfbd5a800e383be6eb2a4a87294626e13/pipeline/pipeline-roles.yaml#L55-L87

It is already much better than putting a CloudFormation role with full access rights.


Credits: Cover Photo by George Becker.


Top comments (1)

Collapse
 
jilltheskank profile image
Jill Skank

Wait,

You specified a vulnerability at the top using IAM permissions, then at the bottom you gave the cloud Formation role permissions to IAM:

CloudFormation role only needs permissions for Lambda, CloudFormation, S3 and IAM

So what was the problem with the original access? is the mitigation just in github or code pipelines?

What was the point of this article?