When working with DNS configurations, there's a fundamental limitation defined in RFC 1034 section 3.6.2: "If a CNAME RR is present at a node, no other data should be present." This means you cannot have both a CNAME and any other record type (including CAA) for the same hostname.
For domains where you need both a CNAME alias and CAA records, consider these approaches:
; Option 1: Move CAA to the canonical name
example.com. IN CAA 0 issue "letsencrypt.org"
www.example.com. IN CNAME canonical.example.net.
; Option 2: Use multiple records at domain root
example.com. IN CAA 0 issue "comodoca.com"
example.com. IN CAA 0 issuewild "comodoca.com"
*.example.com. IN CAA 0 issuewild "comodoca.com"
Here's how you might implement this for a web service with a CDN:
; Zone file snippet
@ IN CAA 0 issue "digicert.com"
@ IN CAA 0 issuewild "digicert.com"
app IN CNAME myapp.azurewebsites.net.
api IN CNAME myapi.cloudapp.azure.com.
; For subdomains that need specific CAs
staging IN CAA 0 issue "sectigo.com"
staging IN CNAME staging-app.azurewebsites.net.
Major DNS providers handle this differently:
- AWS Route 53: Allows CAA at zone apex even with CNAME aliases
- Cloudflare: Supports CAA for CNAME-mapped domains through their proxy
- Google Cloud DNS: Strictly enforces RFC compliance
When implementing workarounds:
- Always maintain CAA records at the most specific domain level possible
- For wildcard certificates, ensure issuewild records exist
- Test CAA validation using tools like
dig +short caa example.com
Many DNS providers enforce a restriction where you cannot create a CAA (Certification Authority Authorization) record for a hostname that already has a CNAME record. This stems from RFC 1034's rule that a CNAME record must be the only record at its domain name (with some DNSSEC-related exceptions). While this behavior is technically correct per the RFC, it creates practical challenges for administrators.
CAA records are crucial for security as they specify which certificate authorities (CAs) are allowed to issue certificates for your domain. Without them, any CA could potentially issue certificates for your domain. When you have services behind CNAME aliases (like many cloud services use), this becomes problematic.
Here are three approaches to solve this:
1. Use the Apex Domain for CAA
Create your CAA records at the apex domain level (e.g., example.com) instead of the subdomain with the CNAME:
example.com. IN CAA 0 issue "letsencrypt.org" www.example.com. IN CNAME mycdn.example.net
2. Use a Dedicated Subdomain
Create a separate subdomain just for CAA records that applies to your entire domain:
_caapolicy.example.com. IN CAA 0 issue "digicert.com"
3. DNS Provider-Specific Solutions
Some providers offer alternative solutions:
- Cloudflare: Allows CAA at CNAME records through their proxy
- Route 53: Supports CAA alongside CNAME via alias records
Here's how you might implement this in Terraform for AWS Route 53:
resource "aws_route53_record" "www_cname" { zone_id = aws_route53_zone.main.zone_id name = "www.example.com" type = "CNAME" ttl = 300 records = ["mycdn.example.net"] } resource "aws_route53_record" "caa_apex" { zone_id = aws_route53_zone.main.zone_id name = "example.com" type = "CAA" ttl = 300 records = [ "0 issue \"letsencrypt.org\"", "0 issuewild \"comodoca.com\"" ] }
Use dig to verify your CAA records:
dig example.com CAA +short dig _caapolicy.example.com CAA +short
Remember that CAA records are inherited by subdomains unless explicitly overridden. This means your apex domain CAA records will apply to all subdomains unless you specify different ones.
If you're using wildcard certificates, you'll want to include issuewild records:
example.com. IN CAA 0 issuewild "sectigo.com"