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:
1 parent
293e6ddd33
commit
5630e7a848
72 files changed
+5760
-153
No files matched your search
@@ -4,6 +4,8 @@ import { rerender } from "../app.js";
|
||||
import { optionsEditor } from "./options.js";
|
||||
import { emailOf, pendingBadge } from "./zones.js";
|
||||
import { isReverseZone, reverseInfo, ptrOwner, addressOf } from "../names.js";
|
||||
import { dnssecTab } from "./dnssec.js";
|
||||
import { registrarTab } from "./registrar.js";
|
||||
|
||||
export async function render(el, params, query) {
|
||||
const id = params.id;
|
||||
@@ -15,6 +17,8 @@ export async function render(el, params, query) {
|
||||
["options", "Options"],
|
||||
zone.type === "primary" ? ["file", "Zone file"] : null,
|
||||
["primary", "secondary", "mirror"].includes(zone.type) ? ["servers", "Name servers"] : null,
|
||||
zone.type === "primary" ? ["dnssec", "DNSSEC"] : null,
|
||||
zone.registrar && state.me && state.me.admin ? ["registrar", "Registrar"] : null,
|
||||
].filter(Boolean);
|
||||
const body = h("div");
|
||||
mount(el,
|
||||
@@ -26,6 +30,7 @@ export async function render(el, params, query) {
|
||||
zone.pending ? [pendingBadge(zone.pending), " "] : null,
|
||||
zone.view ? ["view ", h("a", { href: "#/views" }, zone.view), " · "] : null,
|
||||
zone.type === "primary" ? "serial " + zone.soa.serial + " · " : null,
|
||||
zone.dnssec_policy ? [h("a", { href: "#/zones/" + id + "/dnssec" }, badge(zone.dnssec_policy === "insecure" ? "DNSSEC: turning off" : "DNSSEC", zone.dnssec_policy === "insecure" ? "warn" : "ok")), " "] : null,
|
||||
zone.zone_file ? h("span", { class: "mono small" }, zone.zone_file) : null)),
|
||||
h("div", { class: "actions" },
|
||||
h("button", { class: "danger", onclick: () => deleteZone(zone) }, "Delete zone"))),
|
||||
@@ -36,6 +41,8 @@ export async function render(el, params, query) {
|
||||
else if (tab === "options") await optionsEditor(body, { scope: "zone", scope_id: zone.id, catalogScope: "zone:" + zone.type, title: "Zone options" });
|
||||
else if (tab === "file") await fileTab(body, zone);
|
||||
else if (tab === "servers") await serversTab(body, zone);
|
||||
else if (tab === "dnssec") await dnssecTab(body, zone);
|
||||
else if (tab === "registrar") await registrarTab(body, zone);
|
||||
}
|
||||
|
||||
// ---- name servers: serials on the other servers, and the delegation
|
||||
|
||||
Reference in new issue
Block a user