1 | # Amazon Route53 Construct Library
|
2 |
|
3 |
|
4 | ---
|
5 |
|
6 | ![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge)
|
7 |
|
8 | ![cdk-constructs: Stable](https://img.shields.io/badge/cdk--constructs-stable-success.svg?style=for-the-badge)
|
9 |
|
10 | ---
|
11 |
|
12 |
|
13 |
|
14 | To add a public hosted zone:
|
15 |
|
16 | ```ts
|
17 | new route53.PublicHostedZone(this, 'HostedZone', {
|
18 | zoneName: 'fully.qualified.domain.com',
|
19 | });
|
20 | ```
|
21 |
|
22 | To add a private hosted zone, use `PrivateHostedZone`. Note that
|
23 | `enableDnsHostnames` and `enableDnsSupport` must have been enabled for the
|
24 | VPC you're configuring for private hosted zones.
|
25 |
|
26 | ```ts
|
27 | declare const vpc: ec2.Vpc;
|
28 |
|
29 | const zone = new route53.PrivateHostedZone(this, 'HostedZone', {
|
30 | zoneName: 'fully.qualified.domain.com',
|
31 | vpc, // At least one VPC has to be added to a Private Hosted Zone.
|
32 | });
|
33 | ```
|
34 |
|
35 | Additional VPCs can be added with `zone.addVpc()`.
|
36 |
|
37 | ## Adding Records
|
38 |
|
39 | To add a TXT record to your zone:
|
40 |
|
41 | ```ts
|
42 | declare const myZone: route53.HostedZone;
|
43 |
|
44 | new route53.TxtRecord(this, 'TXTRecord', {
|
45 | zone: myZone,
|
46 | recordName: '_foo', // If the name ends with a ".", it will be used as-is;
|
47 | // if it ends with a "." followed by the zone name, a trailing "." will be added automatically;
|
48 | // otherwise, a ".", the zone name, and a trailing "." will be added automatically.
|
49 | // Defaults to zone root if not specified.
|
50 | values: [ // Will be quoted for you, and " will be escaped automatically.
|
51 | 'Bar!',
|
52 | 'Baz?',
|
53 | ],
|
54 | ttl: Duration.minutes(90), // Optional - default is 30 minutes
|
55 | });
|
56 | ```
|
57 |
|
58 | To add a NS record to your zone:
|
59 |
|
60 | ```ts
|
61 | declare const myZone: route53.HostedZone;
|
62 |
|
63 | new route53.NsRecord(this, 'NSRecord', {
|
64 | zone: myZone,
|
65 | recordName: 'foo',
|
66 | values: [
|
67 | 'ns-1.awsdns.co.uk.',
|
68 | 'ns-2.awsdns.com.',
|
69 | ],
|
70 | ttl: Duration.minutes(90), // Optional - default is 30 minutes
|
71 | });
|
72 | ```
|
73 |
|
74 | To add a DS record to your zone:
|
75 |
|
76 | ```ts
|
77 | declare const myZone: route53.HostedZone;
|
78 |
|
79 | new route53.DsRecord(this, 'DSRecord', {
|
80 | zone: myZone,
|
81 | recordName: 'foo',
|
82 | values: [
|
83 | '12345 3 1 123456789abcdef67890123456789abcdef67890',
|
84 | ],
|
85 | ttl: Duration.minutes(90), // Optional - default is 30 minutes
|
86 | });
|
87 | ```
|
88 |
|
89 | To add an A record to your zone:
|
90 |
|
91 | ```ts
|
92 | declare const myZone: route53.HostedZone;
|
93 |
|
94 | new route53.ARecord(this, 'ARecord', {
|
95 | zone: myZone,
|
96 | target: route53.RecordTarget.fromIpAddresses('1.2.3.4', '5.6.7.8'),
|
97 | });
|
98 | ```
|
99 |
|
100 | To add an A record for an EC2 instance with an Elastic IP (EIP) to your zone:
|
101 |
|
102 | ```ts
|
103 | declare const instance: ec2.Instance;
|
104 |
|
105 | const elasticIp = new ec2.CfnEIP(this, 'EIP', {
|
106 | domain: 'vpc',
|
107 | instanceId: instance.instanceId,
|
108 | });
|
109 |
|
110 | declare const myZone: route53.HostedZone;
|
111 | new route53.ARecord(this, 'ARecord', {
|
112 | zone: myZone,
|
113 | target: route53.RecordTarget.fromIpAddresses(elasticIp.ref),
|
114 | });
|
115 | ```
|
116 |
|
117 | To add an AAAA record pointing to a CloudFront distribution:
|
118 |
|
119 | ```ts
|
120 | import * as cloudfront from '@aws-cdk/aws-cloudfront';
|
121 |
|
122 | declare const myZone: route53.HostedZone;
|
123 | declare const distribution: cloudfront.CloudFrontWebDistribution;
|
124 | new route53.AaaaRecord(this, 'Alias', {
|
125 | zone: myZone,
|
126 | target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
|
127 | });
|
128 | ```
|
129 |
|
130 | Constructs are available for A, AAAA, CAA, CNAME, MX, NS, SRV and TXT records.
|
131 |
|
132 | Use the `CaaAmazonRecord` construct to easily restrict certificate authorities
|
133 | allowed to issue certificates for a domain to Amazon only.
|
134 |
|
135 | To add a NS record to a HostedZone in different account you can do the following:
|
136 |
|
137 | In the account containing the parent hosted zone:
|
138 |
|
139 | ```ts
|
140 | const parentZone = new route53.PublicHostedZone(this, 'HostedZone', {
|
141 | zoneName: 'someexample.com',
|
142 | crossAccountZoneDelegationPrincipal: new iam.AccountPrincipal('12345678901'),
|
143 | crossAccountZoneDelegationRoleName: 'MyDelegationRole',
|
144 | });
|
145 | ```
|
146 |
|
147 | In the account containing the child zone to be delegated:
|
148 |
|
149 | ```ts
|
150 | const subZone = new route53.PublicHostedZone(this, 'SubZone', {
|
151 | zoneName: 'sub.someexample.com',
|
152 | });
|
153 |
|
154 | // import the delegation role by constructing the roleArn
|
155 | const delegationRoleArn = Stack.of(this).formatArn({
|
156 | region: '', // IAM is global in each partition
|
157 | service: 'iam',
|
158 | account: 'parent-account-id',
|
159 | resource: 'role',
|
160 | resourceName: 'MyDelegationRole',
|
161 | });
|
162 | const delegationRole = iam.Role.fromRoleArn(this, 'DelegationRole', delegationRoleArn);
|
163 |
|
164 | // create the record
|
165 | new route53.CrossAccountZoneDelegationRecord(this, 'delegate', {
|
166 | delegatedZone: subZone,
|
167 | parentHostedZoneName: 'someexample.com', // or you can use parentHostedZoneId
|
168 | delegationRole,
|
169 | });
|
170 | ```
|
171 |
|
172 | ## Imports
|
173 |
|
174 | If you don't know the ID of the Hosted Zone to import, you can use the
|
175 | `HostedZone.fromLookup`:
|
176 |
|
177 | ```ts
|
178 | route53.HostedZone.fromLookup(this, 'MyZone', {
|
179 | domainName: 'example.com',
|
180 | });
|
181 | ```
|
182 |
|
183 | `HostedZone.fromLookup` requires an environment to be configured. Check
|
184 | out the [documentation](https://docs.aws.amazon.com/cdk/latest/guide/environments.html) for more documentation and examples. CDK
|
185 | automatically looks into your `~/.aws/config` file for the `[default]` profile.
|
186 | If you want to specify a different account run `cdk deploy --profile [profile]`.
|
187 |
|
188 | ```text
|
189 | new MyDevStack(app, 'dev', {
|
190 | env: {
|
191 | account: process.env.CDK_DEFAULT_ACCOUNT,
|
192 | region: process.env.CDK_DEFAULT_REGION,
|
193 | },
|
194 | });
|
195 | ```
|
196 |
|
197 | If you know the ID and Name of a Hosted Zone, you can import it directly:
|
198 |
|
199 | ```ts
|
200 | const zone = route53.HostedZone.fromHostedZoneAttributes(this, 'MyZone', {
|
201 | zoneName: 'example.com',
|
202 | hostedZoneId: 'ZOJJZC49E0EPZ',
|
203 | });
|
204 | ```
|
205 |
|
206 | Alternatively, use the `HostedZone.fromHostedZoneId` to import hosted zones if
|
207 | you know the ID and the retrieval for the `zoneName` is undesirable.
|
208 |
|
209 | ```ts
|
210 | const zone = route53.HostedZone.fromHostedZoneId(this, 'MyZone', 'ZOJJZC49E0EPZ');
|
211 | ```
|
212 |
|
213 | You can import a Public Hosted Zone as well with the similar `PubicHostedZone.fromPublicHostedZoneId` and `PubicHostedZone.fromPublicHostedZoneAttributes` methods:
|
214 |
|
215 | ```ts
|
216 | const zoneFromAttributes = route53.PublicHostedZone.fromPublicHostedZoneAttributes(this, 'MyZone', {
|
217 | zoneName: 'example.com',
|
218 | hostedZoneId: 'ZOJJZC49E0EPZ',
|
219 | });
|
220 |
|
221 | // Does not know zoneName
|
222 | const zoneFromId = route53.PublicHostedZone.fromPublicHostedZoneId(this, 'MyZone', 'ZOJJZC49E0EPZ');
|
223 | ```
|
224 |
|
225 | ## VPC Endpoint Service Private DNS
|
226 |
|
227 | When you create a VPC endpoint service, AWS generates endpoint-specific DNS hostnames that consumers use to communicate with the service.
|
228 | For example, vpce-1234-abcdev-us-east-1.vpce-svc-123345.us-east-1.vpce.amazonaws.com.
|
229 | By default, your consumers access the service with that DNS name.
|
230 | This can cause problems with HTTPS traffic because the DNS will not match the backend certificate:
|
231 |
|
232 | ```console
|
233 | curl: (60) SSL: no alternative certificate subject name matches target host name 'vpce-abcdefghijklmnopq-rstuvwx.vpce-svc-abcdefghijklmnopq.us-east-1.vpce.amazonaws.com'
|
234 | ```
|
235 |
|
236 | Effectively, the endpoint appears untrustworthy. To mitigate this, clients have to create an alias for this DNS name in Route53.
|
237 |
|
238 | Private DNS for an endpoint service lets you configure a private DNS name so consumers can
|
239 | access the service using an existing DNS name without creating this Route53 DNS alias
|
240 | This DNS name can also be guaranteed to match up with the backend certificate.
|
241 |
|
242 | Before consumers can use the private DNS name, you must verify that you have control of the domain/subdomain.
|
243 |
|
244 | Assuming your account has ownership of the particular domain/subdomain,
|
245 | this construct sets up the private DNS configuration on the endpoint service,
|
246 | creates all the necessary Route53 entries, and verifies domain ownership.
|
247 |
|
248 | ```ts nofixture
|
249 | import { Stack } from '@aws-cdk/core';
|
250 | import { Vpc, VpcEndpointService } from '@aws-cdk/aws-ec2';
|
251 | import { NetworkLoadBalancer } from '@aws-cdk/aws-elasticloadbalancingv2';
|
252 | import { PublicHostedZone, VpcEndpointServiceDomainName } from '@aws-cdk/aws-route53';
|
253 |
|
254 | const stack = new Stack();
|
255 | const vpc = new Vpc(stack, 'VPC');
|
256 | const nlb = new NetworkLoadBalancer(stack, 'NLB', {
|
257 | vpc,
|
258 | });
|
259 | const vpces = new VpcEndpointService(stack, 'VPCES', {
|
260 | vpcEndpointServiceLoadBalancers: [nlb],
|
261 | });
|
262 | // You must use a public hosted zone so domain ownership can be verified
|
263 | const zone = new PublicHostedZone(stack, 'PHZ', {
|
264 | zoneName: 'aws-cdk.dev',
|
265 | });
|
266 | new VpcEndpointServiceDomainName(stack, 'EndpointDomain', {
|
267 | endpointService: vpces,
|
268 | domainName: 'my-stuff.aws-cdk.dev',
|
269 | publicHostedZone: zone,
|
270 | });
|
271 | ```
|