Skip to content

Commit

Permalink
fix(route53-targets): A/AAAA Alias Record to ELB cannot resolve IPv6 …
Browse files Browse the repository at this point in the history
…addresses (#8747)

**[ISSUE]**
Route53 A/AAAA Alias Record created by CDK didn't add prefix 'dualstack' to the dnsName of ElasticLoadBalancer as suggested in [documentation](https://aws.amazon.com/de/premiumsupport/knowledge-center/alias-resource-record-set-route53-cli/), resulting in inability to resolve IPv6 records (outcome consistent with these [docs](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-internet-facing-load-balancers.html)).

**[APPROACH]**
Joined prefix: _dualstack_ to DNS of ELB targets to resolve IPv6 records. 

Example:
> If ELB DNS name is `ALB-xxxxxxxx.us-west-2.elb.amazonaws.com`,
> Route53 A/AAAA Alias Record will create Alias Target `dualstack.ALB-xxxxxxxx.us-west-2.elb.amazonaws.com`

**[NOTE]** 
Ignoring the case of using `ApiGatewayDomain(domainName)` because the prefix of 'dualstack' should be added in the `domainName` parameter.

```
new route53.ARecord(this, 'AliasRecord', {
  zone,
  target: route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
});
```

If creating an ApiGatewayDomain for ELB, endpoint for ELB with prefix 'dualstack' should be declared there, not within route53 package.

Fixes #6271 

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
BryanPan342 authored Jun 26, 2020
1 parent d2ae4bc commit 87e2651
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 15 deletions.
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ export = {
Type: 'A',
AliasTarget: {
HostedZoneId: { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'CanonicalHostedZoneID'] },
DNSName: { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'DNSName'] },
DNSName: { 'Fn::Join': ['', [ 'dualstack.', { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'DNSName'] } ] ] },
},
}));

Expand Down Expand Up @@ -501,7 +501,7 @@ export = {
Type: 'A',
AliasTarget: {
HostedZoneId: { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'CanonicalHostedZoneID'] },
DNSName: { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'DNSName'] },
DNSName: { 'Fn::Join': [ '', [ 'dualstack.', { 'Fn::GetAtt': ['ServiceLBE9A1ADBC', 'DNSName'] } ] ] },
},
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,9 +618,18 @@
"Type": "A",
"AliasTarget": {
"DNSName": {
"Fn::GetAtt": [
"myServiceLB168895E1",
"DNSName"
"Fn::Join":
[
"",
[
"dualstack.",
{
"Fn::GetAtt": [
"myServiceLB168895E1",
"DNSName"
]
}
]
]
},
"HostedZoneId": {
Expand Down
11 changes: 8 additions & 3 deletions packages/@aws-cdk/aws-route53-targets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This library contains Route53 Alias Record targets for:
new route53.ARecord(this, 'AliasRecord', {
zone,
target: route53.RecordTarget.fromAlias(new alias.ApiGateway(restApi)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomainName(domainName)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
});
```
* CloudFront distributions
Expand All @@ -28,17 +28,22 @@ This library contains Route53 Alias Record targets for:
new route53.ARecord(this, 'AliasRecord', {
zone,
target: route53.RecordTarget.fromAlias(new alias.LoadBalancerTarget(elbv2)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomainName(domainName)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
});
```
* Classic load balancers
```ts
new route53.ARecord(this, 'AliasRecord', {
zone,
target: route53.RecordTarget.fromAlias(new alias.ClassicLoadBalancerTarget(elb)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomainName(domainName)),
// or - route53.RecordTarget.fromAlias(new alias.ApiGatewayDomain(domainName)),
});
```

**Important:** Based on [AWS documentation](https://aws.amazon.com/de/premiumsupport/knowledge-center/alias-resource-record-set-route53-cli/), all alias record in Route 53 that points to a Elastic Load Balancer will always include *dualstack* for the DNSName to resolve IPv4/IPv6 addresses (without *dualstack* IPv6 will not resolve).

For example, if the Amazon-provided DNS for the load balancer is `ALB-xxxxxxx.us-west-2.elb.amazonaws.com`, CDK will create alias target in Route 53 will be `dualstack.ALB-xxxxxxx.us-west-2.elb.amazonaws.com`.

* InterfaceVpcEndpoints

**Important:** Based on the CFN docs for VPCEndpoints - [see here](attrDnsEntries) - the attributes returned for DnsEntries in CloudFormation is a combination of the hosted zone ID and the DNS name. The entries are ordered as follows: regional public DNS, zonal public DNS, private DNS, and wildcard DNS. This order is not enforced for AWS Marketplace services, and therefore this CDK construct is ONLY guaranteed to work with non-marketplace services.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class ClassicLoadBalancerTarget implements route53.IAliasRecordTarget {
public bind(_record: route53.IRecordSet): route53.AliasRecordTargetConfig {
return {
hostedZoneId: this.loadBalancer.loadBalancerCanonicalHostedZoneNameId,
dnsName: this.loadBalancer.loadBalancerDnsName,
dnsName: `dualstack.${this.loadBalancer.loadBalancerDnsName}`,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class LoadBalancerTarget implements route53.IAliasRecordTarget {
public bind(_record: route53.IRecordSet): route53.AliasRecordTargetConfig {
return {
hostedZoneId: this.loadBalancer.loadBalancerCanonicalHostedZoneId,
dnsName: this.loadBalancer.loadBalancerDnsName,
dnsName: `dualstack.${this.loadBalancer.loadBalancerDnsName}`,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test('use classic ELB as record target', () => {
// THEN
expect(stack).toHaveResource('AWS::Route53::RecordSet', {
AliasTarget: {
DNSName: { 'Fn::GetAtt': [ 'LB8A12904C', 'DNSName' ] },
DNSName: { 'Fn::Join': [ '', [ 'dualstack.', { 'Fn::GetAtt': [ 'LB8A12904C', 'DNSName' ] } ] ] },
HostedZoneId: { 'Fn::GetAtt': [ 'LB8A12904C', 'CanonicalHostedZoneNameID' ] },
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,17 @@
"Type": "A",
"AliasTarget": {
"DNSName": {
"Fn::GetAtt": [
"LB8A12904C",
"DNSName"
"Fn::Join": [
"",
[
"dualstack.",
{
"Fn::GetAtt": [
"LB8A12904C",
"DNSName"
]
}
]
]
},
"HostedZoneId": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test('use ALB as record target', () => {
// THEN
expect(stack).toHaveResource('AWS::Route53::RecordSet', {
AliasTarget: {
DNSName: { 'Fn::GetAtt': [ 'LB8A12904C', 'DNSName' ] },
DNSName: { 'Fn::Join': [ '', [ 'dualstack.', { 'Fn::GetAtt': [ 'LB8A12904C', 'DNSName' ] } ] ] },
HostedZoneId: { 'Fn::GetAtt': [ 'LB8A12904C', 'CanonicalHostedZoneID' ] },
},
});
Expand Down

0 comments on commit 87e2651

Please sign in to comment.