From ee4199f22a409ff4344e84dd53ee743ea265bf28 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Tue, 18 Mar 2025 10:34:53 +0100 Subject: [PATCH] Convert enable dnssec test case to pytest Move the 'enable-dnssec' to the rollover test dir and convert to pytest. This requires new test functionality to check that "CDS is published" messages are logged (or prohibited). The setup part is slightly adapted such that it no longer needs to set the '-P sync' value in most cases (this is then set by 'named'), and to adjust for the inappropriate safety intervals fix. (cherry picked from commit 233fdb8d520bda11fe18efe9c14e36930e6e96b0) --- bin/tests/system/isctest/kasp.py | 19 +++ bin/tests/system/isctest/vars/algorithms.py | 2 + bin/tests/system/kasp/ns3/named-fips.conf.in | 24 --- .../system/kasp/ns3/policies/autosign.conf.in | 20 --- bin/tests/system/kasp/ns3/setup.sh | 69 -------- bin/tests/system/kasp/tests.sh | 153 ------------------ bin/tests/system/rollover/ns3/kasp.conf.j2 | 19 +++ bin/tests/system/rollover/ns3/named.conf.j2 | 24 +++ bin/tests/system/rollover/ns3/setup.sh | 61 +++++++ bin/tests/system/rollover/tests_rollover.py | 131 +++++++++++++++ 10 files changed, 256 insertions(+), 266 deletions(-) diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 35d8c6e82a..5beb8f2632 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -25,6 +25,7 @@ import dns.tsig import isctest.log import isctest.query import isctest.util +from isctest.vars.algorithms import Algorithm, ALL_ALGORITHMS_BY_NUM DEFAULT_TTL = 300 @@ -403,6 +404,11 @@ class Key: def is_zsk(self) -> bool: return self.get_metadata("ZSK") == "yes" + @property + def algorithm(self) -> Algorithm: + num = int(self.get_metadata("Algorithm")) + return ALL_ALGORITHMS_BY_NUM[num] + def dnskey_equals(self, value, cdnskey=False): dnskey = value.split() @@ -955,6 +961,19 @@ def check_cds(rrset, keys): assert numcds == len(cdss) +def check_cdslog(server, zone, key, substr): + with server.watch_log_from_start() as watcher: + watcher.wait_for_line( + f"{substr} for key {zone}/{key.algorithm.name}/{key.tag} is now published" + ) + + +def check_cdslog_prohibit(server, zone, key, substr): + server.log.prohibit( + f"{substr} for key {zone}/{key.algorithm.name}/{key.tag} is now published" + ) + + def _query_rrset(server, fqdn, qtype, tsig=None): response = _query(server, fqdn, qtype, tsig=tsig) assert response.rcode() == dns.rcode.NOERROR diff --git a/bin/tests/system/isctest/vars/algorithms.py b/bin/tests/system/isctest/vars/algorithms.py index 26bcc579f8..446ab09d69 100644 --- a/bin/tests/system/isctest/vars/algorithms.py +++ b/bin/tests/system/isctest/vars/algorithms.py @@ -90,6 +90,8 @@ ALL_ALGORITHMS = [ ED448, ] +ALL_ALGORITHMS_BY_NUM = {alg.number: alg for alg in ALL_ALGORITHMS} + ALGORITHM_SETS = { "stable": AlgorithmSet( default=ECDSAP256SHA256, alternative=RSASHA256, disabled=ECDSAP384SHA384 diff --git a/bin/tests/system/kasp/ns3/named-fips.conf.in b/bin/tests/system/kasp/ns3/named-fips.conf.in index 8368c4822e..dbbc6e0f37 100644 --- a/bin/tests/system/kasp/ns3/named-fips.conf.in +++ b/bin/tests/system/kasp/ns3/named-fips.conf.in @@ -324,30 +324,6 @@ zone "zsk-retired.autosign" { dnssec-policy "autosign"; }; -/* - * Zones for testing enabling DNSSEC. - */ -zone "step1.enable-dnssec.autosign" { - type primary; - file "step1.enable-dnssec.autosign.db"; - dnssec-policy "enable-dnssec"; -}; -zone "step2.enable-dnssec.autosign" { - type primary; - file "step2.enable-dnssec.autosign.db"; - dnssec-policy "enable-dnssec"; -}; -zone "step3.enable-dnssec.autosign" { - type primary; - file "step3.enable-dnssec.autosign.db"; - dnssec-policy "enable-dnssec"; -}; -zone "step4.enable-dnssec.autosign" { - type primary; - file "step4.enable-dnssec.autosign.db"; - dnssec-policy "enable-dnssec"; -}; - /* * Zones for testing ZSK Pre-Publication steps. */ diff --git a/bin/tests/system/kasp/ns3/policies/autosign.conf.in b/bin/tests/system/kasp/ns3/policies/autosign.conf.in index bc3b7e11dd..062885ad24 100644 --- a/bin/tests/system/kasp/ns3/policies/autosign.conf.in +++ b/bin/tests/system/kasp/ns3/policies/autosign.conf.in @@ -25,26 +25,6 @@ dnssec-policy "autosign" { }; }; -dnssec-policy "enable-dnssec" { - - signatures-refresh P1W; - signatures-validity P2W; - signatures-validity-dnskey P2W; - - dnskey-ttl 300; - max-zone-ttl PT12H; - zone-propagation-delay PT5M; - retire-safety PT20M; - publish-safety PT5M; - - parent-propagation-delay 1h; - parent-ds-ttl 2h; - - keys { - csk lifetime unlimited algorithm @DEFAULT_ALGORITHM_NUMBER@; - }; -}; - dnssec-policy "zsk-prepub" { signatures-refresh P1W; diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index 7eeb248838..827bca18c0 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -281,75 +281,6 @@ oldtimes="-P $T2 -A $T2 -I $T1 -D $T1" OLD=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $oldtimes $zone 2>keygen.out.$zone.3) $SETTIME -s -g $H -k $H $T1 -z $H $T1 "$OLD" >settime.out.$zone.3 2>&1 -# -# The zones at enable-dnssec.autosign represent the various steps of the -# initial signing of a zone. -# - -# Step 1: -# This is an unsigned zone and named should perform the initial steps of -# introducing the DNSSEC records in the right order. -setup step1.enable-dnssec.autosign -cp template.db.in $zonefile - -# Step 2: -# The DNSKEY has been published long enough to become OMNIPRESENT. -setup step2.enable-dnssec.autosign -# DNSKEY TTL: 300 seconds -# zone-propagation-delay: 5 minutes (300 seconds) -# publish-safety: 5 minutes (300 seconds) -# Total: 900 seconds -TpubN="now-900s" -# RRSIG TTL: 12 hour (43200 seconds) -# zone-propagation-delay: 5 minutes (300 seconds) -# Already passed time: -900 seconds -# Total: 42600 seconds -TsbmN="now+42600s" -keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" -CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 3: -# The zone signatures have been published long enough to become OMNIPRESENT. -setup step3.enable-dnssec.autosign -# Passed time since publications: 42600 + 900 = 43500 seconds. -TpubN="now-43500s" -# The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT. -TcotN="now-42600s" -# We can submit the DS now. -TsbmN="now" -keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" -CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TcotN -r $O $TcotN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 4: -# The DS has been submitted long enough ago to become OMNIPRESENT. -setup step4.enable-dnssec.autosign -# DS TTL: 2 hour (7200 seconds) -# parent-propagation-delay: 1 hour (3600 seconds) -# retire-safety: 20 minutes (1200 seconds) -# Total aditional time: 12000 seconds -# 44700 + 12000 = 56700 -TpubN="now-56700s" -# 43800 + 12000 = 55800 -TcotN="now-55800s" -TsbmN="now-12000s" -keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" -CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -P ds $TsbmN -k $O $TcotN -r $O $TcotN -d $R $TsbmN -z $O $TsbmN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - # # The zones at zsk-prepub.autosign represent the various steps of a ZSK # Pre-Publication rollover. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 2aa7f547da..5c2a2aaf64 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -206,55 +206,6 @@ set_keytimes_autosign_policy() { set_addkeytime "KEY2" "REMOVED" "${retired}" 695100 } -# -# Testing DNSSEC introduction. -# - -# -# Zone: step1.enable-dnssec.autosign. -# -set_zone "step1.enable-dnssec.autosign" -set_policy "enable-dnssec" "1" "300" -set_server "ns3" "10.53.0.3" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# The DNSKEY and signatures are introduced first, the DS remains hidden. -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" -# This policy lists only one key (CSK). -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The first key is immediately published and activated. -created=$(key_get KEY1 CREATED) -set_keytime "KEY1" "PUBLISHED" "${created}" -set_keytime "KEY1" "ACTIVE" "${created}" -# - The DS can be published if the DNSKEY and RRSIG records are -# OMNIPRESENT. This happens after max-zone-ttl (12h) plus -# plus zone-propagation-delay (5m) = -# 43200 + 300 = 43500. -set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43500 -# - Key lifetime is unlimited, so not setting RETIRED and REMOVED. - -# Various signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - _check_next_key_event() { _expect=$1 @@ -290,110 +241,6 @@ check_next_key_event() { } -# Next key event is when the DNSKEY RRset becomes OMNIPRESENT: DNSKEY TTL plus -# publish safety plus the zone propagation delay: 900 seconds. -check_next_key_event 900 - -# -# Zone: step2.enable-dnssec.autosign. -# -set_zone "step2.enable-dnssec.autosign" -set_policy "enable-dnssec" "1" "300" -set_server "ns3" "10.53.0.3" -# The DNSKEY is omnipresent, but the zone signatures not yet. -# Thus, the DS remains hidden. -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The key was published and activated 900 seconds ago (with settime). -created=$(key_get KEY1 CREATED) -set_addkeytime "KEY1" "PUBLISHED" "${created}" -900 -set_addkeytime "KEY1" "ACTIVE" "${created}" -900 -set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 42600 - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl -# plus zone propagation delay plus retire safety minus the already elapsed -# 900 seconds: 12h + 300s + 20m - 900 = 43500 - 900 = 42600 seconds -check_next_key_event 42600 - -# -# Zone: step3.enable-dnssec.autosign. -# -set_zone "step3.enable-dnssec.autosign" -set_policy "enable-dnssec" "1" "300" -set_server "ns3" "10.53.0.3" -# All signatures should be omnipresent, so the DS can be submitted. -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "rumoured" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The key was published and activated 43500 seconds ago (with settime). -created=$(key_get KEY1 CREATED) -set_addkeytime "KEY1" "PUBLISHED" "${created}" -43500 -set_addkeytime "KEY1" "ACTIVE" "${created}" -43500 -set_keytime "KEY1" "SYNCPUBLISH" "${created}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify -# Check that CDS publication is logged. -check_cdslog "$DIR" "$ZONE" KEY1 - -# The DS can be introduced. We ignore any parent registration delay, so set -# the DS publish time to now. -rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE" -# Next key event is when the DS can move to the OMNIPRESENT state. This occurs -# when the parent propagation delay have passed, plus the DS TTL and retire -# safety delay: 1h + 2h = 3h = 10800 seconds -check_next_key_event 10800 - -# -# Zone: step4.enable-dnssec.autosign. -# -set_zone "step4.enable-dnssec.autosign" -set_policy "enable-dnssec" "1" "300" -set_server "ns3" "10.53.0.3" -# The DS is omnipresent. -set_keystate "KEY1" "STATE_DS" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The key was published and activated 56700 seconds ago (with settime). -created=$(key_get KEY1 CREATED) -set_addkeytime "KEY1" "PUBLISHED" "${created}" -56700 -set_addkeytime "KEY1" "ACTIVE" "${created}" -56700 -set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" -12000 - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is never, the zone dnssec-policy has been established. So we -# fall back to the default loadkeys interval. -check_next_key_event 3600 - # # Testing ZSK Pre-Publication rollover. # diff --git a/bin/tests/system/rollover/ns3/kasp.conf.j2 b/bin/tests/system/rollover/ns3/kasp.conf.j2 index 2ab26877f0..f432cfc6c0 100644 --- a/bin/tests/system/rollover/ns3/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns3/kasp.conf.j2 @@ -29,3 +29,22 @@ dnssec-policy "multisigner-model2" { zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535; }; }; + +dnssec-policy "enable-dnssec" { + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 300; + max-zone-ttl PT12H; + zone-propagation-delay PT5M; + retire-safety PT20M; + publish-safety PT5M; + + parent-propagation-delay 1h; + parent-ds-ttl 2h; + + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM_NUMBER@; + }; +}; diff --git a/bin/tests/system/rollover/ns3/named.conf.j2 b/bin/tests/system/rollover/ns3/named.conf.j2 index 573865d1b9..c65404a8ca 100644 --- a/bin/tests/system/rollover/ns3/named.conf.j2 +++ b/bin/tests/system/rollover/ns3/named.conf.j2 @@ -67,3 +67,27 @@ zone "single-to-multisigner.kasp" { dnssec-policy "multisigner-model2"; allow-update { any; }; }; + +/* + * Zones for testing enabling DNSSEC. + */ +zone "step1.enable-dnssec.autosign" { + type primary; + file "step1.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step2.enable-dnssec.autosign" { + type primary; + file "step2.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step3.enable-dnssec.autosign" { + type primary; + file "step3.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; +zone "step4.enable-dnssec.autosign" { + type primary; + file "step4.enable-dnssec.autosign.db"; + dnssec-policy "enable-dnssec"; +}; diff --git a/bin/tests/system/rollover/ns3/setup.sh b/bin/tests/system/rollover/ns3/setup.sh index 969b6a7e6c..ac6a47924c 100644 --- a/bin/tests/system/rollover/ns3/setup.sh +++ b/bin/tests/system/rollover/ns3/setup.sh @@ -79,3 +79,64 @@ cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" $SIGNER -PS -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}" $infile >signer.out.$zone.1 2>&1 echo "Lifetime: 0" >>"${KSK}".state echo "Lifetime: 0" >>"${ZSK}".state + +# +# The zones at enable-dnssec.autosign represent the various steps of the +# initial signing of a zone. +# + +# Step 1: +# This is an unsigned zone and named should perform the initial steps of +# introducing the DNSSEC records in the right order. +setup step1.enable-dnssec.autosign +cp template.db.in $zonefile + +# Step 2: +# The DNSKEY has been published long enough to become OMNIPRESENT. +setup step2.enable-dnssec.autosign +# DNSKEY TTL: 300 seconds +# zone-propagation-delay: 5 minutes (300 seconds) +# publish-safety: 5 minutes (300 seconds) +# Total: 900 seconds +TpubN="now-900s" +keytimes="-P ${TpubN} -A ${TpubN}" +CSK=$($KEYGEN -k enable-dnssec -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures have been published long enough to become OMNIPRESENT. +setup step3.enable-dnssec.autosign +# Passed time since publication: +# max-zone-ttl: 12 hours (43200 seconds) +# zone-propagation-delay: 5 minutes (300 seconds) +TpubN="now-43500s" +# We can submit the DS now. +keytimes="-P ${TpubN} -A ${TpubN}" +CSK=$($KEYGEN -k enable-dnssec -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TpubN -r $O $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS has been submitted long enough ago to become OMNIPRESENT. +setup step4.enable-dnssec.autosign +# DS TTL: 2 hour (7200 seconds) +# parent-propagation-delay: 1 hour (3600 seconds) +# Total aditional time: 10800 seconds +# 43500 + 10800 = 54300 +TpubN="now-54300s" +TsbmN="now-10800s" +keytimes="-P ${TpubN} -A ${TpubN} -P sync ${TsbmN}" +CSK=$($KEYGEN -k enable-dnssec -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -P ds $TsbmN -k $O $TpubN -r $O $TpubN -d $R $TpubN -z $O $TsbmN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index a055639d36..05e1e9753c 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -382,3 +382,134 @@ def test_rollover_multisigner(servers): isctest.kasp.check_apex(server, zone, ksks, zsks) isctest.kasp.check_subdomain(server, zone, ksks, zsks) isctest.kasp.check_dnssec_verify(server, zone) + + +def check_rollover_step(server, zone, config, policy, keyprops, nextev): + ttl = int(config["dnskey-ttl"].total_seconds()) + expected = isctest.kasp.policy_to_properties(ttl, keyprops) + isctest.kasp.check_zone_is_signed(server, zone) + keys = isctest.kasp.keydir_to_keylist(zone, server.identifier) + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + isctest.kasp.check_keys(zone, keys, expected) + + for kp in expected: + kp.set_expected_keytimes(config) + + # Check that CDS publication/withdrawal is logged. + if "KSK" not in kp.metadata: + continue + if kp.metadata["KSK"] == "no": + continue + key = kp.key + + if kp.metadata["DSState"] == "rumoured": + isctest.kasp.check_cdslog(server, zone, key, "CDS (SHA-256)") + isctest.kasp.check_cdslog(server, zone, key, "CDNSKEY") + isctest.kasp.check_cdslog_prohibit(server, zone, key, "CDS (SHA-384)") + + # The DS can be introduced. We ignore any parent registration delay, + # so set the DS publish time to now. + server.rndc(f"dnssec -checkds -key {key.tag} published {zone}") + + if kp.metadata["DSState"] == "unretentive": + # The DS can be withdrawn. We ignore any parent registration + # delay, so set the DS withdraw time to now. + server.rndc(f"dnssec -checkds -key {key.tag} withdrawn {zone}") + + isctest.kasp.check_keytimes(keys, expected) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy) + isctest.kasp.check_apex(server, zone, ksks, zsks) + isctest.kasp.check_subdomain(server, zone, ksks, zsks) + isctest.kasp.check_dnssec_verify(server, zone) + + def check_next_key_event(): + return isctest.kasp.next_key_event_equals(server, zone, nextev) + + isctest.run.retry_with_timeout(check_next_key_event, timeout=5) + + +def test_rollover_enable_dnssec(servers): + server = servers["ns3"] + policy = "enable-dnssec" + config = { + "dnskey-ttl": timedelta(seconds=300), + "ds-ttl": timedelta(hours=2), + "max-zone-ttl": timedelta(hours=12), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(minutes=5), + "retire-safety": timedelta(minutes=20), + "signatures-refresh": timedelta(days=7), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), + } + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + + ipub = Ipub(config) + ipubC = IpubC(config, rollover=False) + iretZSK = Iret(config, rollover=False) + iretKSK = Iret(config, zsk=False, ksk=True, rollover=False) + offsets = { + "step1": 0, + "step2": -int(ipub.total_seconds()), + "step3": -int(iretZSK.total_seconds()), + "step4": -int(ipubC.total_seconds() + iretKSK.total_seconds()), + } + + steps = [ + { + # Step 1. + "zone": "step1.enable-dnssec.autosign", + "keyprops": [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{offsets['step1']}", + ], + # Next key event is when the DNSKEY RRset becomes OMNIPRESENT, + # after the publication interval. + "nextev": ipub, + }, + { + # Step 2. + "zone": "step2.enable-dnssec.autosign", + # The DNSKEY is omnipresent, but the zone signatures not yet. + # Thus, the DS remains hidden. + # dnskey: rumoured -> omnipresent + # krrsig: rumoured -> omnipresent + "keyprops": [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{offsets['step2']}", + ], + # Next key event is when the zone signatures become OMNIPRESENT, + # Minus the time already elapsed. + "nextev": iretZSK - ipub, + }, + { + # Step 3. + "zone": "step3.enable-dnssec.autosign", + # All signatures should be omnipresent, so the DS can be submitted. + # zrrsig: rumoured -> omnipresent + # ds: hidden -> rumoured + "keyprops": [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{offsets['step3']}", + ], + # Next key event is when the DS can move to the OMNIPRESENT state. + # This is after the retire interval. + "nextev": iretKSK, + }, + { + # Step 4. + "zone": "step4.enable-dnssec.autosign", + # DS has been published long enough. + # ds: rumoured -> omnipresent + "keyprops": [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step4']}", + ], + # Next key event is never, the zone dnssec-policy has been + # established. So we fall back to the default loadkeys interval. + "nextev": timedelta(hours=1), + }, + ] + + for step in steps: + check_rollover_step( + server, step["zone"], config, policy, step["keyprops"], step["nextev"] + )