Networking & Content Delivery

Automating Domain Delegation for Public Applications in AWS

Security is top priority at AWS. Cybersecurity and digital risk management are the primary considerations of customers when ensuring that security and trust are always in place for a secure data and cloud infrastructure. These concerns are even more critical for public internet facing applications, which are accessed using a public domain. In AWS Cloud, the Amazon Route 53 service connects end users to internet applications by managing Domain Name System (DNS) records for a domain. In a multi-account cloud environment, the same base public domain may need to be accessible across different accounts (e.g., dev, test, production) for different internet-facing applications. To resolve the base public domain, zone ownership can be defined in all of these accounts. However, this puts a critical networking component of the infrastructure at risk of alteration and undesirable access.

In this post, we describe a secure architecture to share Route 53 domains across AWS accounts by delegating a public domain from a central networking account to other accounts where applications can consume the domain by creating application service-specific subdomains. Changes to subdomains don’t affect the central top-level domain. Then, we’ll walk through the Infrastructure as Code (IaC) automation to implement the Route 53 zone delegation architecture using AWS Cloud Development Kit (AWS CDK). In the end, we’ll discuss an example architecture for hosting internet facing applications securely in AWS.

Solution architecture

Route 53 connects user requests to infrastructure running within AWS. It’s a highly available and scalable cloud DNS web service that translates host names to IP addresses. In a multi-account implementation of AWS Organizations, you typically create the root domain in the DNS account or in a central networking account. Then, you may choose to create different accounts to run different workload types – development, test, production, and so on – or you may segregate individual application workloads into separate accounts to reduce the blast radius.

Customers using services such as Amazon Elastic Container Service (Amazon ECS), Amazon Elastic Kubernetes Service (Amazon EKS), Amazon CloudFront, and Amazon API Gateway in the application accounts require access to the account hosting the root domain to create custom subdomains and to apply certificates issued by Amazon Certificate Manager (ACM) or a third-party certificate. This cross-account access requirement is even more challenging while provisioning infrastructure using IaC in an automated deployment pipeline, such as AWS CDK and AWS CodePipeline.

In the diagram that follows, we demonstrate how to programmatically delegate a public domain from a central networking account to consumer application accounts using Route 53 zone delegation.

Figure 1: Route 53 zone Delegation Automation Architecture

The key points in the design are described as follows. Numbered items refer to the figure above.

  1. We used AWS CDK for Python to develop the infrastructure code and stored the code in an AWS CodeCommit repository.
  2. CodePipeline integrates the AWS CDK stacks for automated builds into the central networking account and the consumer application account.
  3. The central networking accounts host the top-level domain (e.g., amazon.com) for your organization, along with the subdomain (build.amazon.com) that you want to delegate to other accounts.
  4. Delegated hosted zone information is saved into the AWS Systems Manager Parameter Store for cross-account retrieval.
  5. The AWS Lambda function in the application ingress account retrieves the parent level hosted zone information from the central networking account Systems Manager Parameter Store by assuming an AWS Identity and Access Management (IAM) role that has the necessary read access.
  6. Now you can create the application-specific subdomains (e.g., dev.build.amazon.com, test.build.amazon.com) in Route 53 of the consumer application account.
  7. Apply certificates issued by ACM on the subdomains that you create.

Automation Using AWS CDK

Using the AWS Console, you can create a public hosted zone (e.g., amazon.com) in Route 53 which will then be delegated to other accounts via subdomains (e.g., build.amazon.com). The AWS CDK code that we’ve provided in this blog creates and delegates the hosted zone for you in the central networking account.

The hosted zone delegation must be automated using IaC, as you might need to add more subdomains to the top-level domain for delegation as you migrate and give cross-account access to the delegated zones to build applications in the cloud. For this automation to work, the Systems Manager Parameter Store saves the hosted zone information and IAM roles are given read access to Systems Manager for cross-account hosted zone retrieval.

The AWS CDK stacks use a Lambda function to retrieve the delegated subdomain hosted zone information. Then it creates application specific subdomains in the consumer application account and applies certificates issued by ACM on the custom subdomains.

The development resources (CodeCommit for hosting the AWS CDK in Python code, CodePipeline for deployment of services) are created in a central AWS account. From this account, CodePipeline deploys the automated code to a central networking account and the consumer application accounts.

Prerequisites

To deploy the AWS CDK stacks from the source code, you must review and perform the prerequisites described in the accompanying GitHub repository to make sure that you have the necessary resources to proceed.

Launch the solution

1. Clone the GitHub repository, check out the zone_delegate branch, and move into the aws-fargate-with-rstudio-open-source folder.

