Skip to content

The acm.tf File

Filename Location Group Project/Repository
acm.tf ./acm.tf infrastructure terraform

Why?

Using Amazon Certificate Manager (ACM) we get free TLS certificates that are being updated for us automatically, we can validate ownership of the domain using Terraform and and we can just attach it to the ALB Listener with ease.

Without a TLS certificate attached to our ALB and terminating the TLS connections for us, we'll either have to expose our application to the Internet over plain text, transparent protocols like HTTP or terminate the TLS connections directly on our application servers. Neither is ideal.

Breakdown

First we define the certificate:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
resource "aws_acm_certificate" "cert" {
  validation_method = "DNS"
  domain_name       = "httpcats.net"
  subject_alternative_names = [
    "www.httpcats.net",
  ]

  lifecycle {
    create_before_destroy = true
  }
}

Then we create another DNS record inside of our Route53 Zone so that we can validate to ACM that we own the domain we're trying to create a TLS certificate for:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
resource "aws_route53_record" "httpcats" {
  for_each = {
    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.httpcats.zone_id
}

Notice how we're using the for_each and for functionality of Terraform to loop over the records that come out of the aws_acm_certificate we defined earlier.

Finally we validate the DNS records and then ACM issues the TLS certificate:

1
2
3
4
resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.httpcats : record.fqdn]
}

The Solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
resource "aws_acm_certificate" "cert" {
  validation_method = "DNS"
  domain_name       = "httpcats.net"
  subject_alternative_names = [
    "www.httpcats.net",
  ]

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "httpcats" {
  for_each = {
    for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.httpcats.zone_id
}

resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = aws_acm_certificate.cert.arn
  validation_record_fqdns = [for record in aws_route53_record.httpcats : record.fqdn]
}

Terraform Documentation

Type Documentation
aws_acm_certificate Terraform AWS Provider
aws_route53_record Terraform AWS Provider
aws_acm_certificate_validation Terraform AWS Provider

Committing the Code

  1. Set your working directory to the infrastructure/terraform repository
  2. Save the file as acm.tf and use git add acm.tf to add it to the Git staging area
  3. Use git commit -am 'creating a tls certificate for our ALB' to commit the file to our repository
  4. Push the code to GitLab.com: git push

Last update: August 25, 2021