Skip to content

Commit 64bfbf9

Browse files
authored
feat(certificatemanager): deprecate DnsValidatedCertificate (#21982)
Now that the official CloudFormation resource `AWS::CertificateManager::Certificate` (CDK's `Certificate` construct) supports DNS validation we do not want to recommend using the `DnsValidatedCertificate` construct. The `DnsValidatedCertificate` construct uses CloudFormation custom resources to perform the certificate creation and this creates a lot of maintenance burden on our team (see the list of linked issues). Currently the primary use case for using `DnsValidatedCertificate` over `Certificate` is for cross region use cases. For this use case I have updated the README to have our suggested solution. The example in the README is tested in this [integration test](https://github.com/aws/aws-cdk/blob/main/packages/@aws-cdk/aws-cloudfront/test/integ.cloudfront-cross-region-cert.ts) fixes #8934, #2914, #20698, #17349, #15217, #14519 ---- ### All Submissions: * [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/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/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn 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 ba14612 commit 64bfbf9

File tree

8 files changed

+63
-31
lines changed

8 files changed

+63
-31
lines changed

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

+32-7
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,40 @@ new acm.Certificate(this, 'Certificate', {
100100
## Cross-region Certificates
101101

102102
ACM certificates that are used with CloudFront -- or higher-level constructs which rely on CloudFront -- must be in the `us-east-1` region.
103-
The `DnsValidatedCertificate` construct exists to facilitate creating these certificates cross-region. This resource can only be used with
104-
Route53-based DNS validation.
103+
CloudFormation allows you to create a Stack with a CloudFront distribution in any region. In order
104+
to create an ACM certificate in us-east-1 and reference it in a CloudFront distribution is a
105+
different region, it is recommended to perform a multi stack deployment.
106+
107+
Enable the Stack property `crossRegionReferences`
108+
in order to access the cross stack/region certificate.
109+
110+
> **This feature is currently experimental**
105111
106112
```ts
107-
declare const myHostedZone: route53.HostedZone;
108-
new acm.DnsValidatedCertificate(this, 'CrossRegionCertificate', {
109-
domainName: 'hello.example.com',
110-
hostedZone: myHostedZone,
111-
region: 'us-east-1',
113+
const stack1 = new Stack(app, 'Stack1', {
114+
env: {
115+
region: 'us-east-1',
116+
},
117+
crossRegionReferences: true,
118+
});
119+
const cert = new acm.Certificate(stack1, 'Cert', {
120+
domainName: '*.example.com',
121+
validation: acm.CertificateValidation.fromDns(PublicHostedZone.fromHostedZoneId(stack1, 'Zone', 'ZONE_ID')),
122+
});
123+
124+
const stack2 = new Stack(app, 'Stack2', {
125+
env: {
126+
region: 'us-east-2',
127+
},
128+
crossRegionReferences: true,
129+
});
130+
131+
new cloudfront.Distribution(stack2, 'Distribution', {
132+
defaultBehavior: {
133+
origin: new origins.HttpOrigin('example.com'),
134+
},
135+
domainNames: ['dev.example.com'],
136+
certificate: cert,
112137
});
113138
```
114139

packages/@aws-cdk/aws-certificatemanager/lib/dns-validated-certificate.ts

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export interface DnsValidatedCertificateProps extends CertificateProps {
6666
* validated using DNS validation against the specified Route 53 hosted zone.
6767
*
6868
* @resource AWS::CertificateManager::Certificate
69+
* @deprecated use {@link Certificate} instead
6970
*/
7071
export class DnsValidatedCertificate extends CertificateBase implements ICertificate, cdk.ITaggable {
7172
public readonly certificateArn: string;
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
// Fixture with packages imported, but nothing else
2-
import { Stack } from '@aws-cdk/core';
32
import { Construct } from 'constructs';
43
import * as acm from '@aws-cdk/aws-certificatemanager';
54
import * as route53 from '@aws-cdk/aws-route53';
5+
import { PublicHostedZone } from '@aws-cdk/aws-route53';
6+
import { StringParameter } from '@aws-cdk/aws-ssm';
7+
import { Stack, Names } from '@aws-cdk/core';
8+
import { AwsCustomResource, PhysicalResourceId, AwsCustomResourcePolicy } from '@aws-cdk/custom-resources';
69

710
class Fixture extends Stack {
811
constructor(scope: Construct, id: string) {
912
super(scope, id);
1013
/// here
1114
}
12-
}
15+
}

packages/@aws-cdk/aws-certificatemanager/test/dns-validated-certificate.test.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { Template } from '@aws-cdk/assertions';
22
import * as iam from '@aws-cdk/aws-iam';
33
import { HostedZone, PublicHostedZone } from '@aws-cdk/aws-route53';
4+
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
45
import { App, Stack, Token, Tags, RemovalPolicy, Aws } from '@aws-cdk/core';
56
import { DnsValidatedCertificate } from '../lib/dns-validated-certificate';
67

7-
test('creates CloudFormation Custom Resource', () => {
8+
testDeprecated('creates CloudFormation Custom Resource', () => {
89
const stack = new Stack();
910

1011
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -94,7 +95,7 @@ test('creates CloudFormation Custom Resource', () => {
9495
});
9596
});
9697

97-
test('adds validation error on domain mismatch', () => {
98+
testDeprecated('adds validation error on domain mismatch', () => {
9899
const stack = new Stack();
99100

100101
const helloDotComZone = new PublicHostedZone(stack, 'HelloDotCom', {
@@ -111,7 +112,7 @@ test('adds validation error on domain mismatch', () => {
111112
}).toThrow(/DNS zone hello.com is not authoritative for certificate domain name example.com/);
112113
});
113114

114-
test('does not try to validate unresolved tokens', () => {
115+
testDeprecated('does not try to validate unresolved tokens', () => {
115116
const stack = new Stack();
116117

117118
const helloDotComZone = new PublicHostedZone(stack, 'HelloDotCom', {
@@ -126,7 +127,7 @@ test('does not try to validate unresolved tokens', () => {
126127
Template.fromStack(stack); // does not throw
127128
});
128129

129-
test('test root certificate', () => {
130+
testDeprecated('test root certificate', () => {
130131
const stack = new Stack();
131132

132133
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -152,7 +153,7 @@ test('test root certificate', () => {
152153
});
153154
});
154155

155-
test('test tags are passed to customresource', () => {
156+
testDeprecated('test tags are passed to customresource', () => {
156157
const stack = new Stack();
157158
Tags.of(stack).add('Key1', 'Value1');
158159

@@ -182,7 +183,7 @@ test('test tags are passed to customresource', () => {
182183
});
183184
});
184185

185-
test('works with imported zone', () => {
186+
testDeprecated('works with imported zone', () => {
186187
// GIVEN
187188
const app = new App();
188189
const stack = new Stack(app, 'Stack', {
@@ -213,7 +214,7 @@ test('works with imported zone', () => {
213214
});
214215
});
215216

216-
test('works with imported role', () => {
217+
testDeprecated('works with imported role', () => {
217218
// GIVEN
218219
const app = new App();
219220
const stack = new Stack(app, 'Stack', {
@@ -238,7 +239,7 @@ test('works with imported role', () => {
238239
});
239240

240241

241-
test('throws when domain name is longer than 64 characters', () => {
242+
testDeprecated('throws when domain name is longer than 64 characters', () => {
242243
const stack = new Stack();
243244

244245
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -252,7 +253,7 @@ test('throws when domain name is longer than 64 characters', () => {
252253
}).toThrow(/Domain name must be 64 characters or less/);
253254
}),
254255

255-
test('does not throw when domain name is longer than 64 characters with tokens', () => {
256+
testDeprecated('does not throw when domain name is longer than 64 characters with tokens', () => {
256257
const stack = new Stack();
257258
const zoneName = 'example.com';
258259
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -293,7 +294,7 @@ test('does not throw when domain name is longer than 64 characters with tokens',
293294
});
294295
});
295296

296-
test('test transparency logging settings is passed to the custom resource', () => {
297+
testDeprecated('test transparency logging settings is passed to the custom resource', () => {
297298
const stack = new Stack();
298299

299300
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -321,7 +322,7 @@ test('test transparency logging settings is passed to the custom resource', () =
321322
});
322323
});
323324

324-
test('can set removal policy', () => {
325+
testDeprecated('can set removal policy', () => {
325326
const stack = new Stack();
326327

327328
const exampleDotComZone = new PublicHostedZone(stack, 'ExampleDotCom', {

packages/@aws-cdk/aws-certificatemanager/test/util.test.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PublicHostedZone } from '@aws-cdk/aws-route53';
2+
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
23
import { App, Aws, Stack } from '@aws-cdk/core';
34
import { Certificate, DnsValidatedCertificate } from '../lib';
45
import { apexDomain, getCertificateRegion, isDnsValidatedCertificate } from '../lib/util';
@@ -15,7 +16,7 @@ describe('apex domain', () => {
1516
});
1617

1718
describe('isDnsValidatedCertificate', () => {
18-
test('new DnsValidatedCertificate is a DnsValidatedCertificate', () => {
19+
testDeprecated('new DnsValidatedCertificate is a DnsValidatedCertificate', () => {
1920
const stack = new Stack();
2021

2122
const hostedZone = new PublicHostedZone(stack, 'ExampleDotCom', {
@@ -61,7 +62,7 @@ describe('getCertificateRegion', () => {
6162
expect(getCertificateRegion(certificate)).toEqual('eu-west-1');
6263
});
6364

64-
test('from DnsValidatedCertificate region', () => {
65+
testDeprecated('from DnsValidatedCertificate region', () => {
6566
// GIVEN
6667
const app = new App();
6768
const stack = new Stack(app, 'RegionStack', { env: { region: 'eu-west-1' } });

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ import * as acm from '@aws-cdk/aws-certificatemanager';
9999
import * as route53 from '@aws-cdk/aws-route53';
100100

101101
declare const hostedZone: route53.HostedZone;
102-
const myCertificate = new acm.DnsValidatedCertificate(this, 'mySiteCert', {
102+
const myCertificate = new acm.Certificate(this, 'mySiteCert', {
103103
domainName: 'www.example.com',
104-
hostedZone,
104+
validation: acm.CertificateValidation.fromDns(hostedZone),
105105
});
106106

107107
declare const myBucket: s3.Bucket;
@@ -574,7 +574,7 @@ just HTTP/3. For all supported HTTP versions, see the `HttpVerson` enum.
574574
```ts
575575
// Configure a distribution to use HTTP/2 and HTTP/3
576576
new cloudfront.Distribution(this, 'myDist', {
577-
defaultBehavior: { origin: new origins.HttpOrigin('www.example.com'); },
577+
defaultBehavior: { origin: new origins.HttpOrigin('www.example.com') },
578578
httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,
579579
});
580580
```

packages/@aws-cdk/aws-ecs-patterns/test/fargate/load-balanced-fargate-service.test.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Match, Template } from '@aws-cdk/assertions';
22
import { AutoScalingGroup } from '@aws-cdk/aws-autoscaling';
3-
import { DnsValidatedCertificate } from '@aws-cdk/aws-certificatemanager';
3+
import { Certificate, CertificateValidation } from '@aws-cdk/aws-certificatemanager';
44
import * as ec2 from '@aws-cdk/aws-ec2';
55
import { MachineImage } from '@aws-cdk/aws-ec2';
66
import * as ecs from '@aws-cdk/aws-ecs';
@@ -1013,9 +1013,9 @@ test('domainName and domainZone not required for HTTPS listener with provided ce
10131013
const exampleDotComZone = new route53.PublicHostedZone(stack, 'ExampleDotCom', {
10141014
zoneName: 'example.com',
10151015
});
1016-
const certificate = new DnsValidatedCertificate(stack, 'Certificate', {
1016+
const certificate = new Certificate(stack, 'Certificate', {
10171017
domainName: 'test.example.com',
1018-
hostedZone: exampleDotComZone,
1018+
validation: CertificateValidation.fromDns(exampleDotComZone),
10191019
});
10201020

10211021
// WHEN

packages/@aws-cdk/aws-route53-patterns/test/bucket-website-target.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Template } from '@aws-cdk/assertions';
22
import { Certificate } from '@aws-cdk/aws-certificatemanager';
33
import { HostedZone } from '@aws-cdk/aws-route53';
4+
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
45
import { App, Stack } from '@aws-cdk/core';
56
import { ROUTE53_PATTERNS_USE_CERTIFICATE } from '@aws-cdk/cx-api';
67
import { HttpsRedirect } from '../lib';
78

8-
test('create HTTPS redirect', () => {
9+
testDeprecated('create HTTPS redirect', () => {
910
// GIVEN
1011
const app = new App();
1112
const stack = new Stack(app, 'test', { env: { region: 'us-east-1' } });
@@ -63,7 +64,7 @@ test('create HTTPS redirect', () => {
6364
});
6465
});
6566

66-
test('create HTTPS redirect for apex', () => {
67+
testDeprecated('create HTTPS redirect for apex', () => {
6768
// GIVEN
6869
const app = new App();
6970
const stack = new Stack(app, 'test', { env: { region: 'us-east-1' } });
@@ -96,7 +97,7 @@ test('create HTTPS redirect for apex', () => {
9697
});
9798
});
9899

99-
test('create HTTPS redirect with existing cert', () => {
100+
testDeprecated('create HTTPS redirect with existing cert', () => {
100101
// GIVEN
101102
const app = new App();
102103
const stack = new Stack(app, 'test', { env: { region: 'us-east-1' } });

0 commit comments

Comments
 (0)