Created
May 22, 2022 20:54
-
-
Save SlootSantos/61e44d7b869df94bae53d1a6697477ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
AwsCustomResource, | |
AwsCustomResourcePolicy, | |
PhysicalResourceId, | |
} from "aws-cdk-lib/custom-resources"; | |
import { Construct } from "constructs"; | |
import { CfnOutput, Fn } from "aws-cdk-lib"; | |
import { IHostedZone } from "aws-cdk-lib/aws-route53"; | |
import { domains } from "../../constants/domains"; | |
import { accounts } from "../../constants/accounts"; | |
import { NS_CREATION_ROLE_NAME } from "../../constants/roles"; | |
export const buildDelegatedNameServerRecord = ( | |
scope: Construct, | |
subdomain: string, | |
hostedZone: IHostedZone | |
) => { | |
const rootHostedZoneId = listHostedZone(scope, subdomain); | |
const { nsRecordsForHostedZone, nameServers } = getNameServerList(hostedZone); | |
createNameServerRecords( | |
scope, | |
hostedZone, | |
rootHostedZoneId, | |
nsRecordsForHostedZone | |
); | |
return nameServers; | |
}; | |
// with this custom resource we can list the hosted zones from the root-domain-account | |
const listHostedZone = (scope: Construct, subdomain: string) => { | |
const getRootHostedZoneSDK = { | |
service: "Route53", | |
action: "listHostedZonesByName", | |
physicalResourceId: PhysicalResourceId.fromResponse("HostedZones.0.Id"), | |
assumedRoleArn: `arn:aws:iam::${accounts.rootDomain}:role/${NS_CREATION_ROLE_NAME}`, | |
parameters: { | |
DNSName: `${subdomain}.${domains.root}`, | |
}, | |
region: "eu-central-1", | |
}; | |
const rootHostedZone = new AwsCustomResource(scope, "list-root-zones", { | |
policy: AwsCustomResourcePolicy.fromSdkCalls({ | |
resources: AwsCustomResourcePolicy.ANY_RESOURCE, | |
}), | |
onCreate: getRootHostedZoneSDK, | |
}); | |
const rootHostedZoneId = rootHostedZone.getResponseField("HostedZones.0.Id"); | |
return rootHostedZoneId; | |
}; | |
// we need to build an array of name servers for the hosted zone | |
// the list we get from the reference is not a JS array, hence cannot access elements via map or similar | |
const getNameServerList = (hostedZone: IHostedZone) => { | |
const nsRecordsForHostedZone = []; | |
const nameServers = []; | |
// we can make a fixed assumption here, as Route53 zones always have 4 name servers | |
for (let idx = 0; idx < 4; idx++) { | |
const fullyQualifiedNameServer = | |
Fn.select(idx, hostedZone.hostedZoneNameServers!) + "."; | |
const changeRecordSet = { | |
// we have to resolve the nameserver token at each index | |
Value: fullyQualifiedNameServer, | |
}; | |
nameServers.push(fullyQualifiedNameServer); | |
nsRecordsForHostedZone.push(changeRecordSet); | |
} | |
return { nsRecordsForHostedZone, nameServers }; | |
}; | |
// with this custom resource we can write the NS records to the hosted zone in the root-domain-account | |
const createNameServerRecords = ( | |
scope: Construct, | |
hostedZone: IHostedZone, | |
rootHostedZoneId: string, | |
nsRecordsForHostedZone: { Value: string }[] | |
) => { | |
const changeSet = { | |
Type: "NS", | |
Name: hostedZone.zoneName, | |
TTL: 60 * 5, // 5 minutes | |
ResourceRecords: nsRecordsForHostedZone, | |
}; | |
const baseParameters = { | |
region: "eu-central-1", | |
service: "Route53", | |
action: "changeResourceRecordSets", | |
physicalResourceId: PhysicalResourceId.of("zone-" + hostedZone.zoneName), | |
assumedRoleArn: `arn:aws:iam::${accounts.rootDomain}:role/${NS_CREATION_ROLE_NAME}`, | |
}; | |
const getChangeBatch = (action: "UPSERT" | "DELETE") => ({ | |
HostedZoneId: rootHostedZoneId, | |
ChangeBatch: { | |
Changes: [ | |
{ | |
Action: action, | |
ResourceRecordSet: changeSet, | |
}, | |
], | |
}, | |
}); | |
new AwsCustomResource(scope, "custom-resource-create-ns-records", { | |
policy: AwsCustomResourcePolicy.fromSdkCalls({ | |
resources: AwsCustomResourcePolicy.ANY_RESOURCE, | |
}), | |
onCreate: { | |
...baseParameters, | |
parameters: getChangeBatch("UPSERT"), | |
}, | |
onUpdate: { | |
...baseParameters, | |
parameters: getChangeBatch("UPSERT"), | |
}, | |
onDelete: { | |
...baseParameters, | |
parameters: getChangeBatch("DELETE"), | |
}, | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment