Terraform CloudFlare + Route53

August 03, 2024

As I mentioned early, I like to centralize my credentials on AWS Secrets Manager. We will be reading the CLOUDFLARE_API_TOKEN from a secret after creating one on CloudFlare.

data "aws_secretsmanager_secret" "secrets" {
  name = "terraform"
}

data "aws_secretsmanager_secret_version" "current" {
  secret_id = data.aws_secretsmanager_secret.secrets.id
}

provider "cloudflare" {
  api_token = jsondecode(data.aws_secretsmanager_secret_version.current.secret_string)["CLOUDFLARE_API_TOKEN"]
}

First of all, we must create our Route 53 zone with the subdomain you want to forward.

resource "aws_route53_zone" "this" {
  name = "the-subdomain.my-cloudflare-domain"
}

We assume you have a CloudFlare Zone with the same domain.

data "cloudflare_zone" "this" {
  name = "my-cloudflare-domain"
}

Now we can create a record for each of the 4 name servers.

resource "cloudflare_record" "this" {
  depends_on = [aws_route53_zone.this]

  count = 4

  zone_id = data.cloudflare_zone.this.id
  name    = "the-subdomain"
  type    = "NS"

  value = element(aws_route53_zone.this.name_servers, count.index)
}

Finally we can test creating something like a ACM Certificate and validating.

resource "aws_acm_certificate" "this" {
  domain_name       = "the-subdomain.my-cloudflare-domain"
  validation_method = "DNS"
}

resource "aws_route53_record" "valiation" {
  for_each = {
    for dvo in aws_acm_certificate.this.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         = aws_route53_zone.this.zone_id
}

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

I also like to add a shortcut to the AWS Console so you can hit F5 until the certificate status changes to Issued.

output "acm_console_url" {
  value = "https://${data.aws_region.current.name}.console.aws.amazon.com/acm/home#/certificates/${aws_acm_certificate.this.id}"
}

Written by João Oliveira in his brief moments of clarity.