Test sending NOTIFY(CDS) messages

When starting up the services, send notifies for the existing CDS RRset.
This requires setting up a chain of trust for the test, so the DSYNC
records can be retrieved and validated.

This feature requires enabling 'notify-cds' and 'dnssec-validation'.

In this test, the scanner is pointed to ns2. Since there is no code
for receiving NOTIFY(CDS) messages for delegations, this is treated
as "not authoritative". Checking for this log message ensures us that
the NOTIFY(CDS) message was actually sent.
This commit is contained in:
Matthijs Mekking 2025-11-25 08:56:32 +01:00
parent c8253a0a7a
commit e344fe18bc
14 changed files with 359 additions and 25 deletions

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
// NS1
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
};
zone "." {
type primary;
file "root.db.signed";
};
include "trusted.conf";

View file

@ -0,0 +1,27 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
. IN SOA gson.nominum.com. a.root.servers.nil. (
2000042100 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
multisigner. NS ns2.multisigner.
ns2.multisigner. A 10.53.0.2
secondary. NS ns2.secondary.
ns2.secondary. A 10.53.0.2

View file

@ -0,0 +1,41 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
set -e
zone=.
infile=root.db.in
zonefile=root.db
echo_i "ns1/setup.sh"
for tld in multisigner secondary; do
cp "../ns2/dsset-${tld}." .
done
KSK=$($KEYGEN -q -fk -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone)
cat $infile $KSK.key $ZSK.key >$zonefile
$SIGNER -g -o $zone $zonefile >/dev/null 2>&1
# Configure the resolving server with a static key.
keyfile_to_static_ds "$KSK" >trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf
cp trusted.conf ../ns5/trusted.conf

View file

@ -0,0 +1,34 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
$ORIGIN multisigner.
multisigner. IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
scanner A 10.53.0.2
model2 NS ns3
NS ns4
ns3.model2 A 10.53.0.3
ns4.model2 A 10.53.0.4
*._dsync DSYNC CDS NOTIFY @PORT@ scanner

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
// NS2
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
allow-transfer { any; };
allow-notify { 10.53.0.3; 10.53.0.4; };
dnssec-validation no;
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "multisigner" {
type primary;
file "multisigner.db.signed";
};
zone "secondary" {
type primary;
file "secondary.db.signed";
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -0,0 +1,36 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 300
$ORIGIN secondary.
secondary. IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
scanner A 10.53.0.2
model2 NS ns3
NS ns4
ns3.model2 A 10.53.0.3
ns4.model2 A 10.53.0.4
model2._dsync DSYNC CSYNC NOTIFY @PORT@ scanner ; ignored, unknown rrtype
model2._dsync DSYNC DSYNC NOTIFY @PORT@ scanner ; ignored, bad rrtype
model2._dsync DSYNC CDS NOTIFY @PORT@ scanner

View file

@ -0,0 +1,38 @@
#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# shellcheck source=conf.sh
. ../../conf.sh
echo_i "ns2/setup.sh"
setup() {
zone="$1"
echo_i "setting up zone: $zone"
infile="${zone}.db.in"
zonefile="${zone}.db"
cp ../ns3/dsset-ns3-model2.$zone. .
cp ../ns4/dsset-ns4-model2.$zone. .
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 -f KSK $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zone)
$DSFROMKEY $KSK.key >dsset-ns2-${zone}.
cat $infile $KSK.key $ZSK.key >$zonefile
$SIGNER -g -o $zone $zonefile
# >/dev/null 2>&1
}
setup "multisigner"
setup "secondary"

View file

@ -24,9 +24,9 @@ options {
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
dnssec-validation yes;
notify-cds yes;
};
key rndc_key {
@ -52,4 +52,12 @@ zone "model2.secondary." {
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
notify no;
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -23,20 +23,20 @@ zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns3-${zone}.
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns3-${zone}.
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"

View file

@ -24,9 +24,9 @@ options {
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
dnssec-validation yes;
notify-cds yes;
};
key rndc_key {
@ -52,4 +52,12 @@ zone "model2.secondary." {
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
notify no;
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -23,20 +23,20 @@ zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns4-${zone}.
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns4-${zone}.
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"

View file

@ -24,7 +24,6 @@ options {
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
notify-delay 0;
@ -44,3 +43,10 @@ zone "model2.secondary." {
allow-update { any; };
file "model2.secondary.db";
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -16,6 +16,7 @@
set -e
# multi-signers
(
cd ns3
$SHELL setup.sh
@ -28,3 +29,13 @@ set -e
cd ns5
$SHELL setup.sh
)
# tld
(
cd ns2
$SHELL setup.sh
)
# root
(
cd ns1
$SHELL setup.sh
)

View file

@ -33,16 +33,20 @@ pytestmark = pytest.mark.extra_artifacts(
"secondary.cds.ns*",
"unused.*",
"verify.out.*",
"ns*/K*",
"ns*/db-*",
"ns*/keygen.out.*",
"ns*/*.db",
"ns*/*.db.in",
"ns*/*.jbk",
"ns*/*.jnl",
"ns*/*.zsk",
"ns*/*.signed",
"ns*/*.journal.out.*",
"ns*/*.signed",
"ns*/*.zsk",
"ns*/db-*",
"ns*/dsset-*",
"ns*/K*",
"ns*/keygen.out.*",
"ns*/managed-keys.bind*",
"ns*/settime.out.*",
"ns*/model2.secondary.db",
"ns*/trusted.conf",
]
)
@ -503,7 +507,7 @@ def check_remove_cds(
check_dnssec(server, zone, keys, expected)
def test_multisigner(ns3, ns4):
def test_multisigner(ns2, ns3, ns4):
zone = "model2.multisigner"
keyprops = [
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
@ -515,6 +519,23 @@ def test_multisigner(ns3, ns4):
isctest.kasp.wait_keymgr_done(ns3, zone)
isctest.kasp.wait_keymgr_done(ns4, zone)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN: dsyncfetch: send NOTIFY(CDS) query to scanner.multisigner"
)
with ns4.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.multisigner"
)
with ns2.watch_log_from_start() as watcher:
# Receiving NOTIFY(CDS) has not been implemented yet. Until
# then, notifies for child zones towards the parent result in
# not authoritative (unless child and parent are served by the
# same name server).
watcher.wait_for_line(f"received notify for zone '{zone}': NOTAUTH")
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
ksks3 = [k for k in keys3 if k.is_ksk()]
zsks3 = [k for k in keys3 if not k.is_ksk()]
@ -574,7 +595,7 @@ def test_multisigner(ns3, ns4):
check_no_dnssec_in_journal(ns4, zone)
def test_multisigner_secondary(ns3, ns4, ns5):
def test_multisigner_secondary(ns2, ns3, ns4, ns5):
zone = "model2.secondary"
keyprops = [
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
@ -586,6 +607,24 @@ def test_multisigner_secondary(ns3, ns4, ns5):
isctest.kasp.wait_keymgr_done(ns3, zone)
isctest.kasp.wait_keymgr_done(ns4, zone)
for server in [ns3, ns4]:
with server.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.secondary"
)
msg = f"zone {zone}/IN (signed): dsyncfetch: DSYNC RRtype CSYNC not supported, ignoring"
assert msg in server.log
msg = f"zone {zone}/IN (signed): dsyncfetch: DSYNC RRtype DSYNC not supported, ignoring"
assert msg in server.log
with ns2.watch_log_from_start() as watcher:
# Receiving NOTIFY(CDS) has not been implemented yet. Until
# then, notifies for child zones towards the parent result in
# not authoritative (unless child and parent are served by the
# same name server).
watcher.wait_for_line(f"received notify for zone '{zone}': NOTAUTH")
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
ksks3 = [k for k in keys3 if k.is_ksk()]
zsks3 = [k for k in keys3 if not k.is_ksk()]