AWS Certificate Manager DNS Validation with Terraform

Andrew Larsen
AWS Tip
Published in
4 min readApr 2, 2021

--

As part of our journey building out our new SaaS product Compoze, our team will be documenting their progress and lessons learned along the way. This particular learning comes from our experience with Terraform and AWS Certificate Manager.

AWS Certificate Manager

AWS Certificate Manager (ACM) takes the pain out of signing and managing certificates within the AWS ecosystem. While tools like LetsEncrypt make this processes much easier, why deal with it if you don’t have to?

We’ve used ACM on nearly all of our AWS projects, both for client project, as well as for our new product Compoze. One major pain point we’ve experienced was validating these certificates via our Infrastructure as Code (IaC) pipelines. All infrastructure we create is built with some IaC tool, usually Terraform (depending on the use case of course).

ACM Certificate Validation

In order to sign a new certificate, the certificate authority (CA), needs to verify that you own the registered domain. In order to do this, AWS Certificate Manager supports two different methods for validating a certificate: Email and DNS. What’s the difference?

Email Validation

For email validation, AWS sends an email to the contact emails configured for the registered domain. These emails can be found in Route 53 under the Registered Domain tab.

image from https://aws.amazon.com/blogs/aws/route-53-domain-reg-geo-route-price-drop/

The email that Amazon sends provides a link to manually approve the creation of the certificate, thus certifying that you own the domain and approve the certificate to be signed. The email looks something like the below figure:

image from https://github.com/awsdocs/aws-certificate-user-guide/blob/master/doc_source/gs-acm-validate-email.md

DNS Validation

For DNS Validation, AWS verifies that you own the registered down by making a call to a CNAME record, configured in your Hosted Zone. This record will look something like this:

image from https://docs.aws.amazon.com/acm/latest/userguide/dns-validation.html

In the past we relied on email validation for our certificates. However, as our pipelines started to expand and more certificates were being provisioned, the overhead of manually approving certificates began to build. Since we want our pipelines to require as little manual intervention as possible, the email validation was not going to work long term.

Terraform and DNS Validation

We did some investigation into how to configure DNS Validation with Terraform and came up with the following solution:

First we needed to configure the certificate itself, and rather than specifying email, we used DNS for the validation_method

Next, we needed to tell Terraform to create the DNS validation CNAME record in our hosted zone. We did this by configuring a aws_route53_record. The resource loops over each domain validation option (dvo) and creates the appropriate record sets.

It’s worth noting that the below also assumes an aws_route_53 zone already exists.

Finally, we needed to tell Terraform to kick off the validation process. This is done via the acm_certificate_validation resource.

It’s worth noting that the acm_certificate_validation resource does not actually represent physical infrastructure, like traditional Terraform resources do. More details can be found in the official Terraform Docs.

Once you perform terraform apply you will see that the certificate has been successfully validated!

You can also log into the ACM console and see that the certificate has been issued

image from https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-describe.html

And below is the full example

There were a couple of gotchas along the way that are worth mentioning:

  1. After registering our domain via Route53, we naively tried to managed our own hosted zone via Terraform. However, what we found was that this lead to a mismatch between the Registered Domain and the new Hosted Zone. Since we had already deleted the original Hosted Zone, we had to update our domain with the new Hosted Zone’s Name Servers. How to do that can be found in the AWS Docs here.
  2. Since we could not initially manage the Hosted Zone with Terraform, we ran into trouble with how to give the certificate validation a Hosted Zone Id. We chose the path of using Terraform Import to bring the existing Hosted Zone under management of Terraform.
  3. We found out the hard way that the default timeout for Terraform’s aws_acm_certificate_validation is 45 minutes. We ended up being stuck with a running process in Terraform Cloud for the full 45 minutes. Make sure to configure the timeout to something more reasonable (we set it to 5 minutes)

And that’s it. As we continue to build Compoze we plan to share more learnings we have along the way!

--

--