Skip to content

Commit 274c3d5

Browse files
authored
fix(bootstrap): remove Security Hub finding KMS.2 (#24588)
**NOTE:** This PR bumps the version of the bootstrap stack to `16`, but there is no need to update your bootstrap stacks, unless it is to get rid of the Security Hub finding; this change has no effect on the functionality of any CDK app deployed to the environment. [Security Hub finding KMS.2](https://docs.aws.amazon.com/securityhub/latest/userguide/kms-controls.html#kms-2) says: > The control fails if the policy is open enough to allow kms:Decrypt or kms:ReEncryptFrom actions on any arbitrary KMS key. > > [...] > > The control only checks KMS keys in the Resource element and doesn't take into account any conditionals in the Condition element of a policy. This control is a "defense in depth" control. It does not mitigate any attack by itself, and there is no actual security impact from the current configuration of our policies. However, customers are anxious about the Security Hub findings reported on resources we create for them. Therefore, we turn the `Resources: *` into a list of wildcard ARNs, one for each trusted account. This should satisify Security Hub without breaking the functionality of the bootstrap resources (as this statement is only used for cross-account CodePipeline deployments using CDK Pipelines). The CloudFormation expression we use to turn a list of account IDs into a list of ARNs is quite crazy. To turn `['1111', '2222', '3333']` into `['arn:aws:kms:*:1111:*', 'arn:aws:kms:*:2222:*', 'arn:aws:kms:*:3333:*']` we do the following: * Skip the entire statement if the list is empty * Use the following equivalence if the list has at least one element (E1 cannot be expressed in CloudFormation but E2 can): ``` (E1) xs.map(x => PREFIX + x + SUFFIX).join(SEP) <==> { assuming xs.length >= 1 } (E2) PREFIX + xs.join(SUFFIX + SEP + PREFIX) + SUFFIX ``` * Finally split the string on the separator to come up with an array of elements. I would have used `${AWS::Region}` instead of allowing all regions, but `{ Fn::Join }` doesn't allow using intrinsics in its separator. I tested the new template using a CDK Pipeline that deploys in-region, cross-region, cross-account and cross-account-cross-region. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent b935f2b commit 274c3d5

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml

+30-15
Original file line numberDiff line numberDiff line change
@@ -455,20 +455,35 @@ Resources:
455455
StringNotEquals:
456456
s3:ResourceAccount:
457457
Ref: 'AWS::AccountId'
458-
- Sid: PipelineCrossAccountArtifactsKey
459-
# Use keys only for the purposes of reading encrypted files from S3.
460-
Effect: Allow
461-
Action:
462-
- kms:Decrypt
463-
- kms:DescribeKey
464-
- kms:Encrypt
465-
- kms:ReEncrypt*
466-
- kms:GenerateDataKey*
467-
Resource: "*"
468-
Condition:
469-
StringEquals:
470-
kms:ViaService:
471-
Fn::Sub: s3.${AWS::Region}.amazonaws.com
458+
- Fn::If:
459+
- HasTrustedAccounts
460+
- Sid: PipelineCrossAccountArtifactsKey
461+
# Use keys only for the purposes of reading encrypted files from S3.
462+
Effect: Allow
463+
Action:
464+
- kms:Decrypt
465+
- kms:DescribeKey
466+
- kms:Encrypt
467+
- kms:ReEncrypt*
468+
- kms:GenerateDataKey*
469+
470+
# SecurityHub's rule KMS.2 complains if we put a '*' here, so instead we'll
471+
# turn the list of trusted accountIds ['111', '222', ...] into a list of
472+
# wildcard ARNS: ['arn:aws:kms:*:1111:*', 'arn:aws:kms:*:2222:*', ...].
473+
Resource:
474+
Fn::Split:
475+
- "|"
476+
- Fn::Sub:
477+
- "arn:aws:kms:*:${JoinedAccounts}:*"
478+
- JoinedAccounts:
479+
Fn::Join:
480+
- ":*|arn:aws:kms:*:"
481+
- { Ref: TrustedAccounts }
482+
Condition:
483+
StringEquals:
484+
kms:ViaService:
485+
Fn::Sub: s3.${AWS::Region}.amazonaws.com
486+
- { Ref: AWS::NoValue }
472487
- Action: iam:PassRole
473488
Resource:
474489
Fn::Sub: "${CloudFormationExecutionRole.Arn}"
@@ -600,7 +615,7 @@ Resources:
600615
Type: String
601616
Name:
602617
Fn::Sub: '/cdk-bootstrap/${Qualifier}/version'
603-
Value: '15'
618+
Value: '16'
604619
Outputs:
605620
BucketName:
606621
Description: The name of the S3 bucket owned by the CDK toolkit stack

0 commit comments

Comments
 (0)