Mismatch with AWS ACM certs validation record in Cloudflare DNS

Context #

While integrating Cloudflare DNS with AWS ACM certificates, I ran into a recurring problem when running terraform plan on subsequent changes after deploying the following code:

resource "aws_acm_certificate" "example" {
domain_name = "example.com"
validation_method = "DNS"

subject_alternative_names = [
"*.example.com",
"*.docs.example.com"
]

lifecycle {
create_before_destroy = true
}
}

resource "cloudflare_zone" "example" {
zone = "example.com"
type = "full"
}

resource "cloudflare_record" "certificate_validation" {
for_each = {
for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}

zone_id = cloudflare_zone.example.id
name = each.value.name
value = each.value.record
type = each.value.type
ttl = 1
proxied = false
}

Terraform complaint was as follows (with the output sanitized):

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
~ update in-place

Terraform will perform the following actions:

# cloudflare_record.certificate_validation["*.example.com"] will be updated in-place
~ resource "cloudflare_record" "certificate_validation" {
id = "09fasljhdfa087adfnkaldf97d8"
name = "_0123456789abcdedfghijklmn.example.com."
~ value = "_324fadahadkfh8327y49bjadf.kjhadfadfak.acm-validations.aws" -> "_324fadahadkfh8327y49bjadf.kjhadfadfak.acm-validations.aws."
# (10 unchanged attributes hidden)
}

# cloudflare_record.certificate_validation["*.docs.example.com"] will be updated in-place
~ resource "cloudflare_record" "certificate_validation" {
id = "089724952khadja9a6adank"
name = "_701849akdhfaakd97465Ss452.docs.example.com."
~ value = "_98472hjkadha98746kaldhf.bbhjkaddfafd.acm-validations.aws" -> "_98472hjkadha98746kaldhf.bbhjkaddfafd.acm-validations.aws."
# (10 unchanged attributes hidden)
}

Plan: 0 to add, 2 to change, 0 to destroy.

Notice how Terraform wants to add a trailing dot to the value of the validation record (a CNAME record in Cloudflare)

Solution #

The solution is to explicitly remove the trailing dot for each validation record before Terraform compares them against what is stored in Cloudflare. With can achieve this with the help of the trimsuffix function as shown below:

resource "cloudflare_record" "certificate_validation" {
for_each = {
for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}

zone_id = cloudflare_zone.example.id
name = each.value.name
value = trimsuffix(each.value.record, ".")
type = each.value.type
ttl = 1
proxied = false
}

References #

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer’s view in any way.