AWS CDK: Principle of Least Privilege
Tags: aws, security, cloud, tutorial
Published: 2023-09-29 14:51:10

## CDK Deploy

AWS CDK creates multiple roles at bootstrap time which allows CDK to deploy infrastructure on your behalf using a **CloudFormation** deployment. This can be kicked off by a developer or by an automated system like a pipeline. 

In order to deploy, the actor needs the permissions to assume the created CDK roles:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "arn:aws:iam::*:role/cdk-*"
            ]
        }
    ]
}
```

With this permission you have everything you need to deploy your stacks.

## Bootstrap

This post is to address the permissions required for `cdk deploy`, however, I think it is worth looking at the permissions required to bootstrap an environment. Of course this step is only required once per account for each region so once you have completed this, you won't need these permissions again.

The permissions are as follows:

Permissions to deploy the CDK bootstrap CloudFormation stack.
```
{
    "Effect": "Allow",
    "Action": [
        "cloudformation:CreateChangeSet",
        "cloudformation:DeleteChangeSet",
        "cloudformation:DeleteStack",
        "cloudformation:DescribeChangeSet",
        "cloudformation:DescribeStacks",
        "cloudformation:DescribeStackEvents",
        "cloudformation:ExecuteChangeSet",
        "cloudformation:GetTemplate"
    ],
    "Resource": [
        "arn:aws:cloudformation:eu-west-1:112233445566:stack/CDKToolkit/*"
    ]
}
```

Permissions to create the CDK bootstrap roles we mentioned above.
```
{
    "Effect": "Allow",
    "Action": [
        "iam:AttachRolePolicy",
        "iam:CreateRole",
        "iam:DeleteRole",
        "iam:DeleteRolePolicy",
        "iam:DetachRolePolicy",
        "iam:GetRole",
        "iam:GetRolePolicy",
        "iam:PutRolePolicy",
        "iam:TagRole"
    ],
    "Resource": [
        "arn:aws:iam::112233445566:role/cdk-hnb659fds-cfn-exec-role-*",
        "arn:aws:iam::112233445566:role/cdk-hnb659fds-file-publishing-role-*",
        "arn:aws:iam::112233445566:role/cdk-hnb659fds-image-publishing-role-*",
        "arn:aws:iam::112233445566:role/cdk-hnb659fds-lookup-role-*",
        "arn:aws:iam::112233445566:role/cdk-hnb659fds-deploy-role-*"
    ]
}
```
Permissions to create the CDK bootstrap bucket. CDK uses this bucket to stage S3 assets in your application, such as Lambda function bundles and static assets in your frontend applications.
```
{
    "Effect": "Allow",
    "Action": [
        "s3:CreateBucket",
        "s3:DeleteBucketPolicy",
        "s3:GetEncryptionConfiguration",
        "s3:GetBucketPolicy",
        "s3:PutBucketPolicy",
        "s3:PutBucketVersioning",
        "s3:PutEncryptionConfiguration",
        "s3:PutLifecycleConfiguration",
        "s3:PutBucketPublicAccessBlock"
    ],
    "Resource": [
        "arn:aws:s3:::cdk-hnb659fds-assets-*"
    ]
}
```
Permissions to create CDK bootstrap ECR repository. CDK uses this repository to stage Docker images in your application.
```
{
    "Effect": "Allow",
    "Action": [
        "ecr:CreateRepository",
        "ecr:DeleteRepository",
        "ecr:DescribeRepositories",
        "ecr:PutLifecyclePolicy",
        "ecr:SetRepositoryPolicy"
    ],
    "Resource": [
        "arn:aws:ecr:eu-west-1:112233445566:repository/cdk-hnb659fds-container-assets-*"
    ]
}
```
Permissions to create CDK bootstrap version SSM parameter. The parameter stores the version of the deployed CDK bootstrap stack.
```
{
    "Effect": "Allow",
    "Action": [
        "ssm:DeleteParameter",
        "ssm:GetParameters",
        "ssm:PutParameter"
    ],
    "Resource": [
        "arn:aws:ssm:eu-west-1:112233445566:parameter/cdk-bootstrap/hnb659fds/version"
    ]
}
```

#### Execution Role Issues

The `exec` role that CDK creates has caused some problems for users as this role has a default of `AdministratorAccess`. For some users this is simply not possible for security reasons, understandably. 

There is an option at bootstrap time to instead pass the ARNs of **managed** policies:

> --cloudformation-execution-policies specifies the ARNs of managed policies that should be attached to the deployment role assumed by AWS CloudFormation during deployment of your stacks. By default, stacks are deployed with full administrator permissions using the AdministratorAccess policy.

For Example:
```
--cloudformation-execution-policies "arn:aws:iam::aws:policy/AWSLambda_FullAccess,arn:aws:iam::aws:policy/AWSCodeDeployFullAccess".
```

## Caveats

### Testing

If you use your pipeline to also run some post deployment tests or to maybe inject some config into your deployed infrastucture you will need to carefully consider all the permissions you need for those steps. 

### Developer Experience

As a developer, you do not want to be continually denied to perform the things you need to do for your job. If your permisions are locked down too tightly then it can hinder your productivity. You may just need to be patient until you find the right balance between least privlege and productivity.

## Least Privilege Principle
It can take time and patience to follow this principle but for security reasons it is always worth sticking with it until you find that balance. If you use AWS Organisations within your company you can save some time by finding the balance once for your developers and then applying it across the board.