From 149ca5d46a96fbe289ba4b7c0e80e9dc6e9c39e9 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 31 Jul 2025 14:25:22 +0200 Subject: [PATCH 1/6] Rollover test case for rumoured zone signatures Test a manual rollover when zone signatures have not become omnipresent yet. This should not immediately remove the predecessor key. --- bin/tests/system/rollover/ns3/named.conf.j2 | 7 +- bin/tests/system/rollover/setup.sh | 14 +++ .../system/rollover/tests_rollover_manual.py | 105 ++++++++++++++---- 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/bin/tests/system/rollover/ns3/named.conf.j2 b/bin/tests/system/rollover/ns3/named.conf.j2 index f44a96afd0..c7e4397845 100644 --- a/bin/tests/system/rollover/ns3/named.conf.j2 +++ b/bin/tests/system/rollover/ns3/named.conf.j2 @@ -14,8 +14,11 @@ include "kasp.conf"; include "named.common.conf"; -zone "manual-rollover.kasp" { +{% for zone in ['manual-rollover.kasp', 'manual-rollover-zrrsig-rumoured.kasp'] %} +zone "@zone@" { type primary; - file "manual-rollover.kasp.db"; + file "@zone@.db"; dnssec-policy "manual-rollover"; }; + +{% endfor %} diff --git a/bin/tests/system/rollover/setup.sh b/bin/tests/system/rollover/setup.sh index 20cd7d5a49..f465ddf46a 100644 --- a/bin/tests/system/rollover/setup.sh +++ b/bin/tests/system/rollover/setup.sh @@ -43,3 +43,17 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" cp $infile $zonefile $SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Zone to test manual rollover. +setup manual-rollover-zrrsig-rumoured.kasp +T2="now-2h" +zsktimes="-P $T2 -A $T2" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T2 -z $R $T2 "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/rollover/tests_rollover_manual.py b/bin/tests/system/rollover/tests_rollover_manual.py index 2103fcd7e5..0fa5edc58f 100644 --- a/bin/tests/system/rollover/tests_rollover_manual.py +++ b/bin/tests/system/rollover/tests_rollover_manual.py @@ -17,21 +17,23 @@ from isctest.kasp import KeyTimingMetadata, Ipub, Iret from rollover.common import pytestmark # pylint: disable=unused-import +CONFIG = { + "dnskey-ttl": timedelta(hours=1), + "ds-ttl": timedelta(days=1), + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=7), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), +} + +POLICY = "manual-rollover" + def test_rollover_manual(ns3): - policy = "manual-rollover" - config = { - "dnskey-ttl": timedelta(hours=1), - "ds-ttl": timedelta(days=1), - "max-zone-ttl": timedelta(days=1), - "parent-propagation-delay": timedelta(hours=1), - "publish-safety": timedelta(hours=1), - "retire-safety": timedelta(hours=1), - "signatures-refresh": timedelta(days=7), - "signatures-validity": timedelta(days=14), - "zone-propagation-delay": timedelta(minutes=5), - } - ttl = int(config["dnskey-ttl"].total_seconds()) + ttl = int(CONFIG["dnskey-ttl"].total_seconds()) alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] size = os.environ["DEFAULT_BITS"] zone = "manual-rollover.kasp" @@ -53,10 +55,10 @@ def test_rollover_manual(ns3): offset = -timedelta(days=7) for kp in expected: - kp.set_expected_keytimes(config, offset=offset) + kp.set_expected_keytimes(CONFIG, offset=offset) isctest.kasp.check_keytimes(keys, expected) - isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=policy) + isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=POLICY) isctest.kasp.check_apex(ns3, zone, ksks, zsks) isctest.kasp.check_subdomain(ns3, zone, ksks, zsks) @@ -64,9 +66,9 @@ def test_rollover_manual(ns3): assert len(ksks) == 1 ksk = ksks[0] startroll = expected[0].timing["Active"] + timedelta(days=30 * 6) - expected[0].timing["Retired"] = startroll + Ipub(config) + expected[0].timing["Retired"] = startroll + Ipub(CONFIG) expected[0].timing["Removed"] = expected[0].timing["Retired"] + Iret( - config, zsk=False, ksk=True + CONFIG, zsk=False, ksk=True ) with ns3.watch_log_from_here() as watcher: @@ -76,7 +78,7 @@ def test_rollover_manual(ns3): isctest.kasp.check_dnssec_verify(ns3, zone) isctest.kasp.check_keys(zone, keys, expected) isctest.kasp.check_keytimes(keys, expected) - isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=policy) + isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=POLICY) isctest.kasp.check_apex(ns3, zone, ksks, zsks) isctest.kasp.check_subdomain(ns3, zone, ksks, zsks) @@ -108,15 +110,15 @@ def test_rollover_manual(ns3): off = offset if "Predecessor" in kp.metadata: off = 0 - kp.set_expected_keytimes(config, offset=off) + kp.set_expected_keytimes(CONFIG, offset=off) - expected[0].timing["Retired"] = now + Ipub(config) + expected[0].timing["Retired"] = now + Ipub(CONFIG) expected[0].timing["Removed"] = expected[0].timing["Retired"] + Iret( - config, zsk=False, ksk=True + CONFIG, zsk=False, ksk=True ) isctest.kasp.check_keytimes(keys, expected) - isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=policy) + isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=POLICY) isctest.kasp.check_apex(ns3, zone, ksks, zsks) isctest.kasp.check_subdomain(ns3, zone, ksks, zsks) @@ -153,3 +155,62 @@ def test_rollover_manual(ns3): zsk = expected[3].key response = ns3.rndc(f"dnssec -rollover -key {zsk.tag} {zone}") assert "key is not actively signing" in response + + +def test_rollover_manual_zrrsig_rumoured(ns3): + ttl = int(CONFIG["dnskey-ttl"].total_seconds()) + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + zone = "manual-rollover-zrrsig-rumoured.kasp" + + isctest.kasp.wait_keymgr_done(ns3, zone) + + isctest.kasp.check_dnssec_verify(ns3, zone) + + koffset = -int(timedelta(days=7).total_seconds()) + zoffset = -int(timedelta(hours=2).total_seconds()) + key_properties = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", + ] + expected = isctest.kasp.policy_to_properties(ttl, key_properties) + keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + + isctest.kasp.check_keys(zone, keys, expected) + + for kp in expected: + kp.set_expected_keytimes(CONFIG) + + isctest.kasp.check_keytimes(keys, expected) + isctest.kasp.check_dnssecstatus(ns3, zone, keys, policy=POLICY) + isctest.kasp.check_apex(ns3, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns3, zone, ksks, zsks) + + # Schedule ZSK rollover now. + assert len(zsks) == 1 + zsk = zsks[0] + now = KeyTimingMetadata.now() + with ns3.watch_log_from_here() as watcher: + ns3.rndc(f"dnssec -rollover -key {zsk.tag} -when {now} {zone}") + watcher.wait_for_line(f"keymgr: {zone} done") + + isctest.kasp.check_dnssec_verify(ns3, zone) + + key_properties = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{koffset}", + # Predecessor DNSKEY must stay until successor ZSK is fully omnipresent. + f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:rumoured offset:{zoffset}", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:0", + ] + expected = isctest.kasp.policy_to_properties(ttl, key_properties) + keys = isctest.kasp.keydir_to_keylist(zone, ns3.identifier) + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + + isctest.kasp.check_keys(zone, keys, expected) + + expected[1].metadata["Successor"] = expected[2].key.tag + expected[2].metadata["Predecessor"] = expected[1].key.tag + isctest.kasp.check_keyrelationships(keys, expected) From b19871f8a23f83ed004d86690cb8de39794e0931 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 31 Jul 2025 14:30:20 +0200 Subject: [PATCH 2/6] Make keymgr state machine more robust If the keymgr state machine is in an invalid state, it tries to move it self to a valid state. But when you do key rollovers during an invalid state, and the next state is also an invalid state, the keymgr will happily do the transition. It would be good to not do key rollovers if there is not a KSK and ZSK fully omnipresent. But also it would be good to safeguard against unexpected transitions. This commit does that by not moving things to unretentive (which is the state where we would remove the corresponding record from the zone) if the state machine is currently in an invalid state. --- lib/dns/keymgr.c | 72 ++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/lib/dns/keymgr.c b/lib/dns/keymgr.c index f38936aef8..704acca5ec 100644 --- a/lib/dns/keymgr.c +++ b/lib/dns/keymgr.c @@ -1254,17 +1254,18 @@ keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, static bool keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type, dst_key_state_t next_state, uint8_t opts) { + bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b; + rule1a = keymgr_have_ds(keyring, key, type, NA, opts); + rule1b = keymgr_have_ds(keyring, key, type, next_state, opts); + rule2a = keymgr_have_dnskey(keyring, key, type, NA); + rule2b = keymgr_have_dnskey(keyring, key, type, next_state); + rule3a = keymgr_have_rrsig(keyring, key, type, NA); + rule3b = keymgr_have_rrsig(keyring, key, type, next_state); + /* Debug logging. */ if (isc_log_wouldlog(ISC_LOG_DEBUG(1))) { - bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b; char keystr[DST_KEY_FORMATSIZE]; dst_key_format(key->key, keystr, sizeof(keystr)); - rule1a = keymgr_have_ds(keyring, key, type, NA, opts); - rule1b = keymgr_have_ds(keyring, key, type, next_state, opts); - rule2a = keymgr_have_dnskey(keyring, key, type, NA); - rule2b = keymgr_have_dnskey(keyring, key, type, next_state); - rule3a = keymgr_have_rrsig(keyring, key, type, NA); - rule3b = keymgr_have_rrsig(keyring, key, type, next_state); isc_log_write( DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), @@ -1277,29 +1278,40 @@ keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, rule3a ? "true" : "false", rule3b ? "true" : "false"); } - return - /* - * Rule 1: There must be a DS at all times. - * First check the current situation: if the rule check fails, - * we allow the transition to attempt to move us out of the - * invalid state. If the rule check passes, also check if - * the next state is also still a valid situation. - */ - (!keymgr_have_ds(keyring, key, type, NA, opts) || - keymgr_have_ds(keyring, key, type, next_state, opts)) && - /* - * Rule 2: There must be a DNSKEY at all times. Again, first - * check the current situation, then assess the next state. - */ - (!keymgr_have_dnskey(keyring, key, type, NA) || - keymgr_have_dnskey(keyring, key, type, next_state)) && - /* - * Rule 3: There must be RRSIG records at all times. Again, - * first check the current situation, then assess the next - * state. - */ - (!keymgr_have_rrsig(keyring, key, type, NA) || - keymgr_have_rrsig(keyring, key, type, next_state)); + /* + * Rule checking: + * First check the current situation: if the rule check fails, + * we allow the transition to attempt to move us out of the + * invalid state. If the rule check passes, also check if + * the next state is also still a valid situation. + */ + char keystr2[DST_KEY_FORMATSIZE]; + dst_key_format(key->key, keystr2, sizeof(keystr2)); + + /* + * Rule 1: There must be a DS at all times. + */ + if (!rule1a && !rule1b && next_state == UNRETENTIVE) { + return false; + } + /* + * Rule 2: There must be a DNSKEY at all times. Again, first + * check the current situation, then assess the next state. + */ + if (!rule2a && !rule2b && next_state == UNRETENTIVE) { + return false; + } + /* + * Rule 3: There must be RRSIG records at all times. Again, + * first check the current situation, then assess the next + * state. + */ + if (!rule3a && !rule3b && next_state == UNRETENTIVE) { + return false; + } + + return (!rule1a || rule1b) && (!rule2a || rule2b) && + (!rule3a || rule3b); } /* From 67ea0e656b9267075773a35d265fde809da0e092 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 31 Jul 2025 16:51:37 +0200 Subject: [PATCH 3/6] Fix views system test This test case enables DNSSEC and has a mismatch in policy. Fix the policy so that it matches the existing key set, and adjust the expected answer count because no longer a new key is generated. --- bin/tests/system/views/ns2/named1.conf.in | 2 +- bin/tests/system/views/ns2/named2.conf.in | 2 +- bin/tests/system/views/tests.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/tests/system/views/ns2/named1.conf.in b/bin/tests/system/views/ns2/named1.conf.in index 4fd3ee5501..72e4ab4ff1 100644 --- a/bin/tests/system/views/ns2/named1.conf.in +++ b/bin/tests/system/views/ns2/named1.conf.in @@ -37,7 +37,7 @@ controls { dnssec-policy "views" { keys { ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; - csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; }; }; diff --git a/bin/tests/system/views/ns2/named2.conf.in b/bin/tests/system/views/ns2/named2.conf.in index de312f10a5..c39aab1276 100644 --- a/bin/tests/system/views/ns2/named2.conf.in +++ b/bin/tests/system/views/ns2/named2.conf.in @@ -37,7 +37,7 @@ controls { dnssec-policy "views" { keys { ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; - csk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; }; }; diff --git a/bin/tests/system/views/tests.sh b/bin/tests/system/views/tests.sh index 4684f82249..d7a20aa12d 100644 --- a/bin/tests/system/views/tests.sh +++ b/bin/tests/system/views/tests.sh @@ -137,8 +137,8 @@ ret=0 wait_for_signed() { "$DIG" -p "${PORT}" @10.53.0.2 -b 10.53.0.2 +dnssec DNSKEY inline >dig.out.internal "$DIG" -p "${PORT}" @10.53.0.2 -b 10.53.0.5 +dnssec DNSKEY inline >dig.out.external - grep "ANSWER: 4," dig.out.internal >/dev/null || return 1 - grep "ANSWER: 4," dig.out.external >/dev/null || return 1 + grep "ANSWER: 3," dig.out.internal >/dev/null || return 1 + grep "ANSWER: 3," dig.out.external >/dev/null || return 1 return 0 } retry_quiet 10 wait_for_signed || ret=1 From c756b8a505ca1975e967f59477370287077c1f12 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 31 Jul 2025 17:41:11 +0200 Subject: [PATCH 4/6] Fix autosign system test When creating keys, set Publish and Activate times so that keys will be initialized as omnipresent. This way we start with a safe DNSSEC state. In most cases at least, because some tests depend on special key timings. The ttl[1-4].example cases have become incorrect. With dnssec-policy we require the TTL to match the dnskey-ttl from the policy. The delzsk.example will have a ZSK removed from the zone. It also requires that the DNSKEY RRset is already published. This means that for the existing keys the, no longer "is now published" messages will be logged. The nsec-only.example and reconf.example zones are fixed to have a correct matching policy. This all means the expected count of log messages changes slightly. --- bin/tests/system/autosign/ns3/keygen.sh | 141 +++++++++--------- bin/tests/system/autosign/ns3/named.conf.in | 10 +- .../system/autosign/ns3/nsec-only.conf.in | 27 ++++ bin/tests/system/autosign/setup.sh | 5 + bin/tests/system/autosign/tests.sh | 12 +- .../system/autosign/tests_sh_autosign.py | 1 + 6 files changed, 114 insertions(+), 82 deletions(-) create mode 100644 bin/tests/system/autosign/ns3/nsec-only.conf.in diff --git a/bin/tests/system/autosign/ns3/keygen.sh b/bin/tests/system/autosign/ns3/keygen.sh index 54f53a46c8..5834dc1e2f 100644 --- a/bin/tests/system/autosign/ns3/keygen.sh +++ b/bin/tests/system/autosign/ns3/keygen.sh @@ -31,10 +31,13 @@ setup() { mkdir inactive +T="now-7d" +keytimes="-P $T -A $T" + setup secure.example cp $infile $zonefile -ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -42,8 +45,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup secure.nsec3.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -51,8 +54,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup nsec3.nsec3.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -74,8 +77,8 @@ done # setup optout.nsec3.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -83,8 +86,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup nsec3.example cat $infile dsset-*.${zone}. >$zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -92,9 +95,9 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup autonsec3.example cat $infile >$zonefile -ksk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out echo $ksk >../autoksk.key -zsk=$($KEYGEN -G -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone 2>kg.out) || dumpit kg.out echo $zsk >../autozsk.key $DSFROMKEY $ksk.key >dsset-${zone}. @@ -103,8 +106,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup secure.optout.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -112,8 +115,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup nsec3.optout.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -121,8 +124,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup optout.optout.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -130,8 +133,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup optout.example cat $infile dsset-*.${zone}. >$zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -139,8 +142,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup rsasha256.example cp $infile $zonefile -ksk=$($KEYGEN -q -a RSASHA256 -b 2048 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a RSASHA256 -b 2048 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a RSASHA256 -b 2048 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a RSASHA256 -b 2048 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -148,8 +151,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup rsasha512.example cp $infile $zonefile -ksk=$($KEYGEN -q -a RSASHA512 -b 2048 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a RSASHA512 -b 2048 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a RSASHA512 -b 2048 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a RSASHA512 -b 2048 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -160,8 +163,8 @@ $DSFROMKEY $ksk.key >dsset-${zone}. if [ $RSASHA1_SUPPORTED = 1 ]; then setup nsec-only.example cp $infile $zonefile - ksk=$($KEYGEN -q -a RSASHA1 -fk $zone 2>kg.out) || dumpit kg.out - $KEYGEN -q -a RSASHA1 $zone >kg.out 2>&1 || dumpit kg.out + ksk=$($KEYGEN -q -a RSASHA1 -fk $keytimes $zone 2>kg.out) || dumpit kg.out + $KEYGEN -q -a RSASHA1 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. else echo_i "skip: nsec-only.example - signing with RSASHA1 not supported" @@ -178,8 +181,8 @@ while [ $count -le 1000 ]; do echo "label${count} IN TXT label${count}" >>$zonefile count=$((count + 1)) done -$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $keytimes $zone >kg.out 2>&1 || dumpit kg.out $SIGNER -PS -x -s now-1y -e now-6mo -o $zone -f $zonefile.signed $zonefile >s.out || dumpit s.out cp $zonefile.signed $zonefile.bak mv $zonefile.signed $zonefile @@ -188,16 +191,16 @@ mv $zonefile.signed $zonefile # NSEC3->NSEC transition test zone. # setup nsec3-to-nsec.example -$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $keytimes $zone >kg.out 2>&1 || dumpit kg.out $SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out # # NSEC3->NSEC3 transition test zone. # setup nsec3-to-nsec3.example -$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM $keytimes $zone >kg.out 2>&1 || dumpit kg.out $SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out # @@ -205,8 +208,8 @@ $SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out # setup prepub.example infile="prepub.example.db.in" -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone >kg.out 2>&1 || dumpit kg.out -zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone 2>kg.out) || dumpit kg.out echo $zsk >../prepub.key $SIGNER -S -3 beef -o $zone -f $zonefile $infile >s.out || dumpit s.out @@ -214,29 +217,29 @@ $SIGNER -S -3 beef -o $zone -f $zonefile $infile >s.out || dumpit s.out # Key TTL tests. # -# no default key TTL; DNSKEY should get SOA TTL +# no default key TTL; DNSKEY should get default dnskey-ttl setup ttl1.example -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone >kg.out 2>&1 || dumpit kg.out cp $infile $zonefile -# default key TTL should be used +# default dnskey-ttl should be used setup ttl2.example -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 60 $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 60 $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $keytimes $zone >kg.out 2>&1 || dumpit kg.out cp $infile $zonefile -# mismatched key TTLs, should use shortest +# mismatched key TTLs, should use default dnskey-ttl setup ttl3.example -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 30 $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -L 30 $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 60 $keytimes $zone >kg.out 2>&1 || dumpit kg.out cp $infile $zonefile -# existing DNSKEY RRset, should retain TTL +# existing DNSKEY RRset, should update to use dnksey-ttl setup ttl4.example -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 -fk $zone >kg.out 2>&1 || dumpit kg.out -cat ${infile} K${zone}.+*.key >$zonefile -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 180 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q -L 30 $keytimes $zone >kg.out 2>&1 || dumpit kg.out +cp $infile $zonefile # # A zone with a DNSKEY RRset that is published before it's activated @@ -253,8 +256,8 @@ cp delay.example.db.in delay.example.db # is missing. # setup noksk.example -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone 2>kg.out) || dumpit kg.out $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out echo $ksk >../noksk-ksk.key rm -f ${ksk}.private @@ -264,8 +267,8 @@ rm -f ${ksk}.private # is missing. # setup nozsk.example -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone 2>kg.out) || dumpit kg.out $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out echo $ksk >../nozsk-ksk.key echo $zsk >../nozsk-zsk.key @@ -276,8 +279,8 @@ rm -f ${zsk}.private # is inactive. # setup inaczsk.example -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone 2>kg.out) || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +zsk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone 2>kg.out) || dumpit kg.out $SIGNER -S -P -s now-1mo -e now-1mi -o $zone -f $zonefile ${zonefile}.in >s.out || dumpit s.out echo $ksk >../inaczsk-ksk.key echo $zsk >../inaczsk-zsk.key @@ -288,16 +291,16 @@ $SETTIME -I now $zsk >st.out 2>&1 || dumpit st.out # setup reconf.example cp secure.example.db.in $zonefile -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone >kg.out 2>&1 || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone >kg.out 2>&1 || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out # # A zone which generates CDS and CDNSEY RRsets automatically (with an additional CSK) # setup sync.example cp $infile $zonefile -ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2>kg.out) || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. echo ns3/$ksk >../sync.key @@ -306,8 +309,8 @@ echo ns3/$ksk >../sync.key # setup kskonly.example cp $infile $zonefile -ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $zone 2>kg.out) || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. # @@ -315,7 +318,7 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup inaczsk2.example cp $infile $zonefile -ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $keytimes $zone 2>kg.out) || dumpit kg.out $KEYGEN -a $DEFAULT_ALGORITHM -3 -q -P now -A now+3600 $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. @@ -325,19 +328,19 @@ $DSFROMKEY $ksk.key >dsset-${zone}. # setup delzsk.example cp $infile $zonefile -ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -a $DEFAULT_ALGORITHM -3 -q $zone >kg.out 2>&1 || dumpit kg.out -zsk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -I now-1w $zone 2>kg.out) || dumpit kg.out -cat $zsk.key >>$zonefile -mv $zsk.key inactive/ -mv $zsk.private inactive/ -echo $zsk >../delzsk.key +ksk=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q -fk -P sync now-7d $keytimes $zone 2>kg.out) || dumpit kg.out +zsk1=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes $zone >kg.out 2>&1) || dumpit kg.out +zsk2=$($KEYGEN -a $DEFAULT_ALGORITHM -3 -q $keytimes -I now-1d $zone 2>kg.out) || dumpit kg.out +cat $ksk.key $zsk2.key >>$zonefile +cp $zsk2.key inactive/ +cp $zsk2.private inactive/ +echo $zsk2 >../delzsk.key # # Check that NSEC3 are correctly signed and returned from below a DNAME # setup dname-at-apex-nsec3.example cp $infile $zonefile -ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $zone 2>kg.out) || dumpit kg.out -$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $zone >kg.out 2>&1 || dumpit kg.out +ksk=$($KEYGEN -q -a $DEFAULT_ALGORITHM -3 -fk $keytimes $zone 2>kg.out) || dumpit kg.out +$KEYGEN -q -a $DEFAULT_ALGORITHM -3 $keytimes $zone >kg.out 2>&1 || dumpit kg.out $DSFROMKEY $ksk.key >dsset-${zone}. diff --git a/bin/tests/system/autosign/ns3/named.conf.in b/bin/tests/system/autosign/ns3/named.conf.in index 3707a2c7c9..f6d061bb0a 100644 --- a/bin/tests/system/autosign/ns3/named.conf.in +++ b/bin/tests/system/autosign/ns3/named.conf.in @@ -250,14 +250,6 @@ zone "rsasha512.example" { dnssec-policy rsasha512; }; -zone "nsec-only.example" { - type primary; - file "nsec-only.example.db"; - allow-update { any; }; - inline-signing no; - dnssec-policy autosign; -}; - zone "nsec3-to-nsec.example" { type primary; file "nsec3-to-nsec.example.db"; @@ -394,4 +386,6 @@ zone "dname-at-apex-nsec3.example" { dnssec-policy nsec3; }; +include "nsec-only.conf"; + include "trusted.conf"; diff --git a/bin/tests/system/autosign/ns3/nsec-only.conf.in b/bin/tests/system/autosign/ns3/nsec-only.conf.in new file mode 100644 index 0000000000..37eb30d629 --- /dev/null +++ b/bin/tests/system/autosign/ns3/nsec-only.conf.in @@ -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. + */ + +dnssec-policy "nsec-only" { + keys { + ksk key-directory lifetime unlimited algorithm rsasha1; + zsk key-directory lifetime unlimited algorithm rsasha1; + }; +}; + +zone "nsec-only.example" { + type primary; + file "nsec-only.example.db"; + allow-update { any; }; + inline-signing no; + dnssec-policy nsec-only; +}; diff --git a/bin/tests/system/autosign/setup.sh b/bin/tests/system/autosign/setup.sh index e029fdf8aa..2c785ac245 100644 --- a/bin/tests/system/autosign/setup.sh +++ b/bin/tests/system/autosign/setup.sh @@ -15,6 +15,11 @@ copy_setports ns1/named.conf.in ns1/named.conf copy_setports ns2/named.conf.in ns2/named.conf +if [ $RSASHA1_SUPPORTED = 1 ]; then + cp ns3/nsec-only.conf.in ns3/nsec-only.conf +else + : >ns3/nsec-only.conf +fi copy_setports ns3/named.conf.in ns3/named.conf copy_setports ns4/named.conf.in ns4/named.conf copy_setports ns5/named.conf.in ns5/named.conf diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index 298de9196c..afc847b935 100755 --- a/bin/tests/system/autosign/tests.sh +++ b/bin/tests/system/autosign/tests.sh @@ -1087,7 +1087,7 @@ ret=0 rekey_calls=$(grep "zone reconf.example.*next key event" ns3/named.run | wc -l) [ "$rekey_calls" -eq 0 ] || ret=1 # ...then we add dnssec-policy and reconfigure -($RNDCCMD 10.53.0.3 modzone reconf.example '{ type primary; file "reconf.example.db"; allow-update { any; }; dnssec-policy default; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 +($RNDCCMD 10.53.0.3 modzone reconf.example '{ type primary; file "reconf.example.db"; allow-update { any; }; dnssec-policy autosign; };' 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1 rndc_reconfig ns3 10.53.0.3 for i in 0 1 2 3 4 5 6 7 8 9; do lret=0 @@ -1256,17 +1256,19 @@ act=$(grep "DNSKEY .* is now active" ns3/named.run | wc -l) if [ $RSASHA1_SUPPORTED = 1 ]; then # Include two log lines for nsec-only zone. [ "$pub" -eq 53 ] || ret=1 - [ "$act" -eq 53 ] || ret=1 + [ "$act" -eq 54 ] || ret=1 else [ "$pub" -eq 51 ] || ret=1 - [ "$act" -eq 51 ] || ret=1 + [ "$act" -eq 52 ] || ret=1 fi rev=$(grep "DNSKEY .* is now revoked" ns3/named.run | wc -l) [ "$rev" -eq 0 ] || ret=1 +# inaczsk.example inac=$(grep "DNSKEY .* is now inactive" ns3/named.run | wc -l) -[ "$inac" -eq 0 ] || ret=1 +[ "$inac" -eq 1 ] || ret=1 +# delzsk.example del=$(grep "DNSKEY .* is now deleted" ns3/named.run | wc -l) -[ "$del" -eq 3 ] || ret=1 +[ "$del" -eq 1 ] || ret=1 n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) diff --git a/bin/tests/system/autosign/tests_sh_autosign.py b/bin/tests/system/autosign/tests_sh_autosign.py index ef11cbe21a..5a4b2ed833 100644 --- a/bin/tests/system/autosign/tests_sh_autosign.py +++ b/bin/tests/system/autosign/tests_sh_autosign.py @@ -114,6 +114,7 @@ pytestmark = pytest.mark.extra_artifacts( "ns3/kskonly.example.db.jbk", "ns3/noksk.example.db", "ns3/nozsk.example.db", + "ns3/nsec-only.conf", "ns3/nsec-only.example.db", "ns3/nsec3-to-nsec.example.db", "ns3/nsec3-to-nsec3.example.db", From a8339be0f82019f6eecb9136ea928788bec0794b Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Mon, 4 Aug 2025 13:09:12 +0200 Subject: [PATCH 5/6] Fix nsec3 system test The nsec3 system test has a couple of cases where the configured policy changes the algorithm, effectively triggering an algorithm rollover. Fix those cases to start in a valid DNSSEC state. Then fix the expected key states, no longer should the old algorithm be removed immediately. --- .../system/nsec3/ns3/named-rsasha1.conf.j2 | 4 +-- bin/tests/system/nsec3/ns3/setup.sh | 27 +++++++++---------- bin/tests/system/nsec3/tests_nsec3_initial.py | 4 +-- .../system/nsec3/tests_nsec3_reconfig.py | 26 +++++++++--------- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/bin/tests/system/nsec3/ns3/named-rsasha1.conf.j2 b/bin/tests/system/nsec3/ns3/named-rsasha1.conf.j2 index 7c47ae2d54..e05d3410e2 100644 --- a/bin/tests/system/nsec3/ns3/named-rsasha1.conf.j2 +++ b/bin/tests/system/nsec3/ns3/named-rsasha1.conf.j2 @@ -25,7 +25,7 @@ dnssec-policy "rsasha1" { {% if "rsasha1-to-nsec3.kasp" in zones %} /* * This zone starts with NSEC, but will be reconfigured to use NSEC3. - * This should work despite the incompatible RSAHSHA1 algorithm, + * This should work despite the incompatible RSASHA1 algorithm, * because the DS is still in hidden state. */ zone "rsasha1-to-nsec3.kasp" { @@ -51,7 +51,7 @@ zone "rsasha1-to-nsec3-wait.kasp" { {% if "nsec3-to-rsasha1.kasp" in zones %} /* * This zone starts with NSEC3, but will be reconfigured to use NSEC with an - * NSEC only algorithm. This should work despite the incompatible RSAHSHA1 + * NSEC only algorithm. This should work despite the incompatible RSASHA1 * algorithm, because the DS is still in hidden state. */ zone "nsec3-to-rsasha1.kasp" { diff --git a/bin/tests/system/nsec3/ns3/setup.sh b/bin/tests/system/nsec3/ns3/setup.sh index 5b7053e08d..03b6b81b0d 100644 --- a/bin/tests/system/nsec3/ns3/setup.sh +++ b/bin/tests/system/nsec3/ns3/setup.sh @@ -31,24 +31,23 @@ for zn in nsec-to-nsec3 nsec3 nsec3-other nsec3-change nsec3-to-nsec \ done if [ $RSASHA1_SUPPORTED = 1 ]; then - for zn in rsasha1-to-nsec3 rsasha1-to-nsec3-wait nsec3-to-rsasha1 \ - nsec3-to-rsasha1-ds; do - setup "${zn}.kasp" - done - longago="now-1y" - keytimes="-P ${longago} -A ${longago}" + keytimes="-P ${longago} -A ${longago} -P sync ${longago}" O="omnipresent" - zone="rsasha1-to-nsec3-wait.kasp" - CSK=$($KEYGEN -k "rsasha1" -l named.conf $keytimes $zone 2>keygen.out.$zone) - echo_i "Created key file $CSK" - $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 + for zn in nsec3-to-rsasha1 nsec3-to-rsasha1-ds; do + setup "${zn}.kasp" + CSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone) + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 + cat $CSK.key >>$zonefile + done - zone="nsec3-to-rsasha1-ds.kasp" - CSK=$($KEYGEN -k "default" -l named.conf $keytimes $zone 2>keygen.out.$zone) - echo_i "Created key file $CSK" - $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 + for zn in rsasha1-to-nsec3 rsasha1-to-nsec3-wait; do + setup "${zn}.kasp" + CSK=$($KEYGEN -k "rsasha1" -l named.conf $keytimes $zone 2>keygen.out.$zone) + $SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1 + cat $CSK.key >>$zonefile + done else echo_i "skip: skip rsasha1 zones - signing with RSASHA1 not supported" fi diff --git a/bin/tests/system/nsec3/tests_nsec3_initial.py b/bin/tests/system/nsec3/tests_nsec3_initial.py index 6ef80343a9..b890bf9cbd 100644 --- a/bin/tests/system/nsec3/tests_nsec3_initial.py +++ b/bin/tests/system/nsec3/tests_nsec3_initial.py @@ -81,7 +81,7 @@ def bootstrap(): "zone": "rsasha1-to-nsec3.kasp", "policy": "rsasha1", "key-properties": [ - f"csk 0 {RSASHA1.number} 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {RSASHA1.number} 2048 goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", ], }, id="rsasha1-to-nsec3.kasp", @@ -162,7 +162,7 @@ def test_nsec_case(ns3, params): "zone": "nsec3-to-rsasha1.kasp", "policy": "nsec3", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", ], }, id="nsec3-to-rsasha1.kasp", diff --git a/bin/tests/system/nsec3/tests_nsec3_reconfig.py b/bin/tests/system/nsec3/tests_nsec3_reconfig.py index 3b791eba11..26df38cfdd 100644 --- a/bin/tests/system/nsec3/tests_nsec3_reconfig.py +++ b/bin/tests/system/nsec3/tests_nsec3_reconfig.py @@ -92,6 +92,18 @@ def after_servers_start(ns3, templates): @pytest.mark.parametrize( "params", [ + pytest.param( + { + "zone": "rsasha1-to-nsec3.kasp", + "policy": "nsec3", + "key-properties": [ + f"csk 0 {RSASHA1.number} 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", + f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + }, + id="rsasha1-to-nsec3.kasp", + marks=isctest.mark.with_algorithm("RSASHA1"), + ), pytest.param( { "zone": "rsasha1-to-nsec3-wait.kasp", @@ -109,7 +121,7 @@ def after_servers_start(ns3, templates): "zone": "nsec3-to-rsasha1.kasp", "policy": "rsasha1", "key-properties": [ - f"csk 0 {ALGORITHM} {SIZE} goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:unretentive ds:hidden", + f"csk 0 {ALGORITHM} {SIZE} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent", f"csk 0 {RSASHA1.number} 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", ], }, @@ -163,18 +175,6 @@ def test_nsec_case(ns3, params): }, id="nsec-to-nsec3.kasp", ), - pytest.param( - { - "zone": "rsasha1-to-nsec3.kasp", - "policy": "nsec3", - "key-properties": [ - f"csk 0 {RSASHA1.number} 2048 goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:unretentive ds:hidden", - f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", - ], - }, - id="rsasha1-to-nsec3.kasp", - marks=isctest.mark.with_algorithm("RSASHA1"), - ), pytest.param( { "zone": "nsec3.kasp", From 14a243a81dd6b438345d70ff7963ceaaedd85ee7 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Mon, 4 Aug 2025 14:34:07 +0200 Subject: [PATCH 6/6] Fix statschannel system test The manykeys test case relies on keys being removed. Make sure the zone is fully signed with the keys that will stay, so the other keys may be removed safely. This means the expected number of signatures generated and refreshed will change. The CDS and CDNSKEY RRset also need to be signed now. Configure the test case with sig-signing-signatures 100, large enough that the entire zone is processed in a single step. --- .../system/statschannel/ns2/named.conf.in | 1 + .../system/statschannel/ns2/named2.conf.in | 1 + bin/tests/system/statschannel/ns2/sign.sh | 23 +++++++--- bin/tests/system/statschannel/tests.sh | 46 +++++++++---------- bin/tests/system/statschannel/tests_json.py | 3 ++ .../statschannel/tests_sh_statschannel.py | 4 ++ bin/tests/system/statschannel/tests_xml.py | 3 ++ 7 files changed, 52 insertions(+), 29 deletions(-) diff --git a/bin/tests/system/statschannel/ns2/named.conf.in b/bin/tests/system/statschannel/ns2/named.conf.in index 342d03b561..c2f4c1f278 100644 --- a/bin/tests/system/statschannel/ns2/named.conf.in +++ b/bin/tests/system/statschannel/ns2/named.conf.in @@ -24,6 +24,7 @@ options { notify no; minimal-responses no; version none; // make statistics independent of the version number + sig-signing-signatures 100; }; statistics-channels { inet 10.53.0.2 port @EXTRAPORT1@ allow { localhost; }; }; diff --git a/bin/tests/system/statschannel/ns2/named2.conf.in b/bin/tests/system/statschannel/ns2/named2.conf.in index c726ae4220..f93bf94e75 100644 --- a/bin/tests/system/statschannel/ns2/named2.conf.in +++ b/bin/tests/system/statschannel/ns2/named2.conf.in @@ -24,6 +24,7 @@ options { notify no; minimal-responses no; version none; // make statistics independent of the version number + sig-signing-signatures 100; }; statistics-channels { inet 10.53.0.2 port @EXTRAPORT1@ allow { localhost; }; }; diff --git a/bin/tests/system/statschannel/ns2/sign.sh b/bin/tests/system/statschannel/ns2/sign.sh index b9d2ed72d3..a4df397a2a 100644 --- a/bin/tests/system/statschannel/ns2/sign.sh +++ b/bin/tests/system/statschannel/ns2/sign.sh @@ -16,13 +16,18 @@ set -e +longago="now-1y" +keytimes="-P ${longago} -A ${longago}" +O="omnipresent" + zone=dnssec. infile=dnssec.db.in -zonefile=dnssec.db.signed +zonefile=dnssec.db +cp $infile $zonefile ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" -f KSK "$zone") zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -L 3600 -b "$DEFAULT_BITS" "$zone") # Sign deliberately with a very short expiration date. -"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1 +"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" "$zonefile" >"signzone.out.$zone" 2>&1 id=$(keyfile_to_key_id "$ksk") echo "$DEFAULT_ALGORITHM_NUMBER+$id" >dnssec.ksk.id id=$(keyfile_to_key_id "$zsk") @@ -30,16 +35,22 @@ echo "$DEFAULT_ALGORITHM_NUMBER+$id" >dnssec.zsk.id zone=manykeys. infile=manykeys.db.in -zonefile=manykeys.db.signed -ksk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 -f KSK "$zone") -zsk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 "$zone") +zonefile=manykeys.db +cp $infile $zonefile +ksk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 -f KSK $keytimes -P sync $longago "$zone") +zsk8=$("$KEYGEN" -q -a RSASHA256 -L 3600 -b 2048 $keytimes "$zone") +$SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$ksk8" >settime.out.$zone 2>&1 +$SETTIME -s -g $O -k $O $longago -z $O $longago "$zsk8" >settime.out.$zone 2>&1 +cat $ksk8.key $zsk8.key >>$zonefile ksk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 -f KSK "$zone") zsk13=$("$KEYGEN" -q -a ECDSAP256SHA256 -L 3600 -b 256 "$zone") +cat $ksk13.key $zsk13.key >>$zonefile ksk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 -f KSK "$zone") zsk14=$("$KEYGEN" -q -a ECDSAP384SHA384 -L 3600 -b 384 "$zone") +cat $ksk14.key $zsk14.key >>$zonefile # Sign deliberately with a very short expiration date. # Disable zone verification (-P) as records may expire before signing is complete -"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" >"signzone.out.$zone" 2>&1 +"$SIGNER" -P -S -x -O full -e "now"+1s -o "$zone" "$zonefile" >"signzone.out.$zone" 2>&1 id=$(keyfile_to_key_id "$ksk8") echo "8+$id" >manykeys.ksk8.id id=$(keyfile_to_key_id "$zsk8") diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh index 8a343fe1b5..f681649331 100644 --- a/bin/tests/system/statschannel/tests.sh +++ b/bin/tests/system/statschannel/tests.sh @@ -392,22 +392,22 @@ ksk13_id=$(cat ns2/$zone.ksk13.id) zsk13_id=$(cat ns2/$zone.zsk13.id) ksk14_id=$(cat ns2/$zone.ksk14.id) zsk14_id=$(cat ns2/$zone.zsk14.id) -# The dnssec zone has 10 RRsets to sign (including NSEC) with the ZSKs and one -# RRset (DNSKEY) with the KSKs. So starting named with signatures that expire -# almost right away, this should trigger 10 zsk and 1 ksk sign operations per -# key. +# The dnssec zone has 10 RRsets to sign (including NSEC) with the ZSKs and the +# DNSKEY, CDS, and CDNSKEY RRsets with the KSKs. So starting named with +# signatures that expire almost right away, this should trigger 10 zsk and 3 +# ksk sign operations per key. echo "${refresh_prefix} ${zsk8_id}: 10" >zones.expect echo "${refresh_prefix} ${zsk13_id}: 10" >>zones.expect echo "${refresh_prefix} ${zsk14_id}: 10" >>zones.expect -echo "${refresh_prefix} ${ksk8_id}: 1" >>zones.expect -echo "${refresh_prefix} ${ksk13_id}: 1" >>zones.expect -echo "${refresh_prefix} ${ksk14_id}: 1" >>zones.expect +echo "${refresh_prefix} ${ksk8_id}: 3" >>zones.expect +echo "${refresh_prefix} ${ksk13_id}: 3" >>zones.expect +echo "${refresh_prefix} ${ksk14_id}: 3" >>zones.expect echo "${sign_prefix} ${zsk8_id}: 10" >>zones.expect echo "${sign_prefix} ${zsk13_id}: 10" >>zones.expect echo "${sign_prefix} ${zsk14_id}: 10" >>zones.expect -echo "${sign_prefix} ${ksk8_id}: 1" >>zones.expect -echo "${sign_prefix} ${ksk13_id}: 1" >>zones.expect -echo "${sign_prefix} ${ksk14_id}: 1" >>zones.expect +echo "${sign_prefix} ${ksk8_id}: 3" >>zones.expect +echo "${sign_prefix} ${ksk13_id}: 3" >>zones.expect +echo "${sign_prefix} ${ksk14_id}: 3" >>zones.expect cat zones.expect | sort >zones.expect.$n rm -f zones.expect # Fetch and check the dnssec sign statistics. @@ -437,15 +437,15 @@ ret=0 echo "${refresh_prefix} ${zsk8_id}: 10" >zones.expect echo "${refresh_prefix} ${zsk13_id}: 10" >>zones.expect echo "${refresh_prefix} ${zsk14_id}: 10" >>zones.expect -echo "${refresh_prefix} ${ksk8_id}: 1" >>zones.expect -echo "${refresh_prefix} ${ksk13_id}: 1" >>zones.expect -echo "${refresh_prefix} ${ksk14_id}: 1" >>zones.expect +echo "${refresh_prefix} ${ksk8_id}: 3" >>zones.expect +echo "${refresh_prefix} ${ksk13_id}: 3" >>zones.expect +echo "${refresh_prefix} ${ksk14_id}: 3" >>zones.expect echo "${sign_prefix} ${zsk8_id}: 13" >>zones.expect echo "${sign_prefix} ${zsk13_id}: 13" >>zones.expect echo "${sign_prefix} ${zsk14_id}: 13" >>zones.expect -echo "${sign_prefix} ${ksk8_id}: 1" >>zones.expect -echo "${sign_prefix} ${ksk13_id}: 1" >>zones.expect -echo "${sign_prefix} ${ksk14_id}: 1" >>zones.expect +echo "${sign_prefix} ${ksk8_id}: 3" >>zones.expect +echo "${sign_prefix} ${ksk13_id}: 3" >>zones.expect +echo "${sign_prefix} ${ksk14_id}: 3" >>zones.expect cat zones.expect | sort >zones.expect.$n rm -f zones.expect # Fetch and check the dnssec sign statistics. @@ -466,15 +466,15 @@ n=$((n + 1)) ret=0 copy_setports ns2/named2.conf.in ns2/named.conf $RNDCCMD 10.53.0.2 reload 2>&1 | sed 's/^/I:ns2 /' -# This should trigger the resign of DNSKEY (+1 ksk), and SOA, NSEC, -# TYPE65534 (+3 zsk). The dnssec-sign statistics for the removed keys should -# be cleared and thus no longer visible. But NSEC and SOA are (mistakenly) -# counted double, one time because of zone_resigninc and one time because of -# zone_nsec3chain. So +5 zsk in total. +# This should trigger the resign of DNSKEY, CDS, and CDNSKEY (+3 ksk), +# and SOA, NSEC, TYPE65534 (+3 zsk). The dnssec-sign statistics for the +# removed keys should be cleared and thus no longer visible. But NSEC and SOA +# are (mistakenly) counted double, one time because of zone_resigninc and one +# time because of zone_nsec3chain. So +5 zsk in total. echo "${refresh_prefix} ${zsk8_id}: 15" >zones.expect -echo "${refresh_prefix} ${ksk8_id}: 2" >>zones.expect +echo "${refresh_prefix} ${ksk8_id}: 6" >>zones.expect echo "${sign_prefix} ${zsk8_id}: 18" >>zones.expect -echo "${sign_prefix} ${ksk8_id}: 2" >>zones.expect +echo "${sign_prefix} ${ksk8_id}: 6" >>zones.expect cat zones.expect | sort >zones.expect.$n rm -f zones.expect # Fetch and check the dnssec sign statistics. diff --git a/bin/tests/system/statschannel/tests_json.py b/bin/tests/system/statschannel/tests_json.py index 21f2402243..6a2dbc9f96 100755 --- a/bin/tests/system/statschannel/tests_json.py +++ b/bin/tests/system/statschannel/tests_json.py @@ -31,8 +31,11 @@ pytestmark = [ "ns2/dsset-*", "ns2/K*", "ns2/dnssec.db.signed", + "ns2/dnssec.db", "ns2/dnssec.*.id", + "ns2/manykeys.db", "ns2/manykeys.*.id", + "ns2/settime.out.*", "ns2/signzone.out.*", "ns3/_default.nzd", "ns3/example-tcp.db", diff --git a/bin/tests/system/statschannel/tests_sh_statschannel.py b/bin/tests/system/statschannel/tests_sh_statschannel.py index 2f7a826aa4..7b5788010d 100644 --- a/bin/tests/system/statschannel/tests_sh_statschannel.py +++ b/bin/tests/system/statschannel/tests_sh_statschannel.py @@ -31,11 +31,15 @@ pytestmark = pytest.mark.extra_artifacts( "zones*", "ns2/*.jnl", "ns2/*.signed", + "ns2/*.db", "ns2/dsset-*", "ns2/K*", + "ns2/dnssec.db", "ns2/dnssec.*.id", + "ns2/manykeys.db", "ns2/manykeys.*.id", "ns2/named.stats", + "ns2/settime.out.*", "ns2/signzone.out.*", "ns3/_default.nzf*", "ns3/_default.nzd*", diff --git a/bin/tests/system/statschannel/tests_xml.py b/bin/tests/system/statschannel/tests_xml.py index 796eea9d24..59fbcf0b06 100755 --- a/bin/tests/system/statschannel/tests_xml.py +++ b/bin/tests/system/statschannel/tests_xml.py @@ -31,8 +31,11 @@ pytestmark = [ "ns2/*.jnl", "ns2/*.signed", "ns2/dsset-*", + "ns2/dnssec.db", "ns2/dnssec.*.id", + "ns2/manykeys.db", "ns2/manykeys.*.id", + "ns2/settime.out.*", "ns2/signzone.out.*", "ns3/_default.nzd", "ns3/example-tcp.db",