Add DNSSEC signing, key backups and Porkbun support

Zones get a DNSSEC setting: named signs them with BIND's default (or a
custom) dnssec-policy and inline signing, with keys in a per-view key
directory. Jarl shows the keys, the DS record and when it is safe to
publish it, checks the parent's DS records (check-ds, which also tells
named), and refuses steps that would break a signed domain: switching
straight to unsigned, finishing a turn-off too early, deleting or moving
a signed zone, TTLs above max-zone-ttl. Turning off goes through the
insecure policy; wipe starts over once the parent has no DS.

Backups store the DNSSEC keys and restore puts them back for named; the
backup unit gets CAP_DAC_READ_SEARCH to read them. Jarl raises a zone's
serial above named's whenever it writes an older one (after a restore).
The serials check compares the signed serial.

With a Porkbun API key in jarl.yaml, the registrar's name servers, glue
records and DS records can be shown and changed, each change checked
first (dry run, force to override).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-08 21:19:04 +00:00
1 parent 293e6ddd33
commit 5630e7a848
72 files changed
+5760 -153

No files matched your search

+15
View File
@@ -118,13 +118,28 @@ type Zone struct {
SOA SOA `json:"soa"`
DefaultTTL uint32 `json:"default_ttl"`
SerialPolicy string `json:"serial_policy,omitempty"`
// DNSSECPolicy is the dnssec-policy named signs the zone with (primary
// zones only): "" for an unsigned zone, "default" (BIND's built-in
// policy), the name of a dnssec-policy statement, or "insecure" while
// signing is being removed safely (docs/dnssec.md).
DNSSECPolicy string `json:"dnssec_policy,omitempty"`
Comment string `json:"comment"`
Meta
}
// DNSSEC policies with a special meaning.
const (
DNSSECDefault = "default" // BIND's built-in policy
DNSSECInsecure = "insecure" // BIND's built-in policy for removing signing
)
// HasRecords reports whether Jarl manages the zone's records.
func (z *Zone) HasRecords() bool { return z.Type == ZonePrimary }
// Signed reports whether named signs the zone (or is still removing its
// signatures, under the insecure policy).
func (z *Zone) Signed() bool { return z.Type == ZonePrimary && z.DNSSECPolicy != "" }
// Record is a resource record in a primary zone.
type Record struct {
ID int64 `json:"id"`