From 2c10acafa438887f9a2b34f7b48e22fdbe2316ea Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Mon, 17 Mar 2025 16:39:52 +0100 Subject: [PATCH] Convert kasp checkds test cases to pytest This converts the checkds test cases that deal with the 'rndc checkds' command and setting the 'DSPublish' and 'DSRemoved' metadata. (cherry picked from commit 44b4d5ebd66163b97b3ba0a08e01b8d99523a58e) --- bin/tests/system/kasp/tests.sh | 231 ---------------------------- bin/tests/system/kasp/tests_kasp.py | 160 +++++++++++++++++++ 2 files changed, 160 insertions(+), 231 deletions(-) diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 53950cb543..228ef50cba 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() { diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py index 5fe82fa403..d3406b746a 100644 --- a/bin/tests/system/kasp/tests_kasp.py +++ b/bin/tests/system/kasp/tests_kasp.py @@ -921,6 +921,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"]