Add a CAA typed record builder for RFC 8659.

CheckDNS needs this so domain files with CAA records can be reconciled instead of failing the zone check.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Konrad Neitzel
2026-09-05 14:56:08 +02:00
co-authored by Cursor
parent 959a0ca9f9
commit 4f1a35dedb
3 changed files with 26 additions and 1 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ go get gitea.neitzel.de/konrad/go-dns
- **AXFR** — full zone read over TCP - **AXFR** — full zone read over TCP
- **RFC 2136 UPDATE** — typed add/delete changes (UDP with TCP fallback) - **RFC 2136 UPDATE** — typed add/delete changes (UDP with TCP fallback)
- **TSIG** — caller-supplied key name, algorithm, and base64 secret - **TSIG** — caller-supplied key name, algorithm, and base64 secret
- **Typed RR builders** — A, AAAA, MX, TXT, CNAME, NS, SRV, PTR (ASCII names) - **Typed RR builders** — A, AAAA, MX, TXT, CNAME, NS, SRV, PTR, CAA (ASCII names)
- **Zone / RRSet / Record** — in-memory zone model from AXFR - **Zone / RRSet / Record** — in-memory zone model from AXFR
**Excluded** **Excluded**
+10
View File
@@ -124,6 +124,16 @@ func PTR(owner string, ttl uint32, target string) (Record, error) {
return fromRR(&dns.PTR{Hdr: rrHeader(owner, dns.TypePTR, ttl), Ptr: name}) return fromRR(&dns.PTR{Hdr: rrHeader(owner, dns.TypePTR, ttl), Ptr: name})
} }
// CAA builds a certification-authority authorization record (RFC 8659).
func CAA(owner string, ttl uint32, flag uint8, tag, value string) (Record, error) {
return fromRR(&dns.CAA{
Hdr: rrHeader(owner, dns.TypeCAA, ttl),
Flag: flag,
Tag: tag,
Value: value,
})
}
// rrHeader builds an INET header. Owner ASCII is checked in fromRR. // rrHeader builds an INET header. Owner ASCII is checked in fromRR.
func rrHeader(owner string, typ uint16, ttl uint32) dns.RR_Header { func rrHeader(owner string, typ uint16, ttl uint32) dns.RR_Header {
name, err := fqdnASCII(owner) name, err := fqdnASCII(owner)
+15
View File
@@ -137,6 +137,21 @@ func TestPTRBuilder(t *testing.T) {
} }
} }
func TestCAABuilder(t *testing.T) {
t.Parallel()
rec, err := godns.CAA("example.test", 3600, 0, "issue", "letsencrypt.org")
if err != nil {
t.Fatal(err)
}
if rec.Type != "CAA" {
t.Fatalf("type: %q", rec.Type)
}
if rec.RData != `0 issue "letsencrypt.org"` {
t.Fatalf("rdata: %q", rec.RData)
}
}
func TestBuilderRejectsNonASCIIOwner(t *testing.T) { func TestBuilderRejectsNonASCIIOwner(t *testing.T) {
t.Parallel() t.Parallel()