Skip to content

Commit

Permalink
feat(cloudfront): complete viewerCertificate support (aws#4579)
Browse files Browse the repository at this point in the history
* feat(cloudfront): complete viewerCertificate support

* chore: tslint errors

* feat(certificatemanager): add getCertificateRegion method

* chore: more tslint

* chore(acm): export utils

* chore(acm): add fromCertificateArn test

* feat(cloudfront): throw cert not in us-east-1

* chore: remove eroneous import

* chore: more tslint fixes

* chore: fix integ test arn

* chore: more integ test arn

* chore: fix cert region

* chore: refactor static X -> fromX

* chore: refactor arrow into classic functions

* chore: refactor fromCertificate apis

* chore: viewer certificate docs

* chore: fix README link
  • Loading branch information
nmussy authored and mergify[bot] committed Oct 23, 2019
1 parent 3202720 commit 80b4ac9
Show file tree
Hide file tree
Showing 12 changed files with 674 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-certificatemanager/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './certificate';
export * from './dns-validated-certificate';
export * from './util';

// AWS::CertificateManager CloudFormation Resources:
export * from './certificatemanager.generated';
33 changes: 33 additions & 0 deletions packages/@aws-cdk/aws-certificatemanager/lib/util.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Arn, Stack, Token } from '@aws-cdk/core';
import { ICertificate } from './certificate';
import { DnsValidatedCertificate } from './dns-validated-certificate';
import publicSuffixes = require('./public-suffixes');

