CDK Bootstrap with Minimal Permissions

Before you can start deploying AWS CDK applications, you need to take the essential step of bootstrapping your account. During that process, CDK will provision a few resources used for storing files and create roles required to perform deployments.

By default, it is a simple as running:

cdk bootstrap

The above command however, has the drawback that the default Cloudformation execution role is set to AdministratorAccess. Even though this will simplify permissions for you, it goes against AWS best practices of providing least privilege access. For example, even though your CDK app only implements ApiGateway with Lambda function integrations, the role would allow for spinning up EC2 instances.

Depending on how this role is planned on being used, you might not feel comfortable with full admin access, for example when using the role with GitHub's OIDC as a federated identity.

Defining a custom policy

Fortunately, it is very simple to customise the execution policy during the bootstrapping process. First we define our custom policy document. In the following example, we limit the permissions to ApiGateway, Lambda and Cloudwatch logs. Additionally, we prohibt access to the policy for the roles generated during bootstrapping.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["apigateway:*", "cloudwatch:*", "lambda:*", "logs:*", "ssm:*"],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "eu-west-1"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:*Role*",
        "iam:GetPolicy",
        "iam:CreatePolicy",
        "iam:DeletePolicy",
        "iam:*PolicyVersion*"
      ],
      "NotResource": [
        "arn:aws:iam::*:role/cdk-*",
        "arn:aws:iam::*:policy/cdkCfExecutionPolicy"
      ]
    }
  ]
}

Create the IAM policy

Now that we have our custom permissions defined, we can create the policy via the aws cli:

aws iam create-policy \
  --policy-name cdkCfExecutionPolicy \
  --policy-document file://cdkCfExecutionPolicy.json

CDK Bootstrap

Once the policy was successfully created we can reference it when running the cdk bootstrap command:

cdk bootstrap \
    aws://YOUR_ACCOUNT_ID/YOUR_REGION \
    --cloudformation-execution-policies "arn:aws:iam::YOUR_ACCOUNT_ID:policy/cdkCfExecutionPolicy"

Maintaining the policy

Since the permissions set in the policy will evolve with the resources defined in your CDK application, they will need to be updated as required. All you have to do here is edit the policy and make sure the changes are applied as the new default version.

For example:

aws iam create-policy-version \
  --policy-arn arn:aws:iam::YOUR_ACCOUNT_ID:policy/cdkCfExecutionPolicy \
  --policy-document file://cdkCfExecutionPolicy.json \
  --set-as-default

Even though this setup requires additional work and adds an extra maintenance step, I plan to use this approach for my side project which I'm currently in the process of migrating to a serverless architecture.

I will add additional blog posts in the future as I progress with the project.