Skip to content

Commit

Permalink
feat(aws-cloudfront): Support Security Policy
Browse files Browse the repository at this point in the history
Adds support for changing the default Security Policy (minimumProtocolVersion) with logic to ensure the proper one is being set for your SSLMethod. Fixes aws#795
  • Loading branch information
Blake Price committed Sep 28, 2018
1 parent c23230e commit a02555a
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
38 changes: 38 additions & 0 deletions packages/@aws-cdk/aws-cloudfront/lib/web_distribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface AliasConfiguration {
readonly names: string[],
readonly acmCertRef: string,
readonly sslMethod?: SSLMethod,
readonly securityPolicy?: SecurityPolicyProtocol
}

/**
Expand All @@ -64,6 +65,18 @@ export enum SSLMethod {
VIP = "vip"
}

/**
* The minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections.
* CloudFront serves your objects only to browsers or devices that support at least the SSL version that you specify.
*/
export enum SecurityPolicyProtocol {
SSLv3 = "SSLv3",
TLSv1 = "TLSv1",
TLSv1_2016 = "TLSv1_2016",
TLSv1_1_2016 = "TLSv1.1_2016",
TLSv1_2_2018 = "TLSv1.2_2018"
}

/**
* CloudFront supports logging of incoming requests and can log details to a given S3 Bucket.
*
Expand Down Expand Up @@ -453,6 +466,17 @@ export class CloudFrontWebDistribution extends cdk.Construct {
ALL: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"],
};

/**
* Maps for which SecurityPolicyProtocol are available to which SSLMethods
*/
private readonly VALID_SSL_PROTOCOLS: { [key: string]: string[] } = {
"sni-only": [
SecurityPolicyProtocol.TLSv1, SecurityPolicyProtocol.TLSv1_1_2016,
SecurityPolicyProtocol.TLSv1_2016, SecurityPolicyProtocol.TLSv1_2_2018
],
"vip": [SecurityPolicyProtocol.SSLv3, SecurityPolicyProtocol.TLSv1],
};

constructor(parent: cdk.Construct, name: string, props: CloudFrontWebDistributionProps) {
super(parent, name);

Expand Down Expand Up @@ -554,7 +578,21 @@ export class CloudFrontWebDistribution extends cdk.Construct {
distributionConfig.viewerCertificate = {
acmCertificateArn: props.aliasConfiguration.acmCertRef,
sslSupportMethod: props.aliasConfiguration.sslMethod || SSLMethod.SNI,
minimumProtocolVersion: props.aliasConfiguration.securityPolicy
};

if (distributionConfig.viewerCertificate.minimumProtocolVersion !== undefined) {
const validProtocols = this.VALID_SSL_PROTOCOLS[distributionConfig.viewerCertificate.sslSupportMethod!.toString()];

if (validProtocols === undefined) {
throw new Error(`Invalid sslMethod. ${distributionConfig.viewerCertificate.sslSupportMethod!.toString()} is not fully implemented yet.`);
}

if (validProtocols.indexOf(distributionConfig.viewerCertificate.minimumProtocolVersion.toString()) === -1) {
// tslint:disable-next-line:max-line-length
throw new Error(`${distributionConfig.viewerCertificate.minimumProtocolVersion} is not compabtible with sslMethod ${distributionConfig.viewerCertificate.sslSupportMethod}.\n\tValid Protocols are: ${validProtocols.join(", ")}`);
}
}
} else {
distributionConfig.viewerCertificate = {
cloudFrontDefaultCertificate: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"Resources": {
"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,
"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": {
"AcmCertificateArn": "testACM",
"MinimumProtocolVersion": "TLSv1",
"SslSupportMethod": "sni-only"
},
"Aliases": [
"test.test.com"
]
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

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');

new cloudfront.CloudFrontWebDistribution(stack, 'AnAmazingWebsiteProbably', {
originConfigs: [
{
originHeaders: {
"X-Custom-Header": "somevalue",
},
customOriginSource: {
domainName: "brelandm.a2z.com",
},
behaviors: [
{
isDefaultBehavior: true,
}
]
}
],
aliasConfiguration: {
acmCertRef: 'testACM',
names: ['test.test.com'],
sslMethod: cloudfront.SSLMethod.SNI,
securityPolicy: cloudfront.SecurityPolicyProtocol.TLSv1
}
});

process.stdout.write(app.run());

0 comments on commit a02555a

Please sign in to comment.