aws / aws/aws-cdk

(aws-cdk): IAM role created by CDK Bootstrap is not following AWS best practices

Open
#19,380 15 comments 14 reactions 0 assignees View on GitHub
@aws-cdk/core bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
1d 19h
Merged PRs (30d)
71

Description

### What is the problem?

Security Hub best practices suggest that IAM roles should not be given encrypt/decrypt permissions to all KMS keys ([source](https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards-fsbp-controls.html#fsbp-kms-2)).

The deployment role created by CDK bootstrap does not meet this criteria.

### Reproduction Steps

Run `cdk bootstrap` and check the role policy on the deployment role (`cdk-hnb659fds-deploy-role-787743944430-eu-west-1`).

### What did you expect to happen?

The bootstrap process should generate roles which conform to AWS best practices.

### What actually happened?

The CDK bootstrap creates an IAM policy which contains a statement which looks like the following:
```json
{
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.eu-west-1.amazonaws.com"
}
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey",
"kms:Encrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*"
],
"Resource": "*",
"Effect": "Allow",
"Sid": "PipelineCrossAccountArtifactsKey"
},
```

This is therefore not following the best practice control guidelines within Security Hub which are proposed by AWS.

### CDK CLI Version

2.15.0 (build 151055e)

### Framework Version

_No response_

### Node.js Version

16.13.1

### OS

Ubuntu

### Language

Typescript, Python, .NET, Java, Go

### Language Version

_No response_

### Other information

Based on the template file (`packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml`) I believe that this can be resolved by changing the `PipelineCrossAccountArtifactsKey` statement in the `DeploymentActionRole` to use a single KMS resource instead of `*`.

For example:

```yml
- Sid: PipelineCrossAccountArtifactsKey
# Use keys only for the purposes of reading encrypted files from S3.
Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Resource: "*"
Condition:
StringEquals:
kms:ViaService:
Fn::Sub: s3.${AWS::Region}.amazonaws.com
```

could be updated to:

```yml
- Sid: PipelineCrossAccountArtifactsKey
# Use keys only for the purposes of reading encrypted files from S3.
Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
- kms:Encrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
Resource: "arn:aws:kms:*:*:alias/SOME_ALIAS_NAME"
Condition:
StringEquals:
kms:ViaService:
Fn::Sub: s3.${AWS::Region}.amazonaws.com
```

However, I do not know enough about the internal working of the CDK pipelines to understand if this could use an alias. Perhaps there's another way to achieve this?

Contributor guide

Open the contributing guide

Research direction

Start with packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml and inspect the PipelineCrossAccountArtifactsKey statement in DeploymentActionRole. Review how CDK Pipelines uses the deployment role and its KMS permissions before deciding whether the resource can be narrowed. Re-run cdk bootstrap and inspect the generated role policy; done means it satisfies the AWS best-practice control without breaking artifact deployment.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, infrastructure, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.