-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
What happened:
When using DNSEndpoint CRDs with CNAME targets that have trailing dots (standard FQDN format), external-dns logs a warning and skips creating the DNS record:
level=warning msg="Endpoint config-control/my-dns-record with DNSName _acme-challenge_xxx.example.com. has an illegal target format."
The validation in source/crd.go lines 189-201 rejects non-NAPTR records with trailing dots:
illegalTarget := false
for _, target := range ep.Targets {
isNAPTR := ep.RecordType == endpoint.RecordTypeNAPTR
hasDot := strings.HasSuffix(target, ".")
if (isNAPTR && !hasDot) || (!isNAPTR && hasDot) {
illegalTarget = true
break
}
}What you expected to happen:
external-dns should accept CNAME records with trailing dots and create the DNS record. This is how other sources (Service, Ingress, etc.) behave - they automatically normalize trailing dots via NewEndpointWithTTL() in endpoint/endpoint.go:
func NewEndpointWithTTL(dnsName, recordType string, ttl TTL, targets ...string) *Endpoint {
cleanTargets := make([]string, len(targets))
for idx, target := range targets {
cleanTargets[idx] = strings.TrimSuffix(target, ".") // Normalizes
}
return &Endpoint{
DNSName: strings.TrimSuffix(dnsName, "."), // Normalizes
Targets: cleanTargets,
// ...
}
}CRD source is inconsistent - it uses endpoints directly from the spec (source/crd.go line 184) without normalization, then validates the raw data which still has trailing dots.
How to reproduce it (as minimally and precisely as possible):
- Deploy external-dns with CRD source:
args:
- --source=crd
- --crd-source-apiversion=externaldns.k8s.io/v1alpha1
- --crd-source-kind=DNSEndpoint
- --provider=cloudflare- Create a DNSEndpoint with FQDN target (trailing dot):
apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
name: my-dns-record
namespace: default
spec:
endpoints:
- dnsName: "subdomain.example.com."
recordTTL: 300
recordType: "CNAME"
targets:
- "target.example.com."-
Check external-dns logs - you'll see the "illegal target format" warning and no DNS record created.
-
Workaround: Manually strip trailing dots from both
dnsNameandtargets- then it works.
Anything else we need to know?:
Impact: This breaks automation workflows where external systems return FQDN data with trailing dots. For example:
- Google Certificate Manager DNS-01 ACME challenges return targets like
<token>.4.us-central1.authorize.certificatemanager.goog. - kpt apply-time-mutation copy this data to DNSEndpoint CRDs
- external-dns rejects it, breaking the automation
No configuration workaround exists:
- ❌ No command-line flags to skip/disable validation
- ❌ No annotations to control validation behavior
- ❌ No spec fields to bypass validation
- ❌ Validation is hardcoded in
source/crd.golines 189-201
History: The validation was added in July 2019 (commit 6bf1c2bc, v0.10.0) to prevent external-dns from "constantly adding and removing records." The assumption was that trailing dots were user errors, not valid FQDN formatting from external systems.
Related: NAPTR fix #3979 shows the maintainers already recognized this validation was too strict for NAPTR records. The same issue applies to CNAME records when FQDN data comes from external systems.
Environment:
- External-DNS version: v0.19.0 (issue present since v0.10.0)
- DNS provider: cloudflare
- Others: Kubernetes 1.29 (GKE), CRD source (DNSEndpoint v1alpha1)