/**
Expand All @@ -16,3 +19,33 @@ export function apexDomain(domainName: string): string {
}
return accumulated.reverse().join('.');
}

export function isDnsValidatedCertificate(cert: ICertificate): cert is DnsValidatedCertificate {
return cert.hasOwnProperty('domainName');
}

export function getCertificateRegion(cert: ICertificate): string | undefined {
const { certificateArn, stack } = cert;

if (isDnsValidatedCertificate(cert)) {
const requestResource = cert.node.findChild('CertificateRequestorResource').node.defaultChild;

// @ts-ignore
const { _cfnProperties: properties } = requestResource;
const { Region: region } = properties;

if (region && !Token.isUnresolved(region)) {
return region;
}
}

{
const { region } = Arn.parse(certificateArn);

if (region && !Token.isUnresolved(region)) {
return region;
}
}

return Stack.of(stack).region;
}
111 changes: 102 additions & 9 deletions packages/@aws-cdk/aws-certificatemanager/test/test.util.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,108 @@
import { PublicHostedZone } from '@aws-cdk/aws-route53';
import { App, Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { apexDomain } from '../lib/util';
import { Certificate, DnsValidatedCertificate } from '../lib';
import { apexDomain, getCertificateRegion, isDnsValidatedCertificate } from '../lib/util';

export = {
'apex domain returns right domain'(test: Test) {
test.equals('domain.com', apexDomain('domain.com'));
test.equals('domain.com', apexDomain('test.domain.com'));
test.done();
'apex domain': {
'returns right domain'(test: Test) {
test.equals('domain.com', apexDomain('domain.com'));
test.equals('domain.com', apexDomain('test.domain.com'));
test.done();
},

'understands eTLDs'(test: Test) {
test.equals('domain.co.uk', apexDomain('test.domain.co.uk'));
test.done();
},
},
'isDnsValidatedCertificate': {
'new DnsValidatedCertificate is a DnsValidatedCertificate'(test: Test) {
const stack = new Stack();

const hostedZone = new PublicHostedZone(stack, 'ExampleDotCom', {
zoneName: 'example.com'
});
const cert = new DnsValidatedCertificate(stack, 'Certificate', {
domainName: 'test.example.com',
hostedZone
});

test.ok(isDnsValidatedCertificate(cert));
test.done();
},
'new Certificate is not a DnsValidatedCertificate'(test: Test) {
const stack = new Stack();

const cert = new Certificate(stack, 'Certificate', {
domainName: 'test.example.com'
});

test.ok(!isDnsValidatedCertificate(cert));
test.done();
},
'fromCertificateArn is not a DnsValidatedCertificate'(test: Test) {
const stack = new Stack();

const cert = Certificate.fromCertificateArn(stack, 'Certificate', 'cert-arn');

test.ok(!isDnsValidatedCertificate(cert));
test.done();
},
},
'getCertificateRegion': {
'from stack'(test: Test) {
// GIVEN
const app = new App();
const stack = new Stack(app, 'RegionStack', {env: {region: 'eu-west-1'}});

'apex domain understands eTLDs'(test: Test) {
test.equals('domain.co.uk', apexDomain('test.domain.co.uk'));
test.done();
}
const certificate = new Certificate(stack, 'TestCertificate', {
domainName: 'www.example.com',
});

test.equals(getCertificateRegion(certificate), 'eu-west-1');
test.done();
},
'from DnsValidatedCertificate region'(test: Test) {
// GIVEN
const app = new App();
const stack = new Stack(app, 'RegionStack', {env: {region: 'eu-west-1'}});
const hostedZone = new PublicHostedZone(stack, 'ExampleDotCom', {
zoneName: 'example.com'
});

const certificate = new DnsValidatedCertificate(stack, 'TestCertificate', {
domainName: 'www.example.com',
hostedZone,
region: 'eu-west-3'
});

test.equals(getCertificateRegion(certificate), 'eu-west-3');
test.done();
},
'fromCertificateArn'(test: Test) {
// GIVEN
const app = new App();
const stack = new Stack(app, 'RegionStack', {env: {region: 'eu-west-1'}});

const certificate = Certificate.fromCertificateArn(
stack, 'TestCertificate', 'arn:aws:acm:us-east-2:1111111:certificate/11-3336f1-44483d-adc7-9cd375c5169d'
);

test.equals(getCertificateRegion(certificate), 'us-east-2');
test.done();
},
'region agnostic stack'(test: Test) {
// GIVEN
const stack = new Stack();

const certificate = new Certificate(stack, 'TestCertificate', {
domainName: 'www.example.com',
});

test.equals(getCertificateRegion(certificate), '${Token[AWS::Region.4]}');
test.done();
},
},
};
38 changes: 37 additions & 1 deletion packages/@aws-cdk/aws-cloudfront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Example usage:

```ts
const sourceBucket = new Bucket(this, 'Bucket');

const distribution = new CloudFrontWebDistribution(this, 'MyDistribution', {
originConfigs: [
{
Expand All @@ -33,3 +33,39 @@ const distribution = new CloudFrontWebDistribution(this, 'MyDistribution', {
]
});
```

### Viewer certificate

By default, CloudFront Web Distributions will answer HTTPS requests with CloudFront's default certificate, only containing the distribution `domainName` (e.g. d111111abcdef8.cloudfront.net).
You can customize the viewer certificate property to provide a custom certificate and/or list of domain name aliases to fit your needs.

See [Using Alternate Domain Names and HTTPS](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-alternate-domain-names.html) in the CloudFront User Guide.

#### Default certificate

You can customize the default certificate aliases. This is intended to be used in combination with CNAME records in your DNS zone.

Example:

[create a distrubution with an default certificiate example](test/example.default-cert-alias.lit.ts)

#### ACM certificate

You can change the default certificate by one stored Amazon Certificate Manager, or ACM.
Those certificate can either be generated by AWS, or purchased by another CA imported into ACM.

For more information, see [the aws-certificatemanager module documentation](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-certificatemanager-readme.html) or [Importing Certificates into AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/import-certificate.html) in the AWS Certificate Manager User Guide.

Example:

[create a distrubution with an acm certificate example](test/example.acm-cert-alias.lit.ts)

#### IAM certificate

You can also import a certificate into the IAM certificate store.

See [Importing an SSL/TLS Certificate](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-procedures.html#cnames-and-https-uploading-certificates) in the CloudFront User Guide.

Example:

[create a distrubution with an iam certificate example](test/example.iam-cert-alias.lit.ts)
Loading

0 comments on commit 80b4ac9

Please sign in to comment.