From e9e3c071bf5a3c6e84d425355752f460d7014d73 Mon Sep 17 00:00:00 2001 From: Thomas Wirth Date: Wed, 23 Sep 2020 09:32:36 +0200 Subject: [PATCH] feat(cloudfront-origins): customize origin access identity in s3origin Adds support for passing in a identity as it is possible in the CloudFrontWebDistribution closes #9859 --- .../aws-cloudfront-origins/lib/s3-origin.ts | 13 ++++- .../test/integ.s3-origin-oai.expected.json | 58 +++++++++++++++++++ .../test/integ.s3-origin-oai.ts | 18 ++++++ .../test/s3-origin.test.ts | 19 +++++- 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.expected.json create mode 100644 packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.ts diff --git a/packages/@aws-cdk/aws-cloudfront-origins/lib/s3-origin.ts b/packages/@aws-cdk/aws-cloudfront-origins/lib/s3-origin.ts index 04c3d5175cace..6c70fb742336c 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/lib/s3-origin.ts +++ b/packages/@aws-cdk/aws-cloudfront-origins/lib/s3-origin.ts @@ -16,6 +16,12 @@ export interface S3OriginProps { * @default '/' */ readonly originPath?: string; + /** + * An optional Origin Access Identity of the origin identity cloudfront will use when calling your s3 bucket. + * + * @default No Origin Access Identity which requires the S3 bucket to be public accessible + */ + readonly originAccessIdentity?: cloudfront.IOriginAccessIdentity; } /** @@ -50,10 +56,13 @@ export class S3Origin implements cloudfront.IOrigin { * Contains additional logic around bucket permissions and origin access identities. */ class S3BucketOrigin extends cloudfront.OriginBase { - private originAccessIdentity!: cloudfront.OriginAccessIdentity; + private originAccessIdentity!: cloudfront.OriginAccessIdentity | cloudfront.IOriginAccessIdentity; - constructor(private readonly bucket: s3.IBucket, props: S3OriginProps) { + constructor(private readonly bucket: s3.IBucket, { originAccessIdentity, ...props }: S3OriginProps) { super(bucket.bucketRegionalDomainName, props); + if (originAccessIdentity) { + this.originAccessIdentity = originAccessIdentity; + } } public bind(scope: cdk.Construct, options: cloudfront.OriginBindOptions): cloudfront.OriginBindConfig { diff --git a/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.expected.json b/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.expected.json new file mode 100644 index 0000000000000..2a41a79aae0ba --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.expected.json @@ -0,0 +1,58 @@ +{ + "Resources": { + "Bucket83908E77": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "OriginAccessIdentityDF1E3CAC": { + "Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", + "Properties": { + "CloudFrontOriginAccessIdentityConfig": { + "Comment": "Identity for bucket provided by test" + } + } + }, + "Distribution830FAC52": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "DefaultCacheBehavior": { + "ForwardedValues": { + "QueryString": false + }, + "TargetOriginId": "cloudfronts3originDistributionOrigin1741C4E95", + "ViewerProtocolPolicy": "allow-all" + }, + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Origins": [ + { + "DomainName": { + "Fn::GetAtt": [ + "Bucket83908E77", + "RegionalDomainName" + ] + }, + "Id": "cloudfronts3originDistributionOrigin1741C4E95", + "S3OriginConfig": { + "OriginAccessIdentity": { + "Fn::Join": [ + "", + [ + "origin-access-identity/cloudfront/", + { + "Ref": "OriginAccessIdentityDF1E3CAC" + } + ] + ] + } + } + } + ] + } + } + } + } +} diff --git a/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.ts b/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.ts new file mode 100644 index 0000000000000..1cf3c426b9839 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront-origins/test/integ.s3-origin-oai.ts @@ -0,0 +1,18 @@ +import * as cloudfront from '@aws-cdk/aws-cloudfront'; +import * as s3 from '@aws-cdk/aws-s3'; +import * as cdk from '@aws-cdk/core'; +import * as origins from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'cloudfront-s3-origin'); + +const bucket = new s3.Bucket(stack, 'Bucket'); +const originAccessIdentity = new cloudfront.OriginAccessIdentity(stack, 'OriginAccessIdentity', { + comment: 'Identity for bucket provided by test', +}); +new cloudfront.Distribution(stack, 'Distribution', { + defaultBehavior: { origin: new origins.S3Origin(bucket, { originAccessIdentity }) }, +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-cloudfront-origins/test/s3-origin.test.ts b/packages/@aws-cdk/aws-cloudfront-origins/test/s3-origin.test.ts index 1d99534652d23..77adf688c0f4b 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/test/s3-origin.test.ts +++ b/packages/@aws-cdk/aws-cloudfront-origins/test/s3-origin.test.ts @@ -30,7 +30,7 @@ describe('With bucket', () => { }); }); - test('can customize properties', () => { + test('can customize originPath property', () => { const bucket = new s3.Bucket(stack, 'Bucket'); const origin = new S3Origin(bucket, { originPath: '/assets' }); @@ -46,6 +46,23 @@ describe('With bucket', () => { }); }); + test('can customize OriginAccessIdentity property ', () => { + const bucket = new s3.Bucket(stack, 'Bucket'); + + const originAccessIdentity = new cloudfront.OriginAccessIdentity(stack, 'OriginAccessIdentity', { + comment: 'Identity for bucket provided by test', + }); + + const origin = new S3Origin(bucket, { originAccessIdentity }); + new cloudfront.Distribution(stack, 'Dist', { defaultBehavior: { origin } }); + + expect(stack).toHaveResourceLike('AWS::CloudFront::CloudFrontOriginAccessIdentity', { + CloudFrontOriginAccessIdentityConfig: { + Comment: 'Identity for bucket provided by test', + }, + }); + }); + test('creates an OriginAccessIdentity and grants read permissions on the bucket', () => { const bucket = new s3.Bucket(stack, 'Bucket');