diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index b6062dad22..731ba06524 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -306,9 +306,8 @@ $SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infil # These signatures are already expired, and the private ZSK is retired. setup zsk-retired.autosign -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T -I now" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +zsktimes="$keytimes -I now" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $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 $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index d8497a40fd..d71c16eef4 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -437,96 +437,6 @@ set_keytimes_autosign_policy() { set_addkeytime "KEY2" "REMOVED" "${retired}" 695100 } -# -# Zone: zsk-retired.autosign. -# -set_zone "zsk-retired.autosign" -set_policy "autosign" "3" "300" -set_server "ns3" "10.53.0.3" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "63072000" -set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -key_clear "KEY2" -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "31536000" -set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" - -# Both KSK and ZSK stay OMNIPRESENT. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" -# Expect only two keys. -key_clear "KEY3" -key_clear "KEY4" -# The third key is not yet expected to be signing. -set_keyrole "KEY3" "zsk" -set_keylifetime "KEY3" "31536000" -set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY3" "no" -set_zonesigning "KEY3" "no" -# The ZSK goal is set to HIDDEN but records stay OMNIPRESENT until the new ZSK -# is active. -set_keystate "KEY2" "GOAL" "hidden" -set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" -# A new ZSK should be introduced, so expect a key with goal OMNIPRESENT, -# the DNSKEY introduced (RUMOURED) and the signatures HIDDEN. -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_ZRRSIG" "hidden" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_autosign_policy - -# The old ZSK is retired. -created=$(key_get KEY2 CREATED) -set_keytime "KEY2" "RETIRED" "${created}" -set_addkeytime "KEY2" "REMOVED" "${created}" 695100 -# The new ZSK is immediately published. -created=$(key_get KEY3 CREATED) -set_keytime "KEY3" "PUBLISHED" "${created}" -# And becomes active after Ipub: -# DNSKEY TTL: 300 seconds -# zone-propagation-delay 5 minutes (300 seconds) -# publish-safety: 1 hour (3600 seconds) -# Ipub: 4200 seconds -published=$(key_get KEY3 PUBLISHED) -set_addkeytime "KEY3" "ACTIVE" "${published}" 4200 -# Lzsk: 1 year (31536000 seconds) -active=$(key_get KEY3 ACTIVE) -set_addkeytime "KEY3" "RETIRED" "${active}" 31536000 -# Iret: 695100 seconds. -retired=$(key_get KEY3 RETIRED) -set_addkeytime "KEY3" "REMOVED" "${retired}" 695100 - -check_keytimes -check_apex -check_subdomain -dnssec_verify -#check_rrsig_refresh - -# Load again, make sure the purged key is not an issue when verifying keys. -echo_i "load keys for $ZONE, making sure a recently purged key is not an issue when verifying keys ($n)" -ret=0 -rndccmd 10.53.0.3 loadkeys "$ZONE" >/dev/null || log_error "rndc loadkeys zone ${ZONE} failed" -wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run || ret=1 -grep "zone $ZONE/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" $DIR/named.run && ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - # # Test dnssec-policy inheritance. # diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py index 63efab4dd5..5fe82fa403 100644 --- a/bin/tests/system/kasp/tests_kasp.py +++ b/bin/tests/system/kasp/tests_kasp.py @@ -1151,3 +1151,138 @@ def test_kasp_dnssec_keygen(): out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8") isctest.kasp.check_keys("kasp", keys, expected) isctest.kasp.check_keytimes(keys, expected) + + +def test_kasp_zsk_retired(servers): + server = servers["ns3"] + + config = { + "dnskey-ttl": timedelta(seconds=300), + "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), + } + + zone = "zsk-retired.autosign" + policy = "autosign" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + key_properties = [ + f"ksk 63072000 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + # zsk predecessor + f"zsk 31536000 {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent", + # zsk successor + f"zsk 31536000 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden", + ] + expected = isctest.kasp.policy_to_properties(300, key_properties) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + + offset = -timedelta(days=30 * 6) + sign_delay = config["signatures-validity"] - config["signatures-refresh"] + + def sumvars(variables): + result = timedelta(0) + for var in variables: + result = result + config[var] + return result + + # KSK Key Timings: + # IpubC = DprpC + TTLkey + # Note: Also need to wait until the signatures are omnipresent. + # That's why we use max-zone-ttl instead of dnskey-ttl here. + Ipub_KSK = sumvars(["zone-propagation-delay", "max-zone-ttl"]) + # Iret = DprpP + TTLds + Iret_KSK = sumvars(["parent-propagation-delay", "retire-safety", "ds-ttl"]) + + # ZSK Key Timings: + # Ipub = Dprp + TTLkey + Ipub_ZSK = sumvars(["zone-propagation-delay", "publish-safety", "dnskey-ttl"]) + # Iret = Dsgn + Dprp + TTLsig + Iret_ZSK = sumvars(["zone-propagation-delay", "retire-safety", "max-zone-ttl"]) + Iret_ZSK = Iret_ZSK + sign_delay + + # KSK + expected[0].timing["Generated"] = expected[0].key.get_timing("Created") + expected[0].timing["Published"] = expected[0].timing["Generated"] + expected[0].timing["Published"] = expected[0].timing["Published"] + offset + expected[0].timing["Active"] = expected[0].timing["Published"] + expected[0].timing["Retired"] = expected[0].timing["Published"] + int( + expected[0].metadata["Lifetime"] + ) + # Trdy(N) = Tpub(N) + IpubC + expected[0].timing["PublishCDS"] = expected[0].timing["Published"] + Ipub_KSK + # Tdea(N) = Tret(N) + Iret + expected[0].timing["Removed"] = expected[0].timing["Retired"] + Iret_KSK + expected[0].timing["DNSKEYChange"] = None + expected[0].timing["DSChange"] = None + expected[0].timing["KRRSIGChange"] = None + + # ZSK (predecessor) + expected[1].timing["Generated"] = expected[1].key.get_timing("Created") + expected[1].timing["Published"] = expected[1].timing["Generated"] + offset + expected[1].timing["Active"] = expected[1].timing["Published"] + expected[1].timing["Retired"] = expected[1].timing["Generated"] + # Tdea(N) = Tret(N) + Iret + expected[1].timing["Removed"] = expected[1].timing["Retired"] + Iret_ZSK + expected[1].timing["DNSKEYChange"] = None + expected[1].timing["ZRRSIGChange"] = None + + # ZSK (successor) + expected[2].timing["Generated"] = expected[2].key.get_timing("Created") + expected[2].timing["Published"] = expected[2].timing["Generated"] + # Trdy(N) = Tpub(N) + Ipub + expected[2].timing["Active"] = expected[2].timing["Published"] + Ipub_ZSK + # Tret(N) = Tact(N) + Lzsk + expected[2].timing["Retired"] = expected[2].timing["Active"] + int( + expected[2].metadata["Lifetime"] + ) + # Tdea(N) = Tret(N) + Iret + expected[2].timing["Removed"] = expected[2].timing["Retired"] + Iret_ZSK + expected[2].timing["DNSKEYChange"] = None + expected[2].timing["ZRRSIGChange"] = None + + isctest.kasp.check_keytimes(keys, expected) + check_all(server, zone, policy, ksks, zsks) + + queries = [ + f"{zone} DNSKEY", + f"{zone} SOA", + f"{zone} NS", + f"{zone} NSEC", + f"a.{zone} A", + f"a.{zone} NSEC", + f"b.{zone} A", + f"b.{zone} NSEC", + f"c.{zone} A", + f"c.{zone} NSEC", + f"ns3.{zone} A", + f"ns3.{zone} NSEC", + ] + + def rrsig_is_refreshed(): + parts = query.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + return isctest.kasp.verify_rrsig_is_refreshed( + server, zone, f"ns3/{zone}.db.signed", qname, qtype, ksks, zsks + ) + + for query in queries: + isctest.run.retry_with_timeout(rrsig_is_refreshed, timeout=5) + + # Load again, make sure the purged key is not an issue when verifying keys. + with server.watch_log_from_here() as watcher: + server.rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line(f"keymgr: {zone} done") + + msg = f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" + server.log.prohibit(msg)