From 8d1f326e2a06d12ecca5eb125c3b3aa210c26d2f Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Wed, 28 Aug 2024 16:02:30 -0700 Subject: [PATCH 1/3] unit test using escape hatch to scope down OAC Key policy permission --- .../lib/s3-bucket-origin.ts | 2 - .../test/s3-bucket-origin.test.ts | 84 ++++++++++++++++++- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts b/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts index 3758258ed1c64..dd8690c7d1e2e 100644 --- a/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts +++ b/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts @@ -167,8 +167,6 @@ export abstract class S3BucketOrigin extends cloudfront.OriginBase { /** * Create a S3 Origin with Origin Access Identity (OAI) configured - * OAI is a legacy feature and we **strongly** recommend you to use OAC via `withOriginAccessControl()` - * unless it is not supported in your required region (e.g. China regions). */ public static withOriginAccessIdentity(bucket: IBucket, props?: S3BucketOriginWithOAIProps): cloudfront.IOrigin { return new class extends S3BucketOrigin { diff --git a/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts b/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts index 0cacb357aa841..c94979eefc775 100644 --- a/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts @@ -383,6 +383,83 @@ describe('S3BucketOrigin', () => { 'a wildcard is used to match all Distribution IDs in Key policy condition.\n' + 'To further scope down the policy for best security practices, see the "Using OAC for a SSE-KMS encrypted S3 origin" section in the module README. [ack: @aws-cdk/aws-cloudfront-origins:wildcardKeyPolicyForOac]'); }); + + it('should allow users to use escape hatch to scope down KMS key policy to specific distribution id', () => { + const stack = new Stack(); + const kmsKey = new kms.Key(stack, 'myKey'); + const bucket = new s3.Bucket(stack, 'myEncryptedBucket', { + encryption: s3.BucketEncryption.KMS, + encryptionKey: kmsKey, + objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED, + }); + new cloudfront.Distribution(stack, 'MyDistributionA', { + defaultBehavior: { origin: origins.S3BucketOrigin.withOriginAccessControl(bucket) }, + }); + + // assuming user now know the Distribution ID and want to use escape hatch to scope down the key policy + const distributionId = 'SomeDistributionId'; + const finalKeyPolicy = { + Statement: [ + { + Action: 'kms:*', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':iam::', + { + Ref: 'AWS::AccountId', + }, + ':root', + ], + ], + }, + }, + Resource: '*', + }, + { + Action: 'kms:Decrypt', + Condition: { + StringLike: { + 'AWS:SourceArn': { + 'Fn::Join': [ + '', + [ + 'arn:', + { + Ref: 'AWS::Partition', + }, + ':cloudfront::', + { + Ref: 'AWS::AccountId', + }, + `:distribution/${distributionId}`, + ], + ], + }, + }, + }, + Effect: 'Allow', + Principal: { + Service: 'cloudfront.amazonaws.com', + }, + Resource: '*', + }, + ], + Version: '2012-10-17', + }; + (kmsKey.node.defaultChild as kms.CfnKey).keyPolicy = finalKeyPolicy; + + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { + KeyPolicy: finalKeyPolicy, + }); + }); }); describe('when attaching to a multiple distribution', () => { @@ -686,6 +763,7 @@ describe('S3BucketOrigin', () => { }); }); }); + describe('when specifying READ, WRITE, and DELETE origin access levels', () => { it('should add the correct permissions to bucket policy', () => { const stack = new Stack(); @@ -693,7 +771,7 @@ describe('S3BucketOrigin', () => { const origin = origins.S3BucketOrigin.withOriginAccessControl(bucket, { originAccessLevels: [cloudfront.AccessLevel.READ, cloudfront.AccessLevel.WRITE, cloudfront.AccessLevel.DELETE], }); - const distribution = new cloudfront.Distribution(stack, 'MyDistribution', { + new cloudfront.Distribution(stack, 'MyDistribution', { defaultBehavior: { origin }, }); Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { @@ -750,8 +828,8 @@ describe('S3BucketOrigin', () => { ], }, }); - }) - }) + }); + }); }); describe('withOriginAccessIdentity', () => { From 06b471a6b572d5ad42e39fb6f592d0bae902457f Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Wed, 28 Aug 2024 16:02:56 -0700 Subject: [PATCH 2/3] liniting fix --- .../aws-cloudfront-origins/test/s3-bucket-origin.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts b/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts index c94979eefc775..d17541ffcae7d 100644 --- a/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts +++ b/packages/aws-cdk-lib/aws-cloudfront-origins/test/s3-bucket-origin.test.ts @@ -455,7 +455,7 @@ describe('S3BucketOrigin', () => { Version: '2012-10-17', }; (kmsKey.node.defaultChild as kms.CfnKey).keyPolicy = finalKeyPolicy; - + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: finalKeyPolicy, }); From e146ecf4f6d5534d3396ae76718f92ae2bfef339 Mon Sep 17 00:00:00 2001 From: Samson Keung Date: Wed, 28 Aug 2024 23:18:36 -0700 Subject: [PATCH 3/3] revert accidentally deleted doc string --- .../aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts b/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts index dd8690c7d1e2e..3758258ed1c64 100644 --- a/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts +++ b/packages/aws-cdk-lib/aws-cloudfront-origins/lib/s3-bucket-origin.ts @@ -167,6 +167,8 @@ export abstract class S3BucketOrigin extends cloudfront.OriginBase { /** * Create a S3 Origin with Origin Access Identity (OAI) configured + * OAI is a legacy feature and we **strongly** recommend you to use OAC via `withOriginAccessControl()` + * unless it is not supported in your required region (e.g. China regions). */ public static withOriginAccessIdentity(bucket: IBucket, props?: S3BucketOriginWithOAIProps): cloudfront.IOrigin { return new class extends S3BucketOrigin {