Skip to content

Commit c5a9679

Browse files
authored
fix(aws-cloudfront): Add sslSupportMethod (#19737)
- Modified to allow selection of sslSupportMethod closes #19476 ---- ### All Submissions: * [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/master/INTEGRATION_TESTS.md)? * [ ] Did you use `cdk-integ` to deploy the infrastructure and generate the snapshot (i.e. `cdk-integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent ccfbcf6 commit c5a9679

File tree

3 files changed

+160
-4
lines changed

3 files changed

+160
-4
lines changed

packages/@aws-cdk/aws-cloudfront/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ new cloudfront.Distribution(this, 'myDist', {
121121
defaultBehavior: { origin: new origins.S3Origin(myBucket) },
122122
domainNames: ['www.example.com'],
123123
minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2016,
124+
sslSupportMethod: cloudfront.SSLMethod.SNI,
124125
});
125126
```
126127

packages/@aws-cdk/aws-cloudfront/lib/distribution.ts

+24-3
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,25 @@ export interface DistributionProps {
220220
* @default - SecurityPolicyProtocol.TLS_V1_2_2021 if the '@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021' feature flag is set; otherwise, SecurityPolicyProtocol.TLS_V1_2_2019.
221221
*/
222222
readonly minimumProtocolVersion?: SecurityPolicyProtocol;
223+
224+
/**
225+
* The SSL method CloudFront will use for your distribution.
226+
*
227+
* Server Name Indication (SNI) - is an extension to the TLS computer networking protocol by which a client indicates
228+
* which hostname it is attempting to connect to at the start of the handshaking process. This allows a server to present
229+
* multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites
230+
* (or any other service over TLS) to be served by the same IP address without requiring all those sites to use the same certificate.
231+
*
232+
* CloudFront can use SNI to host multiple distributions on the same IP - which a large majority of clients will support.
233+
*
234+
* If your clients cannot support SNI however - CloudFront can use dedicated IPs for your distribution - but there is a prorated monthly charge for
235+
* using this feature. By default, we use SNI - but you can optionally enable dedicated IPs (VIP).
236+
*
237+
* See the CloudFront SSL for more details about pricing : https://aws.amazon.com/cloudfront/custom-ssl-domains/
238+
*
239+
* @default SSLMethod.SNI
240+
*/
241+
readonly sslSupportMethod?: SSLMethod;
223242
}
224243

225244
/**
@@ -304,7 +323,8 @@ export class Distribution extends Resource implements IDistribution {
304323
logging: this.renderLogging(props),
305324
priceClass: props.priceClass ?? undefined,
306325
restrictions: this.renderRestrictions(props.geoRestriction),
307-
viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate, props.minimumProtocolVersion) : undefined,
326+
viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate,
327+
props.minimumProtocolVersion, props.sslSupportMethod) : undefined,
308328
webAclId: props.webAclId,
309329
},
310330
});
@@ -450,16 +470,17 @@ export class Distribution extends Resource implements IDistribution {
450470
}
451471

452472
private renderViewerCertificate(certificate: acm.ICertificate,
453-
minimumProtocolVersionProp?: SecurityPolicyProtocol): CfnDistribution.ViewerCertificateProperty {
473+
minimumProtocolVersionProp?: SecurityPolicyProtocol, sslSupportMethodProp?: SSLMethod): CfnDistribution.ViewerCertificateProperty {
454474

455475
const defaultVersion = FeatureFlags.of(this).isEnabled(CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021)
456476
? SecurityPolicyProtocol.TLS_V1_2_2021 : SecurityPolicyProtocol.TLS_V1_2_2019;
457477
const minimumProtocolVersion = minimumProtocolVersionProp ?? defaultVersion;
478+
const sslSupportMethod = sslSupportMethodProp ?? SSLMethod.SNI;
458479

459480
return {
460481
acmCertificateArn: certificate.certificateArn,
461-
sslSupportMethod: SSLMethod.SNI,
462482
minimumProtocolVersion: minimumProtocolVersion,
483+
sslSupportMethod: sslSupportMethod,
463484
};
464485
}
465486
}

packages/@aws-cdk/aws-cloudfront/test/distribution.test.ts

+135-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
LambdaEdgeEventType,
1818
PriceClass,
1919
SecurityPolicyProtocol,
20+
SSLMethod,
2021
} from '../lib';
2122
import { defaultOrigin, defaultOriginGroup } from './test-origin';
2223

@@ -56,7 +57,139 @@ test('minimal example renders correctly', () => {
5657
});
5758
});
5859

59-
test('exhaustive example of props renders correctly', () => {
60+
test('exhaustive example of props renders correctly and SSL method sni-only', () => {
61+
const origin = defaultOrigin();
62+
const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
63+
64+
new Distribution(stack, 'MyDist', {
65+
defaultBehavior: { origin },
66+
certificate,
67+
comment: 'a test',
68+
defaultRootObject: 'index.html',
69+
domainNames: ['example.com'],
70+
enabled: false,
71+
enableIpv6: false,
72+
enableLogging: true,
73+
geoRestriction: GeoRestriction.denylist('US', 'GB'),
74+
httpVersion: HttpVersion.HTTP1_1,
75+
logFilePrefix: 'logs/',
76+
logIncludesCookies: true,
77+
sslSupportMethod: SSLMethod.SNI,
78+
minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2019,
79+
priceClass: PriceClass.PRICE_CLASS_100,
80+
webAclId: '473e64fd-f30b-4765-81a0-62ad96dd167a',
81+
});
82+
83+
Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', {
84+
DistributionConfig: {
85+
Aliases: ['example.com'],
86+
DefaultCacheBehavior: {
87+
CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6',
88+
Compress: true,
89+
TargetOriginId: 'StackMyDistOrigin1D6D5E535',
90+
ViewerProtocolPolicy: 'allow-all',
91+
},
92+
Comment: 'a test',
93+
DefaultRootObject: 'index.html',
94+
Enabled: false,
95+
HttpVersion: 'http1.1',
96+
IPV6Enabled: false,
97+
Logging: {
98+
Bucket: { 'Fn::GetAtt': ['MyDistLoggingBucket9B8976BC', 'RegionalDomainName'] },
99+
IncludeCookies: true,
100+
Prefix: 'logs/',
101+
},
102+
Origins: [{
103+
DomainName: 'www.example.com',
104+
Id: 'StackMyDistOrigin1D6D5E535',
105+
CustomOriginConfig: {
106+
OriginProtocolPolicy: 'https-only',
107+
},
108+
}],
109+
PriceClass: 'PriceClass_100',
110+
Restrictions: {
111+
GeoRestriction: {
112+
Locations: ['US', 'GB'],
113+
RestrictionType: 'blacklist',
114+
},
115+
},
116+
ViewerCertificate: {
117+
AcmCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012',
118+
SslSupportMethod: 'sni-only',
119+
MinimumProtocolVersion: 'TLSv1.2_2019',
120+
},
121+
WebACLId: '473e64fd-f30b-4765-81a0-62ad96dd167a',
122+
},
123+
});
124+
});
125+
126+
test('exhaustive example of props renders correctly and SSL method vip', () => {
127+
const origin = defaultOrigin();
128+
const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
129+
130+
new Distribution(stack, 'MyDist', {
131+
defaultBehavior: { origin },
132+
certificate,
133+
comment: 'a test',
134+
defaultRootObject: 'index.html',
135+
domainNames: ['example.com'],
136+
enabled: false,
137+
enableIpv6: false,
138+
enableLogging: true,
139+
geoRestriction: GeoRestriction.denylist('US', 'GB'),
140+
httpVersion: HttpVersion.HTTP1_1,
141+
logFilePrefix: 'logs/',
142+
logIncludesCookies: true,
143+
sslSupportMethod: SSLMethod.VIP,
144+
minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2019,
145+
priceClass: PriceClass.PRICE_CLASS_100,
146+
webAclId: '473e64fd-f30b-4765-81a0-62ad96dd167a',
147+
});
148+
149+
Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::Distribution', {
150+
DistributionConfig: {
151+
Aliases: ['example.com'],
152+
DefaultCacheBehavior: {
153+
CachePolicyId: '658327ea-f89d-4fab-a63d-7e88639e58f6',
154+
Compress: true,
155+
TargetOriginId: 'StackMyDistOrigin1D6D5E535',
156+
ViewerProtocolPolicy: 'allow-all',
157+
},
158+
Comment: 'a test',
159+
DefaultRootObject: 'index.html',
160+
Enabled: false,
161+
HttpVersion: 'http1.1',
162+
IPV6Enabled: false,
163+
Logging: {
164+
Bucket: { 'Fn::GetAtt': ['MyDistLoggingBucket9B8976BC', 'RegionalDomainName'] },
165+
IncludeCookies: true,
166+
Prefix: 'logs/',
167+
},
168+
Origins: [{
169+
DomainName: 'www.example.com',
170+
Id: 'StackMyDistOrigin1D6D5E535',
171+
CustomOriginConfig: {
172+
OriginProtocolPolicy: 'https-only',
173+
},
174+
}],
175+
PriceClass: 'PriceClass_100',
176+
Restrictions: {
177+
GeoRestriction: {
178+
Locations: ['US', 'GB'],
179+
RestrictionType: 'blacklist',
180+
},
181+
},
182+
ViewerCertificate: {
183+
AcmCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012',
184+
SslSupportMethod: 'vip',
185+
MinimumProtocolVersion: 'TLSv1.2_2019',
186+
},
187+
WebACLId: '473e64fd-f30b-4765-81a0-62ad96dd167a',
188+
},
189+
});
190+
});
191+
192+
test('exhaustive example of props renders correctly and SSL method default', () => {
60193
const origin = defaultOrigin();
61194
const certificate = acm.Certificate.fromCertificateArn(stack, 'Cert', 'arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012');
62195

@@ -404,6 +537,7 @@ describe('certificates', () => {
404537
new Distribution(stack, 'Dist', {
405538
defaultBehavior: { origin: defaultOrigin() },
406539
domainNames: ['www.example.com'],
540+
sslSupportMethod: SSLMethod.SNI,
407541
minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2016,
408542
certificate: certificate,
409543
});

0 commit comments

Comments
 (0)