Any public certificate authority can issue a certificate for your domain to whoever passes its validation. A CAA record narrows that down: it lists the CAs you use, and every other CA must refuse. Since September 2017 all public CAs are required to check it before issuing.
It won't stop an attacker who controls your DNS, but it does stop a certificate being issued by a CA you've never used, through a weaker validation process or a mistake.
The record
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 issuewild ";"
example.com. CAA 0 iodef "mailto:[email protected]"
| Tag | Meaning |
|---|---|
issue |
this CA may issue certificates for the name |
issuewild |
rules for wildcard certificates only; overrides issue for them |
iodef |
where a CA may report a refused request |
";" as the value means "nobody". The example above allows Let's Encrypt for
normal certificates and no CA at all for wildcards. Add one issue line per
CA you use.
The value for each CA
| CA | Value |
|---|---|
| Let's Encrypt | letsencrypt.org |
| DigiCert | digicert.com |
| Sectigo | sectigo.com |
| Google Trust Services | pki.goog |
| Amazon (ACM) | amazon.com (also accepts amazontrust.com, awstrust.com, amazonaws.com) |
It applies to subdomains too
A CA checks the exact name first, then each parent: for shop.example.com it
looks at shop.example.com, then example.com. The first CAA records it
finds apply. So one set at example.com covers every subdomain, and a
subdomain served by another provider (a help desk, a shop platform) needs
either its CA added at the top or its own CAA records.
Before adding CAA, list every certificate already issued for your domain, so you don't lock out a service you forgot. The certificate finder lists them all from Certificate Transparency logs, with the CA that issued each one.
If you use Cloudflare
When Cloudflare's Universal SSL is on and your zone has any CAA record,
Cloudflare adds hidden CAA records for the CAs it uses (including Let's
Encrypt, Google Trust Services, SSL.com and Sectigo), so its edge
certificates keep renewing. They don't show in the dashboard; dig shows
them.
Tighter: lock it to your account
RFC 8657 adds two optional parameters that Let's Encrypt supports:
example.com. CAA 0 issue "letsencrypt.org; accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/123456"
example.com. CAA 0 issue "letsencrypt.org; validationmethods=dns-01"
accounturi allows only your ACME account; validationmethods allows only
the listed challenge types. Use them once your certificate setup is stable:
a new server with a new account will be refused.
Check your records
dig example.com CAA +short
No output means no CAA: any CA may issue. Found a certificate you can't explain? See certificate issued that I didn't request.