DNSSEC: say where the DS record really goes

The DNSSEC tab said "give this to your registrar" for every zone whose
parent wasn't in Jarl in the same view. The DNSSEC response now has
ds_at/ds_place/ds_note: the parent zone in Jarl (any view, its own
first, then a public one), the registrar for a registered domain, the
parent zone wherever it is hosted for a subdomain, the ISP or RIR for a
reverse zone, and nowhere for a private name. The page and the CLI use
them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adamandClaude Opus 5.5 committed 2026-10-18 15:40:58 +01:00
1 parent 82c282cd32
commit a36c54ce60
8 files changed
+161 -26

No files matched your search

+12 -5
View File
@@ -44,7 +44,8 @@ export async function dnssecTab(el, zone) {
s.named_error ? h("div", { class: "msg warn small" }, "named: " + s.named_error) : null,
s.key_error ? h("div", { class: "msg err small" }, "The keys can't be read: " + s.key_error) : null,
!s.policy && !s.keys.length ? h("p", { class: "muted small" },
"Signing lets resolvers that validate DNSSEC detect forged answers for the zone. It only matters for a zone on the internet: validation needs a DS record in the parent zone (at your registrar), and resolvers on your own network don't validate zones this server answers itself.") : null,
"Signing lets resolvers that validate DNSSEC detect forged answers for the zone. It only matters for a zone on the internet: validation needs a DS record " + (s.ds_place || "in the parent zone") + ", and resolvers on your own network don't validate zones this server answers itself.") : null,
s.ds_at === "none" ? h("div", { class: "msg warn small" }, s.ds_note) : null,
out)];
const live = s.keys.filter((k) => k.ds && k.goal === "omnipresent");
@@ -98,8 +99,12 @@ async function addToParent(zone, s, k) {
function dsPanel(zone, s, keys) {
const ph = s.phase;
const where = s.parent_zone
? ["The parent zone ", h("a", { href: "#/zones/" + s.parent_zone_id + "/records" }, display(s.parent_zone)), " is in Jarl: add this as a DS record there (name ", h("code", null, parentName(zone, s)), "), with the button or the jarl command below."]
: "Give this to your registrar (at Porkbun: the domain's DNSSEC settings). Registrars ask either for the whole record or for its four fields.";
? ["The parent zone ", h("a", { href: "#/zones/" + s.parent_zone_id + "/records" }, display(s.parent_zone)),
s.parent_view && s.parent_view !== zone.view ? " (view " + s.parent_view + ")" : "",
" is in Jarl: add this as a DS record there (name ", h("code", null, parentName(zone, s)), "), with the button or the jarl command below."]
: s.ds_at === "registrar"
? "Give this to your registrar (at Porkbun: the domain's DNSSEC settings). Registrars ask either for the whole record or for its four fields."
: s.ds_at === "none" ? s.ds_note : "Add this " + s.ds_place + ".";
return h("div", { class: "panel" },
h("h2", null, "DS record for the parent zone"),
ph.can_publish_ds
@@ -153,7 +158,7 @@ async function enableDialog(zone, s, others) {
"The server's clock must be right (NTP): signatures are valid for a fixed time window.",
"TTLs in the zone must be at most a day; Jarl refuses longer ones.",
"Secondaries get the signed zone by zone transfer; they need nothing else.",
"With the default policy the key is never replaced, so the DS at your registrar never has to change. Keep backups: the daily backup includes the keys.",
"With the default policy the key is never replaced, so the DS record at the parent never has to change. Keep backups: the daily backup includes the keys.",
]),
split,
s.policies.length > 1 ? h("div", { class: "form-grid" }, h("label", null, "Policy"), pol) : null,
@@ -175,7 +180,9 @@ async function disableDialog(zone, s) {
[h("strong", null, "Now: "), "the zone switches to BIND's insecure policy. named keeps it signed and publishes a CDS \"delete\" record. Nothing breaks."],
s.parent_zone
? [h("strong", null, "You: "), "remove the DS record from ", display(s.parent_zone), " (", h("code", null, jarlCmd(zone, s, "delete", "")), ", or on its Records page), then click Check DS at parent so named knows it's gone."]
: [h("strong", null, "You: "), "remove the DS record at your registrar (", s.registrar ? "the Registrar tab can do that at Porkbun" : "at Porkbun: the domain's DNSSEC settings", "), then click Check DS at parent so named knows it's gone."],
: s.ds_at === "registrar"
? [h("strong", null, "You: "), "remove the DS record at your registrar (", s.registrar ? "the Registrar tab can do that at Porkbun" : "at Porkbun: the domain's DNSSEC settings", "), then click Check DS at parent so named knows it's gone."]
: [h("strong", null, "You: "), "remove the DS record ", s.ds_place || "from the parent zone", " (if it was ever added), then click Check DS at parent so named knows it's gone."],
[h("strong", null, "named: "), "waits until resolvers have forgotten the DS (the parent's DS TTL, often a day), then removes the keys and signatures."],
[h("strong", null, "Then: "), "this page lets you finish, which switches DNSSEC off."],
]),