From a09afc4a50b4ae659338b1670dc62f2f52ee83fc Mon Sep 17 00:00:00 2001 From: ZeldoKavira Date: Tue, 2 Oct 2018 03:01:05 -0700 Subject: [PATCH] fix(aws-cloudfront): properly support loggingConfig (#809) feat(aws-s3): Add support for domainName on BucketRef instead of just Bucket LoggingConfiguration now requires bucket instead of it being optional. There is no point to including a LoggingConfiguration without a bucket (no-breaking). Fixes #721 --- .../aws-cloudfront/lib/web_distribution.ts | 34 ++++- ...eg.cloudfront-bucket-logging.expected.json | 141 ++++++++++++++++++ .../test/integ.cloudfront-bucket-logging.ts | 53 +++++++ packages/@aws-cdk/aws-s3/lib/bucket.ts | 18 +++ .../integ.bucket.domain-name.expected.json | 24 +++ .../aws-s3/test/integ.bucket.domain-name.ts | 22 +++ 6 files changed, 285 insertions(+), 7 deletions(-) create mode 100644 packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.expected.json create mode 100644 packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.ts create mode 100644 packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.expected.json create mode 100644 packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts diff --git a/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts b/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts index 18db785426713..e2dd5bd70eaf2 100644 --- a/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts +++ b/packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts @@ -101,17 +101,28 @@ export enum SecurityPolicyProtocol { } /** - * CloudFront supports logging of incoming requests and can log details to a given S3 Bucket. - * - * If you wish to configure logging you can configure details about it. - * - * @default bucket: if you do not pass a bucket for logging - we'll create one - * @default includeCookies: false by default - * @default prefix: no prefix is set by default. + * Logging configuration for incoming requests */ export interface LoggingConfiguration { + /** + * Bucket to log requests to + * + * @default A logging bucket is automatically created + */ readonly bucket?: s3.BucketRef, + + /** + * Whether to include the cookies in the logs + * + * @default false + */ readonly includeCookies?: boolean, + + /** + * Where in the bucket to store logs + * + * @default No prefix + */ readonly prefix?: string } @@ -622,6 +633,15 @@ export class CloudFrontWebDistribution extends cdk.Construct { }; } + if (props.loggingConfig) { + this.loggingBucket = props.loggingConfig.bucket || new s3.Bucket(this, `LoggingBucket`); + distributionConfig.logging = { + bucket: this.loggingBucket.domainName, + includeCookies: props.loggingConfig.includeCookies || false, + prefix: props.loggingConfig.prefix + }; + } + const distribution = new cloudformation.DistributionResource(this, 'CFDistribution', {distributionConfig}); this.domainName = distribution.distributionDomainName; diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.expected.json b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.expected.json new file mode 100644 index 0000000000000..286eaf976517e --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.expected.json @@ -0,0 +1,141 @@ +{ + "Resources": { + "Bucket83908E77": { + "Type": "AWS::S3::Bucket" + }, + "AnAmazingWebsiteProbablyCFDistribution47E3983B": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "CacheBehaviors": [], + "DefaultCacheBehavior": { + "AllowedMethods": [ + "GET", + "HEAD" + ], + "CachedMethods": [ + "GET", + "HEAD" + ], + "ForwardedValues": { + "Cookies": { + "Forward": "none" + }, + "QueryString": false + }, + "TargetOriginId": "origin1", + "ViewerProtocolPolicy": "redirect-to-https" + }, + "DefaultRootObject": "index.html", + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Logging": { + "Bucket": { + "Fn::GetAtt": [ + "Bucket83908E77", + "DomainName" + ] + }, + "IncludeCookies": true, + "Prefix": "test-prefix" + }, + "Origins": [ + { + "CustomOriginConfig": { + "HTTPPort": 80, + "HTTPSPort": 443, + "OriginKeepaliveTimeout": 5, + "OriginProtocolPolicy": "https-only", + "OriginReadTimeout": 30, + "OriginSSLProtocols": [ + "TLSv1.2" + ] + }, + "DomainName": "brelandm.a2z.com", + "Id": "origin1", + "OriginCustomHeaders": [ + { + "HeaderName": "X-Custom-Header", + "HeaderValue": "somevalue" + } + ] + } + ], + "PriceClass": "PriceClass_100", + "ViewerCertificate": { + "CloudFrontDefaultCertificate": true + } + } + } + }, + "AnAmazingWebsiteProbably2LoggingBucket222F7CE9": { + "Type": "AWS::S3::Bucket" + }, + "AnAmazingWebsiteProbably2CFDistribution7C1CCD12": { + "Type": "AWS::CloudFront::Distribution", + "Properties": { + "DistributionConfig": { + "CacheBehaviors": [], + "DefaultCacheBehavior": { + "AllowedMethods": [ + "GET", + "HEAD" + ], + "CachedMethods": [ + "GET", + "HEAD" + ], + "ForwardedValues": { + "Cookies": { + "Forward": "none" + }, + "QueryString": false + }, + "TargetOriginId": "origin1", + "ViewerProtocolPolicy": "redirect-to-https" + }, + "DefaultRootObject": "index.html", + "Enabled": true, + "HttpVersion": "http2", + "IPV6Enabled": true, + "Logging": { + "Bucket": { + "Fn::GetAtt": [ + "AnAmazingWebsiteProbably2LoggingBucket222F7CE9", + "DomainName" + ] + }, + "IncludeCookies": false + }, + "Origins": [ + { + "CustomOriginConfig": { + "HTTPPort": 80, + "HTTPSPort": 443, + "OriginKeepaliveTimeout": 5, + "OriginProtocolPolicy": "https-only", + "OriginReadTimeout": 30, + "OriginSSLProtocols": [ + "TLSv1.2" + ] + }, + "DomainName": "brelandm.a2z.com", + "Id": "origin1", + "OriginCustomHeaders": [ + { + "HeaderName": "X-Custom-Header", + "HeaderValue": "somevalue" + } + ] + } + ], + "PriceClass": "PriceClass_100", + "ViewerCertificate": { + "CloudFrontDefaultCertificate": true + } + } + } + } + } +} diff --git a/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.ts b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.ts new file mode 100644 index 0000000000000..5c58c1e00a869 --- /dev/null +++ b/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-bucket-logging.ts @@ -0,0 +1,53 @@ +import s3 = require('@aws-cdk/aws-s3'); +import cdk = require('@aws-cdk/cdk'); +import cloudfront = require('../lib'); + +const app = new cdk.App(process.argv); + +const stack = new cdk.Stack(app, 'aws-cdk-cloudfront-custom'); + +const loggingBucket = new s3.Bucket(stack, 'Bucket'); + +new cloudfront.CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably', { + originConfigs: [ + { + originHeaders: { + "X-Custom-Header": "somevalue", + }, + customOriginSource: { + domainName: "brelandm.a2z.com", + }, + behaviors: [ + { + isDefaultBehavior: true, + } + ] + } + ], + loggingConfig: { + bucket: loggingBucket, + includeCookies: true, + prefix: 'test-prefix' + } +}); + +new cloudfront.CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably2', { + originConfigs: [ + { + originHeaders: { + "X-Custom-Header": "somevalue", + }, + customOriginSource: { + domainName: "brelandm.a2z.com", + }, + behaviors: [ + { + isDefaultBehavior: true, + } + ] + } + ], + loggingConfig: {} +}); + +process.stdout.write(app.run()); diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 1a55df6afd323..d3291312c3f29 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -30,6 +30,13 @@ export interface BucketRefProps { * policy, won't work. */ bucketName?: string; + + /** + * The domain name of the bucket. + * + * @default Inferred from bucket name + */ + bucketDomainName?: string; } /** @@ -72,6 +79,11 @@ export abstract class BucketRef extends cdk.Construct { */ public abstract readonly bucketName: string; + /** + * The domain of the bucket. + */ + public abstract readonly domainName: string; + /** * Optional KMS encryption key associated with this bucket. */ @@ -701,6 +713,7 @@ export interface NotificationKeyFilter { class ImportedBucketRef extends BucketRef { public readonly bucketArn: string; public readonly bucketName: string; + public readonly domainName: string; public readonly encryptionKey?: kms.EncryptionKey; protected policy?: BucketPolicy; @@ -716,7 +729,12 @@ class ImportedBucketRef extends BucketRef { this.bucketArn = parseBucketArn(props); this.bucketName = bucketName; + this.domainName = props.bucketDomainName || this.generateDomainName(); this.autoCreatePolicy = false; this.policy = undefined; } + + private generateDomainName() { + return `${this.bucketName}.s3.amazonaws.com`; + } } diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.expected.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.expected.json new file mode 100644 index 0000000000000..01c6536296847 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.expected.json @@ -0,0 +1,24 @@ +{ + "Resources": { + "MyBucketF68F3FF0": { + "Type": "AWS::S3::Bucket" + } + }, + "Outputs": { + "RealBucketDomain": { + "Value": { + "Fn::GetAtt":["MyBucketF68F3FF0","DomainName"] + }, + "Export": { + "Name": "aws-cdk-s3-urls:RealBucketDomain" + } + }, + "ImportedBucketDomain": { + "Value": "my-bucket-test.s3.amazonaws.com", + "Export": { + "Name": "aws-cdk-s3-urls:ImportedBucketDomain" + } + } + } +} + diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts new file mode 100644 index 0000000000000..469c22b27b4be --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts @@ -0,0 +1,22 @@ +import cdk = require('@aws-cdk/cdk'); +import s3 = require('../lib'); + +class TestStack extends cdk.Stack { + constructor(parent: cdk.App, id: string) { + super(parent, id); + + /// !show + const bucket = new s3.Bucket(this, 'MyBucket'); + const bucket2 = s3.Bucket.import(this, "MyBucket2", { + bucketArn: "arn:aws:s3:::my-bucket-test" + }); + + new cdk.Output(this, 'RealBucketDomain', { value: bucket.domainName }); + new cdk.Output(this, 'ImportedBucketDomain', { value: bucket2.domainName }); + /// !hide + } +} + +const app = new cdk.App(process.argv); +new TestStack(app, 'aws-cdk-s3-urls'); +process.stdout.write(app.run());