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..c1b33ddb08 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -97,237 +97,6 @@ set_keytimes_csk_policy() { # Key lifetime is unlimited, so not setting RETIRED and REMOVED. } -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -# -# Zone: checkds-ksk.kasp. -# -key_clear "KEY1" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -set_zone "checkds-ksk.kasp" -set_policy "checkds-ksk" "2" "303" -set_server "ns3" "10.53.0.3" - -# Key properties. -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "0" -set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "rumoured" -set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -basefile=$(key_get KEY1 BASEFILE) - -_wait_for_metadata() { - _expr=$1 - _file=$2 - grep "$_expr" $_file >/dev/null || return 1 - return 0 -} - -n=$((n + 1)) -echo_i "checkds publish correctly sets DSPublish for zone $ZONE ($n)" -now=$(date +%Y%m%d%H%M%S) -rndc_checkds "$SERVER" "$DIR" "-" "$now" "published" "$ZONE" -retry_quiet 3 _wait_for_metadata "DSPublish: $now" "${basefile}.state" || log_error "bad DSPublish in ${basefile}.state" -# DS State should be forced into RUMOURED. -set_keystate "KEY1" "STATE_DS" "rumoured" -check_keys -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds withdraw correctly sets DSRemoved for zone $ZONE ($n)" -now=$(date +%Y%m%d%H%M%S) -rndc_checkds "$SERVER" "$DIR" "-" "$now" "withdrawn" "$ZONE" -retry_quiet 3 _wait_for_metadata "DSRemoved: $now" "${basefile}.state" || log_error "bad DSRemoved in ${basefile}.state" -# DS State should be forced into UNRETENTIVE. -set_keystate "KEY1" "STATE_DS" "unretentive" -check_keys -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# -# Zone: checkds-doubleksk.kasp. -# -key_clear "KEY1" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -set_zone "checkds-doubleksk.kasp" -set_policy "checkds-doubleksk" "3" "303" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -set_keyrole "KEY2" "ksk" -set_keylifetime "KEY2" "0" -set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY2" "yes" -set_zonesigning "KEY2" "no" - -set_keyrole "KEY3" "zsk" -set_keylifetime "KEY3" "0" -set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY3" "no" -set_zonesigning "KEY3" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "rumoured" -set_keystate "KEY2" "STATE_KRRSIG" "rumoured" -set_keystate "KEY2" "STATE_DS" "hidden" - -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_ZRRSIG" "rumoured" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -basefile1=$(key_get KEY1 BASEFILE) -basefile2=$(key_get KEY2 BASEFILE) - -n=$((n + 1)) -echo_i "checkds published does not set DSPublish for zone $ZONE (multiple KSK) ($n)" -rndc_checkds "$SERVER" "$DIR" "-" "20200102121314" "published" "$ZONE" -grep "DSPublish:" "${basefile1}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile1}" -grep "DSPublish:" "${basefile2}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile2}" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds withdrawn does not set DSRemoved for zone $ZONE (multiple KSK) ($n)" -rndc_checkds "$SERVER" "$DIR" "-" "20190102121314" "withdrawn" "$ZONE" -grep "DSRemoved:" "${basefile1}.state" >/dev/null && log_error "DSRemoved incorrectly set in ${basefile1}" -grep "DSRemoved:" "${basefile2}.state" >/dev/null && log_error "DSRemoved incorrectly set in ${basefile2}" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds published does not set DSPublish for zone $ZONE (wrong algorithm) ($n)" -rndccmd "$SERVER" dnssec -checkds -key $(key_get KEY1 ID) -alg 8 "published" "$ZONE" >rndc.dnssec.checkds.out.$ZONE.$n -grep "DSPublish:" "${basefile1}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile1}" -grep "DSPublish:" "${basefile2}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile2}" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds withdrawn does not set DSRemoved for zone $ZONE (wrong algorithm) ($n)" -rndccmd "$SERVER" dnssec -checkds -key $(key_get KEY1 ID) -alg RSASHA256 "withdrawn" "$ZONE" >rndc.dnssec.checkds.out.$ZONE.$n -grep "DSRemoved:" "${basefile1}.state" >/dev/null && log_error "DSRemoved incorrectly set in ${basefile1}" -grep "DSRemoved:" "${basefile2}.state" >/dev/null && log_error "DSRemoved incorrectly set in ${basefile2}" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds published -key correctly sets DSPublish for key $(key_get KEY1 ID) zone $ZONE (multiple KSK) ($n)" -rndc_checkds "$SERVER" "$DIR" KEY1 "20190102121314" "published" "$ZONE" -retry_quiet 3 _wait_for_metadata "DSPublish: 20190102121314" "${basefile1}.state" || log_error "bad DSPublish in ${basefile1}.state" -grep "DSPublish:" "${basefile2}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile2}" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds withdrawn -key correctly sets DSRemoved for key $(key_get KEY2 ID) zone $ZONE (multiple KSK) ($n)" -rndc_checkds "$SERVER" "$DIR" KEY2 "20200102121314" "withdrawn" "$ZONE" -grep "DSRemoved:" "${basefile1}.state" >/dev/null && log_error "DSPublish incorrectly set in ${basefile1}" -retry_quiet 3 _wait_for_metadata "DSRemoved: 20200102121314" "${basefile2}.state" || log_error "bad DSRemoved in ${basefile2}.state" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# -# Zone: checkds-csk.kasp. -# -key_clear "KEY1" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -set_zone "checkds-csk.kasp" -set_policy "checkds-csk" "1" "303" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -basefile=$(key_get KEY1 BASEFILE) - -n=$((n + 1)) -echo_i "checkds publish correctly sets DSPublish for zone $ZONE ($n)" -rndc_checkds "$SERVER" "$DIR" "-" "20190102121314" "published" "$ZONE" -retry_quiet 3 _wait_for_metadata "DSPublish: 20190102121314" "${basefile}.state" || log_error "bad DSPublish in ${basefile}.state" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "checkds withdraw correctly sets DSRemoved for zone $ZONE ($n)" -rndc_checkds "$SERVER" "$DIR" "-" "20200102121314" "withdrawn" "$ZONE" -retry_quiet 3 _wait_for_metadata "DSRemoved: 20200102121314" "${basefile}.state" || log_error "bad DSRemoved in ${basefile}.state" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - # Set keytimes for dnssec-policy with various algorithms. # These all use the same time values. set_keytimes_algorithm_policy() { @@ -437,445 +206,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. -# - -# These zones should be unsigned: -# ns2/unsigned.tld -# ns4/none.inherit.signed -# ns4/none.override.signed -# ns4/inherit.none.signed -# ns4/none.none.signed -# ns5/inherit.inherit.unsigned -# ns5/none.inherit.unsigned -# ns5/none.override.unsigned -# ns5/inherit.none.unsigned -# ns5/none.none.unsigned -key_clear "KEY1" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -set_zone "unsigned.tld" -set_policy "none" "0" "0" -set_server "ns2" "10.53.0.2" -TSIG="" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.inherit.signed" -set_policy "none" "0" "0" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha1:sha1:$SHA1" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.override.signed" -set_policy "none" "0" "0" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha224:sha224:$SHA224" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "inherit.none.signed" -set_policy "none" "0" "0" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha256:sha256:$SHA256" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.none.signed" -set_policy "none" "0" "0" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha256:sha256:$SHA256" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "inherit.inherit.unsigned" -set_policy "none" "0" "0" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha1:sha1:$SHA1" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.inherit.unsigned" -set_policy "none" "0" "0" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha1:sha1:$SHA1" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.override.unsigned" -set_policy "none" "0" "0" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha224:sha224:$SHA224" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "inherit.none.unsigned" -set_policy "none" "0" "0" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha256:sha256:$SHA256" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -set_zone "none.none.unsigned" -set_policy "none" "0" "0" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha256:sha256:$SHA256" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -# These zones should be signed with the default policy: -# ns2/signed.tld -# ns4/override.inherit.signed -# ns4/inherit.override.signed -# ns5/override.inherit.signed -# ns5/inherit.override.signed -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" - -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_zone "signed.tld" -set_policy "default" "1" "3600" -set_server "ns2" "10.53.0.2" -TSIG="" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.inherit.signed" -set_policy "default" "1" "3600" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha1:sha1:$SHA1" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "inherit.override.signed" -set_policy "default" "1" "3600" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha224:sha224:$SHA224" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.inherit.unsigned" -set_policy "default" "1" "3600" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha1:sha1:$SHA1" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "inherit.override.unsigned" -set_policy "default" "1" "3600" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha224:sha224:$SHA224" -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# These zones should be signed with the test policy: -# ns4/inherit.inherit.signed -# ns4/override.override.signed -# ns4/override.none.signed -# ns5/override.override.unsigned -# ns5/override.none.unsigned -# ns4/example.net (both views) -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "14" "ECDSAP384SHA384" "384" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" - -set_zone "inherit.inherit.signed" -set_policy "test" "1" "3600" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha1:sha1:$SHA1" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.override.signed" -set_policy "test" "1" "3600" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha224:sha224:$SHA224" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.none.signed" -set_policy "test" "1" "3600" -set_server "ns4" "10.53.0.4" -TSIG="hmac-sha256:sha256:$SHA256" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.override.unsigned" -set_policy "test" "1" "3600" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha224:sha224:$SHA224" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -set_zone "override.none.unsigned" -set_policy "test" "1" "3600" -set_server "ns5" "10.53.0.5" -TSIG="hmac-sha256:sha256:$SHA256" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Test with views. -set_zone "example.net" -set_server "ns4" "10.53.0.4" -TSIG="$DEFAULT_HMAC:keyforview1:$VIEW1" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example1" -set_keytimes_csk_policy -check_keytimes -check_apex -dnssec_verify -# check zonestatus -n=$((n + 1)) -echo_i "check $ZONE (view example1) zonestatus ($n)" -ret=0 -check_isdynamic "$SERVER" "$ZONE" "example1" || log_error "zone not dynamic" -check_inlinesigning "$SERVER" "$ZONE" "example1" && log_error "inline-signing enabled, expected disabled" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -# check subdomain -n=$((n + 1)) -echo_i "check TXT example.net (view example1) rrset is signed correctly ($n)" -ret=0 -dig_with_opts "view.${ZONE}" "@${SERVER}" TXT >"dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed" -grep "status: NOERROR" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "mismatch status in DNS response" -grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view1" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "missing view.${ZONE} TXT record in response" -check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -TSIG="$DEFAULT_HMAC:keyforview2:$VIEW2" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example2" -check_apex -dnssec_verify -# check zonestatus -n=$((n + 1)) -echo_i "check $ZONE (view example2) zonestatus ($n)" -ret=0 -check_isdynamic "$SERVER" "$ZONE" "example2" && log_error "zone dynamic, but not expected" -check_inlinesigning "$SERVER" "$ZONE" "example2" || log_error "inline-signing disabled, expected enabled" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -# check subdomain -n=$((n + 1)) -echo_i "check TXT example.net (view example2) rrset is signed correctly ($n)" -ret=0 -dig_with_opts "view.${ZONE}" "@${SERVER}" TXT >"dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed" -grep "status: NOERROR" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "mismatch status in DNS response" -grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view2" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "missing view.${ZONE} TXT record in response" -check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -TSIG="$DEFAULT_HMAC:keyforview3:$VIEW3" -wait_for_nsec -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" "example3" -check_apex -dnssec_verify -# check zonestatus -n=$((n + 1)) -echo_i "check $ZONE (view example3) zonestatus ($n)" -ret=0 -check_isdynamic "$SERVER" "$ZONE" "example3" && log_error "zone dynamic, but not expected" -check_inlinesigning "$SERVER" "$ZONE" "example3" || log_error "inline-signing disabled, expected enabled" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -# check subdomain -n=$((n + 1)) -echo_i "check TXT example.net (view example3) rrset is signed correctly ($n)" -ret=0 -dig_with_opts "view.${ZONE}" "@${SERVER}" TXT >"dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed" -grep "status: NOERROR" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "mismatch status in DNS response" -grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view2" "dig.out.$DIR.test$n.txt" >/dev/null || log_error "missing view.${ZONE} TXT record in response" -check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK" -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Clear TSIG. -TSIG="" - # # Testing RFC 8901 Multi-Signer Model 2. # @@ -3982,49 +3312,5 @@ dnssec_verify # an unlimited lifetime. Fallback to the default loadkeys interval. check_next_key_event 3600 -_check_soa_ttl() { - dig_with_opts @10.53.0.6 example SOA >dig.out.ns6.test$n.soa2 || return 1 - soa1=$(awk '$4 == "SOA" { print $7 }' dig.out.ns6.test$n.soa1) - soa2=$(awk '$4 == "SOA" { print $7 }' dig.out.ns6.test$n.soa2) - ttl1=$(awk '$4 == "SOA" { print $2 }' dig.out.ns6.test$n.soa1) - ttl2=$(awk '$4 == "SOA" { print $2 }' dig.out.ns6.test$n.soa2) - test ${soa1:-1000} -lt ${soa2:-0} || return 1 - test ${ttl1:-0} -eq $1 || return 1 - test ${ttl2:-0} -eq $2 || return 1 -} - -n=$((n + 1)) -echo_i "Check that 'rndc reload' of just the serial updates the signed instance ($n)" -TSIG= -ret=0 -dig_with_opts @10.53.0.6 example SOA >dig.out.ns6.test$n.soa1 || ret=1 -cp ns6/example2.db.in ns6/example.db || ret=1 -nextpart ns6/named.run >/dev/null -rndccmd 10.53.0.6 reload || ret=1 -wait_for_log 3 "all zones loaded" ns6/named.run || ret=1 -# Check that the SOA SERIAL increases and check the TTLs (should be 300 as -# defined in ns6/example2.db.in). -retry_quiet 10 _check_soa_ttl 300 300 || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -n=$((n + 1)) -echo_i "Check that restart with zone changes and deleted journal works ($n)" -TSIG= -ret=0 -dig_with_opts @10.53.0.6 example SOA >dig.out.ns6.test$n.soa1 || ret=1 -stop_server --use-rndc --port ${CONTROLPORT} ns6 -# TTL of all records change from 300 to 400 -cp ns6/example3.db.in ns6/example.db || ret=1 -rm ns6/example.db.jnl -nextpart ns6/named.run >/dev/null -start_server --noclean --restart --port ${PORT} ns6 -wait_for_log 3 "all zones loaded" ns6/named.run || ret=1 -# Check that the SOA SERIAL increases and check the TTLs (should be changed -# from 300 to 400 as defined in ns6/example3.db.in). -retry_quiet 10 _check_soa_ttl 300 400 || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py index 63efab4dd5..178e602f48 100644 --- a/bin/tests/system/kasp/tests_kasp.py +++ b/bin/tests/system/kasp/tests_kasp.py @@ -26,6 +26,7 @@ from isctest.kasp import ( KeyProperties, KeyTimingMetadata, ) +from isctest.vars.algorithms import ECDSAP256SHA256, ECDSAP384SHA384 pytestmark = pytest.mark.extra_artifacts( [ @@ -116,6 +117,21 @@ lifetime = { "P6M": int(timedelta(days=31 * 6).total_seconds()), } +KASP_INHERIT_TSIG_SECRET = { + "sha1": "FrSt77yPTFx6hTs4i2tKLB9LmE0=", + "sha224": "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==", + "sha256": "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=", + "view1": "YPfMoAk6h+3iN8MDRQC004iSNHY=", + "view2": "4xILSZQnuO1UKubXHkYUsvBRPu8=", + "view3": "C1Azf+gGPMmxrUg/WQINP6eV9Y0=", +} + + +def param(*args, **kwargs): + if "id" not in kwargs: + kwargs["id"] = args[0] # use first argument as test ID + return pytest.param(*args, **kwargs) + def autosign_properties(alg, size): return [ @@ -685,6 +701,129 @@ def test_kasp_case(servers, params): callback(*arguments, params=params, ksks=ksks, zsks=zsks) +@pytest.mark.parametrize( + "zone, server_id, tsig_kind", + [ + param("unsigned.tld", "ns2", None), + param("none.inherit.signed", "ns4", "sha1"), + param("none.override.signed", "ns4", "sha224"), + param("inherit.none.signed", "ns4", "sha256"), + param("none.none.signed", "ns4", "sha256"), + param("inherit.inherit.unsigned", "ns5", "sha1"), + param("none.inherit.unsigned", "ns5", "sha1"), + param("none.override.unsigned", "ns5", "sha224"), + param("inherit.none.unsigned", "ns5", "sha256"), + param("none.none.unsigned", "ns5", "sha256"), + ], +) +def test_kasp_inherit_unsigned(zone, server_id, tsig_kind, servers): + server = servers[server_id] + tsig = ( + f"hmac-{tsig_kind}:{tsig_kind}:{KASP_INHERIT_TSIG_SECRET[tsig_kind]}" + if tsig_kind + else None + ) + + keys = isctest.kasp.keydir_to_keylist(zone, server.identifier) + isctest.kasp.check_keys(zone, keys, []) + isctest.kasp.check_dnssecstatus(server, zone, []) + isctest.kasp.check_apex(server, zone, [], [], tsig=tsig) + isctest.kasp.check_subdomain(server, zone, [], [], tsig=tsig) + + +@pytest.mark.parametrize( + "zone, policy, server_id, alg, tsig_kind", + [ + param("signed.tld", "default", "ns2", ECDSAP256SHA256, None), + param("override.inherit.signed", "default", "ns4", ECDSAP256SHA256, "sha1"), + param("inherit.override.signed", "default", "ns4", ECDSAP256SHA256, "sha224"), + param("override.inherit.unsigned", "default", "ns5", ECDSAP256SHA256, "sha1"), + param("inherit.override.unsigned", "default", "ns5", ECDSAP256SHA256, "sha224"), + param("inherit.inherit.signed", "test", "ns4", ECDSAP384SHA384, "sha1"), + param("override.override.signed", "test", "ns4", ECDSAP384SHA384, "sha224"), + param("override.none.signed", "test", "ns4", ECDSAP384SHA384, "sha256"), + param("override.override.unsigned", "test", "ns5", ECDSAP384SHA384, "sha224"), + param("override.none.unsigned", "test", "ns5", ECDSAP384SHA384, "sha256"), + ], +) +def test_kasp_inherit_signed(zone, policy, server_id, alg, tsig_kind, servers): + server = servers[server_id] + tsig = ( + f"hmac-{tsig_kind}:{tsig_kind}:{KASP_INHERIT_TSIG_SECRET[tsig_kind]}" + if tsig_kind + else None + ) + + key1 = KeyProperties.default() + key1.metadata["Algorithm"] = alg.number + key1.metadata["Length"] = alg.bits + keys = isctest.kasp.keydir_to_keylist(zone, server.identifier) + + isctest.kasp.check_zone_is_signed(server, zone, tsig=tsig) + isctest.kasp.check_keys(zone, keys, [key1]) + set_keytimes_default_policy(key1) + isctest.kasp.check_keytimes(keys, [key1]) + check_all(server, zone, policy, keys, [], tsig=tsig) + + +@pytest.mark.parametrize( + "number, dynamic, inline_signing, txt_rdata", + [ + param("1", "yes", "no", "view1"), + param("2", "no", "yes", "view2"), + param("3", "no", "yes", "view2"), + ], +) +def test_kasp_inherit_view(number, dynamic, inline_signing, txt_rdata, servers): + zone = "example.net" + policy = "test" + server = servers["ns4"] + view = f"example{number}" + tsig = f"{os.environ['DEFAULT_HMAC']}:keyforview{number}:{KASP_INHERIT_TSIG_SECRET[f'view{number}']}" + + key1 = KeyProperties.default() + key1.metadata["Algorithm"] = ECDSAP384SHA384.number + key1.metadata["Length"] = ECDSAP384SHA384.bits + keys = isctest.kasp.keydir_to_keylist(zone, server.identifier) + + isctest.kasp.check_zone_is_signed(server, zone, tsig=tsig) + isctest.kasp.check_keys(zone, keys, [key1]) + set_keytimes_default_policy(key1) + isctest.kasp.check_keytimes(keys, [key1]) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy, view=view) + isctest.kasp.check_apex(server, zone, keys, [], tsig=tsig) + # check zonestatus + response = server.rndc(f"zonestatus {zone} in {view}", log=False) + assert f"dynamic: {dynamic}" in response + assert f"inline signing: {inline_signing}" in response + # check subdomain + fqdn = f"{zone}." + qname = f"view.{zone}." + qtype = dns.rdatatype.TXT + rdata = txt_rdata + query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) + tsigkey = tsig.split(":") + keyring = dns.tsig.Key(tsigkey[1], tsigkey[2], tsigkey[0]) + query.use_tsig(keyring) + try: + response = isctest.query.tcp(query, server.ip, server.ports.dns, timeout=3) + except dns.exception.Timeout: + isctest.log.debug(f"query timeout for query {qname} {qtype} to {server.ip}") + response = None + assert response.rcode() == dns.rcode.NOERROR + match = f'{qname} 300 IN TXT "{rdata}"' + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + else: + assert match in rrset.to_text() + assert len(rrsigs) > 0 + isctest.kasp.check_signatures(rrsigs, qtype, fqdn, keys, []) + + def test_kasp_default(servers): server = servers["ns3"] @@ -921,6 +1060,166 @@ def test_kasp_dynamic(servers): assert f"zone_resigninc: zone {zone}/IN (unsigned): enter" not in "ns3/named.run" +def test_kasp_checkds(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-ksk.kasp. + zone = "checkds-ksk.kasp" + policy = "checkds-ksk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + 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 k.is_zsk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, ksks, zsks) + + now = KeyTimingMetadata.now() + ksk = ksks[0] + + isctest.log.info("check if checkds -publish correctly sets DSPublish") + server.rndc(f"dnssec -checkds -when {now} published {zone}", log=False) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn correctly sets DSRemoved") + server.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "unretentive" + expected[0].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + +def test_kasp_checkds_doubleksk(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-doubleksk.kasp. + zone = "checkds-doubleksk.kasp" + policy = "checkds-doubleksk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + 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 k.is_zsk()] + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, ksks, zsks) + + now = KeyTimingMetadata.now() + ksk = ksks[0] + + badalg = os.environ["ALTERNATIVE_ALGORITHM_NUMBER"] + isctest.log.info("check invalid checkds commands") + + def check_error(): + response = server.rndc(test["command"], log=False) + assert test["error"] in response + + test_cases = [ + { + "command": f"dnssec -checkds -when {now} published {zone}", + "error": "multiple possible keys found, retry command with -key id", + }, + { + "command": f"dnssec -checkds -when {now} withdrawn {zone}", + "error": "multiple possible keys found, retry command with -key id", + }, + { + "command": f"dnssec -checkds -when {now} -key {ksks[0].tag} -alg {badalg} published {zone}", + "error": "Error executing checkds command: no matching key found", + }, + { + "command": f"dnssec -checkds -when {now} -key {ksks[0].tag} -alg {badalg} withdrawn {zone}", + "error": "Error executing checkds command: no matching key found", + }, + ] + for test in test_cases: + check_error() + + isctest.log.info("check if checkds -publish -key correctly sets DSPublish") + server.rndc( + f"dnssec -checkds -when {now} -key {ksk.tag} published {zone}", log=False + ) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn -key correctly sets DSRemoved") + ksk = ksks[1] + server.rndc( + f"dnssec -checkds -when {now} -key {ksk.tag} withdrawn {zone}", log=False + ) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[1].metadata["DSState"] = "unretentive" + expected[1].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + +def test_kasp_checkds_csk(servers): + server = servers["ns3"] + + def wait_for_metadata(): + return isctest.util.file_contents_contain(ksk.statefile, metadata) + + # Zone: checkds-csk.kasp. + zone = "checkds-csk.kasp" + policy = "checkds-csk" + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + policy_keys = [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ] + expected = isctest.kasp.policy_to_properties(ttl=303, keys=policy_keys) + keys = isctest.kasp.keydir_to_keylist(zone, "ns3") + isctest.kasp.check_zone_is_signed(server, zone) + isctest.kasp.check_keys(zone, keys, expected) + check_all(server, zone, policy, keys, []) + + now = KeyTimingMetadata.now() + ksk = keys[0] + + isctest.log.info("check if checkds -publish csk correctly sets DSPublish") + server.rndc(f"dnssec -checkds -when {now} published {zone}", log=False) + metadata = f"DSPublish: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "rumoured" + expected[0].timing["DSPublish"] = now + isctest.kasp.check_keys(zone, keys, expected) + + isctest.log.info("check if checkds -withdrawn csk correctly sets DSRemoved") + server.rndc(f"dnssec -checkds -when {now} withdrawn {zone}", log=False) + metadata = f"DSRemoved: {now}" + isctest.run.retry_with_timeout(wait_for_metadata, timeout=3) + expected[0].metadata["DSState"] = "unretentive" + expected[0].timing["DSRemoved"] = now + isctest.kasp.check_keys(zone, keys, expected) + + def test_kasp_special_characters(servers): server = servers["ns3"] @@ -1151,3 +1450,197 @@ 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) + + +def test_kasp_reload_restart(servers): + server = servers["ns6"] + zone = "example" + + def query_soa(qname): + fqdn = dns.name.from_text(qname) + qtype = dns.rdatatype.SOA + query = dns.message.make_query(fqdn, qtype, use_edns=True, want_dnssec=True) + try: + response = isctest.query.tcp(query, server.ip, server.ports.dns, timeout=3) + except dns.exception.Timeout: + isctest.log.debug(f"query timeout for query {qname} SOA to {server.ip}") + return 0, 0 + + assert response.rcode() == dns.rcode.NOERROR + + for rr in response.answer: + if rr.match(fqdn, dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype): + continue + + assert rr.match(fqdn, dns.rdataclass.IN, qtype, dns.rdatatype.NONE) + assert len(rr) == 1 + return rr[0].serial, rr.ttl + + return 0, 0 + + def check_soa_ttl(): + soa2, ttl2 = query_soa(zone) + return soa1 < soa2 and ttl2 == newttl + + # Check that the SOA SERIAL increases and check the TTLs (should be 300 as + # defined in ns6/example2.db.in). + soa1, ttl1 = query_soa(zone) + assert ttl1 == 300 + + shutil.copyfile(f"ns6/{zone}2.db.in", f"ns6/{zone}.db") + with server.watch_log_from_here() as watcher: + server.rndc("reload", log=False) + watcher.wait_for_line("all zones loaded") + + newttl = 300 + isctest.run.retry_with_timeout(check_soa_ttl, timeout=10) + + # Check that the SOA SERIAL increases and check the TTLs (should be changed + # from 300 to 400 as defined in ns6/example3.db.in). + soa1, ttl1 = query_soa(zone) + assert ttl1 == 300 + + server.stop() + shutil.copyfile(f"ns6/{zone}3.db.in", f"ns6/{zone}.db") + os.unlink(f"ns6/{zone}.db.jnl") + with server.watch_log_from_here() as watcher: + server.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + watcher.wait_for_line("all zones loaded") + + newttl = 400 + isctest.run.retry_with_timeout(check_soa_ttl, timeout=10)