git clone -b zone-delegate https://github.com/aws-samples/aws-fargate-with-rstudio-open-source.git

2. Create a CodeCommit repository to hold the source code for installation of the automated Route 53 Zone Delegation application with the following command:

aws codecommit --profile < AWS CLI profile of the central development account > create-repository --repository-name <name of repository>

3. Pass the required parameters in cdk.json following Step 4 in the Installation Steps section of the readme file.

4. Install the package requirements for the AWS CDK application:

python3 -m pip install -r requirements.txt

5. Before committing the code into the CodeCommit repository, synthesize the AWS CDK stacks. This makes sure that all of the necessary context values are populated into the cdk.context.json file and avoids the dummy values being mapped.

cdk synth --profile <AWS CLI profile of the central development account>

cdk synth --profile <AWS CLI profile of the central network account>

cdk synth --profile <AWS CLI profile of the consumer application account>

6. Commit the changes into the CodeCommit repo you created. Follow Step 6 in the Installation Steps of the readme if you need help with the Git commands.

7. Deploy the AWS CDK stacks to install Route 53 Zone Delegation application using CodePipeline. This step takes approximately 15 minutes.

cdk deploy --profile <AWS CLI profile of the central development account>

8. Navigate to the CodePipeline console (the link takes you to the eu-west-1 Region). Monitor the pipeline and confirm that the services are built successfully.
The pipeline name is R53-Zone-Delegation-<instance>. From this point onward, the pipeline is triggered on commits to the CodeCommit repository that you created. There’s no need to run cdk deploy (Step 7) anymore.

Figure 2: Route53 Zone Delegation Pipeline

Cleaning up

Please follow the readme in the repository to delete the stacks created.

Internet-facing application architecture in AWS

Strong network perimeter controls are mandatory for workloads exposed to the public internet. Guarding these perimeters with appropriate security controls ensure access and data security in the cloud. Delegating Route 53 public hosted zones across accounts only provides management and ease of secure access to the DNS records of the domains and subdomains. We must still securely architect the applications using these custom subdomains for public internet access.

Here we provide an example of the architecture for running your application from private subnets in AWS and exposing it to the internet using Elastic Load Balancing (ELB), AWS PrivateLink, and delegated public hosted zones in Route 53, along with the necessary security services for network perimeter security.

Internet-Facing Application Architecture in AWS

Figure 3: Internet-Facing Application Architecture in AWS

The key points in the design are described as follows. Numbered items refer to the figure above.

  1. Delegate the root subdomain from the central networking account to the consumer application ingress account.
  2. Incoming user requests to application ingress account reach AWS Shield, which provides DDoS protection for the Route 53 resources. You can also subscribe to AWS Shield Advanced for a higher level of protection against attacks targeting your deployment.
  3. AWS Web Application Firewall (WAF) inspects ingress traffic against a set of rules that you define. You can also restrict access to your application only from approved IP ranges by defining IP Set rules in AWS WAF. AWS Firewall Manager helps you centrally manage firewall rules across your AWS accounts.
  4. A VPC endpoint in the application ingress account points to the private applications that the users want to reach.
  5. PrivateLink creates the private communication channel using the VPC endpoint for the privately hosted applications.
  6. User requests reach the Network Load Balancer (NLB), the endpoint for the PrivateLink.
  7. The NLB passes the requests on to the Application Load Balancer (ALB) serving the application http(s) targets in the Fargate containers. You can use the NLB for TCP/UDP targets. Please refer to Application Load Balancer-type Target Group for Network Load Balancer for an example configuration.
  8. An Amazon ECS cluster runs the privately hosted applications on AWS Fargate Launch type.

Using this example architecture, you can securely configure public access to your privately hosted applications in AWS. If the applications require internet connectivity from the private Fargate tasks, then you should configure a secure egress mechanism using AWS Network Firewall.

Conclusion

In this blog, we explained how to securely share Route 53 domains and subdomains in Route 53 for ease of DNS records management in a multi-account AWS environment. Using the code provided in this post, you can automate your Route 53 hosted zone delegation, custom subdomain creation, and certificate management. We also provided an example architecture pattern to securely host your public internet-facing applications in AWS.

Chayan Panda

Chayan Panda

Chayan Panda is a Senior Cloud Infrastructure Architect with Amazon Web Services in the UK. He has 25 years of experience in technology advisory and enterprise architecture domains. He enables AWS enterprise customers to build secure, scalable and reliable digital transformation solutions. In his spare time, he enjoys a short run, music, a book or travel with his family.