mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
chg: test: Rewrite kasp system test to pytest (4)
These tests do not easily fit in the standard test case framework, so they go into their own suite. - zsk retired case - checkds cases - reload/restart - inheritance tests Merge branch 'matthijs-pytest-rewrite-kasp-system-test-4' into 'main' See merge request isc-projects/bind9!10278
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user