DNS
Objective
Establish a domain name, setup subdomains, and delegate control of subdomains to AWS accounts.
Background
Domain Name Service (DNS) is what allows you to connect
to networked services by human-readable names (e.g., panfactum.com
) instead of IP addresses (1.2.3.4
). It also
plays an important role in X.509 certificate infrastructure which underpins
security on the modern internet (e.g., TLS/SSL).
AWS Route 53 is AWS's suite of DNS utilities. It includes both a registrar (an organization that allows you to lease domain names) and a managed DNS server (Hosted Zones) for hosting individual DNS records.
Purchase Domain Name(s)
-
Login to your
production
account in the AWS web console (or whichever account will host your client-facing infrastructure). -
Navigate to Route 53 > Registered domains.
-
Select "Register domains."
-
Search for the domain(s) you want to purchase and add them to your cart.
-
Checkout and ensure you enable auto-renew.
Deploy the AWS Registered Domains Module
To use your domain registrations in IaC and to align them with best practices, we will now deploy the aws_registered_domains module. 1
This module will not register / unregister domains, only update the registration settings. In addition, it will set up the root hosted zones and enable DNSSEC to prevent domain hijacking.
Let's deploy the module now:
-
When you purchased your domain name, AWS may have automatically set up a hosted zone for you. You should delete the automatically generated zone as this module will create one for you. 2
-
Add a new
aws_registered_domains
folder to yourproduction
environment in theglobal
region. -
Add a new
terragrunt.hcl
file that looks like this.Note that we use sops-encrypted values here as we did in the
aws_account
module. It is up to you what you leave encrypted / unencrypted throughout this guide. However, if you choose to use encrypted values, ensure that you create an encryptedsecrets.yaml
. -
Run
pf-tf-init
to enable the required providers. -
Run
terragrunt apply
.
Verify DNS Resolution Works
To verify that everything is working as expected:
-
Navigate to the hosted zone via the AWS web console (Route 53 > Hosted Zone).
-
View the DNSSEC signing section. It should appear as follows:
-
Add a new
A
record undertest
pointing to1.1.1.1
to your hosted zone via the AWS management console. -
Run
delv @1.1.1.1 test.panfactum.com
(replacepanfactum.com
with your domain name). 3 You should see a result that looks as follows:; fully validated test.panfactum.com. 300 IN A 1.1.1.1 test.panfactum.com. 300 IN RRSIG A 13 3 300 20240322220955 20240322200455 11333 panfactum.com. NX8hwISu5w6ZhHKPsawBMeb3XarIMZiDzv1Rxlb584vQgziAx67aX8KK xPS6vQlMtW6jwfWOrhNYLHTrEpIKww==
The presence of
; fully validated
verifies that DNSSEC is working as intended. TheRRSIG
record is the digital signature for the record set. -
Remove the test record.
Set Up Delegated Zones
Each environment will have its own subdomain for each root domain (e.g., dev.panfactum.com
). This
subdomain will be managed by its own hosted zone (not the root hosted zone). This provides the following benefits:
-
Limits the blast radius if something is misconfigured. At most, a configuration problem will impact only a single environment without the possibility of impacting other environments (or worse, your entire DNS infrastructure).
-
Limits the permissions needed to be granted to users and services in each environment. To add records to the subdomain
dev.panfactum.com
, a user would not need any access to records in other environments. This would not be possible if all records were stored in a single, global hosted zone.
This is accomplished via a concept called subdomain delegation. Panfactum's aws_delegated_zones will provide the relevant setup for this to work.
Let's do this now for every environment:
-
Choose a set of subdomain identifiers. For example, for
production
you might use the subdomainsprod
andproduction
. -
Add a new directory in
production/global
calledaws_delegated_zones_<environment>
where<environment>
is replaced with the environment name for this set of subdomains. -
Create a
terragrunt.hcl
that looks like this. 4 Use the appropriatesubdomain_identifiers
for your environment. -
Create a
module.yaml
.-
Run
pf-tf-init
to generate themodule.yaml
and enable the required providers. -
Set the
aws_account_id
andaws_profile
to the appropriate values for the target environment.For example, if setting up
aws_delegated_zones_development
, theaws_account_id
should be set to your development account and theaws_profile
should be set to your profile for creating resources in the development account (e.g.,development-superuser
).Note that this module deploys resources in multiple accounts: it uses the primary
aws
provider to deploy the hosted zones in the target environment account and the secondaryaws
provider to deploy the appropriate DNS records in root hosted zone inside theproduction
environment. -
Set
aws_secondary_region
to your primary region. -
Set
module
toaws_delegated_zones
since we are using a directory nameaws_delegated_zones_<environment>
that is different from the Panfactum moduleaws_delegated_zones
.
-
-
Run
terragrunt apply
.
Verify DNS Resolution Works (Subdomains)
To verify that everything is working as expected, follow the guide from the previous section but for the subdomain zone. This will require you to log in to the respective AWS account.
You would test via delv @1.1.1.1 test.<your_subdomain_identifier>.<your_root_domain>
. Ensure that this
shows both the return A
record and the dnssec signature.
Deploy Records
If you have static records to deploy, you can use our aws_dns_records module to deploy them to the appropriate hosted zone.
Specifically, now would be a good time to migrate and/or set up your MX records for your primary email provider.
In the future, we will set up a mechanism to ensure that DNS records for all of our Panfactum stack infrastructure is automatically deployed and updated without manual intervention.
Next Steps
Now that you have prepared your DNS configuration, we are ready to begin setting up the Panfactum stack. Our next step is to configure AWS networking by creating a Virtual Private Cloud (VPC).
Footnotes
-
The domains will have the following defaults you can override if desired: privacy protection, auto-renewal, and transfer lock. For more information, refer to the module documentation. ↩
-
If the zone does not exist, you may skip this step. If you want to keep this zone, follow the import instructions above. ↩
-
Note that
@1.1.1.1
instructsdelv
to use Cloudflare's DNS servers instead of your network's default. Some intermediate DNS servers do not support DNSSEC and will actually strip the relevant information from the returned responses. This is particularly prevalent for consumer hardware and ISPs. ↩ -
Note that this is the first time we will take advantage of terragrunt's dependency blocks to use the outputs of one module as inputs into another. ↩