(aws-cdk): IAM role created by CDK Bootstrap is not following AWS best practices
- 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
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