fizz.today

ACM wildcard and apex certs share the same validation CNAME

Requested an ACM certificate with a wildcard SAN:

resource "aws_acm_certificate" "main" {
  domain_name               = "fizz.today"
  subject_alternative_names = ["*.fizz.today"]
  validation_method         = "DNS"
}

Terraform plan showed two domain_validation_options entries. Wrote a for_each over them to create DNS validation records. Cloudflare rejected the second record as a duplicate.

The cause

ACM’s DNS validation for fizz.today and *.fizz.today produces the same CNAME record. Same name, same value. They’re validated by a single DNS entry.

But domain_validation_options returns two items — one per domain name on the cert. If you naively iterate, you try to create the same DNS record twice:

# BROKEN — creates duplicate records
resource "cloudflare_dns_record" "acm_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options :
    dvo.domain_name => dvo
  }
  # ...
}

Two entries keyed by fizz.today and *.fizz.today, both pointing to the same _acm-validation.fizz.today CNAME.

The fix

Key the for_each on the record name, not the domain name, and filter to just one:

resource "cloudflare_dns_record" "acm_validation" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options :
    dvo.resource_record_name => dvo
    if dvo.domain_name == var.domain  # dedup: wildcard shares apex CNAME
  }

  zone_id = var.cloudflare_zone_id
  name    = each.value.resource_record_name
  type    = "CNAME"
  content = each.value.resource_record_value
  proxied = false
}

The if dvo.domain_name == var.domain filter drops the wildcard entry. Since both produce the same CNAME, keeping just the apex entry is sufficient.

Why this is easy to miss

It works fine in the AWS console — you create one validation record and both domain names validate. The duplication only bites you in Terraform, where for_each needs unique keys and DNS providers reject duplicate records.

The AWS docs mention that wildcard and apex “may share” a validation record, but they don’t frame it as a Terraform footgun. If you’re writing ACM + DNS validation in Terraform for the first time, you’ll hit this.

#aws #acm #terraform #dns