diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 537ebce0ba..1aec27c3f5 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -997,6 +997,15 @@ def check_cdslog_prohibit(server, zone, key, substr): ) +def check_cdsdelete(rrset, expected): + numrrs = 0 + for rr in rrset: + for rdata in rr: + assert expected in f"{rdata}" + numrrs += 1 + assert numrrs == 1 + + def _query_rrset(server, fqdn, qtype, tsig=None): response = _query(server, fqdn, qtype, tsig=tsig) assert response.rcode() == dns.rcode.NOERROR @@ -1019,7 +1028,15 @@ def _query_rrset(server, fqdn, qtype, tsig=None): def check_apex( - server, zone, ksks, zsks, cdss=None, offline_ksk=False, zsk_missing=False, tsig=None + server, + zone, + ksks, + zsks, + cdss=None, + cds_delete=False, + offline_ksk=False, + zsk_missing=False, + tsig=None, ): # Test the apex of a zone. This checks that the SOA and DNSKEY RRsets # are signed correctly and with the appropriate keys. @@ -1052,10 +1069,13 @@ def check_apex( # test cdnskey query cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig) - if "CDNSKEY" in cdss: - check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + if cds_delete: + check_cdsdelete(cdnskeys, "0 3 0 AA==") else: - assert len(cdnskeys) == 0 + if "CDNSKEY" in cdss: + check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + else: + assert len(cdnskeys) == 0 if len(cdnskeys) > 0: assert len(rrsigs) > 0 @@ -1065,29 +1085,33 @@ def check_apex( # test cds query cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig) - cdsrrs = [] - for rr in cds: - for rdata in rr: - rdclass = dns.rdataclass.to_text(rr.rdclass) - rdtype = dns.rdatatype.to_text(rr.rdtype) - cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" - cdsrrs.append(cds) - numcds = 0 + if cds_delete: + check_cdsdelete(cds, "0 0 0 00") + else: + cdsrrs = [] + for rr in cds: + for rdata in rr: + rdclass = dns.rdataclass.to_text(rr.rdclass) + rdtype = dns.rdatatype.to_text(rr.rdtype) + cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" + cdsrrs.append(cds) - for alg in ["SHA-256", "SHA-384"]: - if f"CDS ({alg})" in cdss: - numcds += check_cds(cdsrrs, ksks, alg) - else: - check_cds_prohibit(cdsrrs, ksks, alg) + numcds = 0 - if len(cds) > 0: - assert len(rrsigs) > 0 - check_signatures( - rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk - ) + for alg in ["SHA-256", "SHA-384"]: + if f"CDS ({alg})" in cdss: + numcds += check_cds(cdsrrs, ksks, alg) + else: + check_cds_prohibit(cdsrrs, ksks, alg) - assert numcds == len(cdsrrs) + if len(cds) > 0: + assert len(rrsigs) > 0 + check_signatures( + rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) + + assert numcds == len(cdsrrs) def check_subdomain( diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in index f77069fdb3..df02890922 100644 --- a/bin/tests/system/kasp/ns6/named.conf.in +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -44,35 +44,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* These zones are going insecure. */ -zone "step1.going-insecure.kasp" { - type primary; - file "step1.going-insecure.kasp.db"; - dnssec-policy "unsigning"; -}; - -zone "step1.going-insecure-dynamic.kasp" { - type primary; - file "step1.going-insecure-dynamic.kasp.db"; - dnssec-policy "unsigning"; - inline-signing no; - allow-update { any; }; -}; - -zone "step1.going-straight-to-none.kasp" { - type primary; - file "step1.going-straight-to-none.kasp.db"; - dnssec-policy "default"; -}; - -zone "step1.going-straight-to-none-dynamic.kasp" { - type primary; - file "step1.going-straight-to-none-dynamic.kasp.db.signed"; - inline-signing no; - dnssec-policy "default"; - allow-update { any; }; -}; - /* These are alorithm rollover test zones. */ zone "step1.algorithm-roll.kasp" { type primary; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in index 88e67dc371..83af019480 100644 --- a/bin/tests/system/kasp/ns6/named2.conf.in +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -43,49 +43,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* Zones for testing going insecure. */ -zone "step1.going-insecure.kasp" { - type primary; - file "step1.going-insecure.kasp.db"; - dnssec-policy "insecure"; -}; - -zone "step2.going-insecure.kasp" { - type primary; - file "step2.going-insecure.kasp.db"; - dnssec-policy "insecure"; -}; - -zone "step1.going-insecure-dynamic.kasp" { - type primary; - file "step1.going-insecure-dynamic.kasp.db"; - inline-signing no; - dnssec-policy "insecure"; - allow-update { any; }; -}; - -zone "step2.going-insecure-dynamic.kasp" { - type primary; - file "step2.going-insecure-dynamic.kasp.db"; - inline-signing no; - dnssec-policy "insecure"; - allow-update { any; }; -}; - -zone "step1.going-straight-to-none.kasp" { - type primary; - file "step1.going-straight-to-none.kasp.db"; - dnssec-policy "none"; -}; - -zone "step1.going-straight-to-none-dynamic.kasp" { - type primary; - file "step1.going-straight-to-none-dynamic.kasp.db.signed"; - inline-signing no; - dnssec-policy "none"; - allow-update { any; }; -}; - /* * Zones for testing KSK/ZSK algorithm roll. */ diff --git a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in index 51c4d88488..4f7db5ad51 100644 --- a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in +++ b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in @@ -11,15 +11,6 @@ * information regarding copyright ownership. */ -dnssec-policy "unsigning" { - dnskey-ttl 7200; - - keys { - ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; - zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; - }; -}; - dnssec-policy "nsec3" { nsec3param iterations 0 optout no salt-length 0; }; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh index 6f963e33d0..306178c7b3 100644 --- a/bin/tests/system/kasp/ns6/setup.sh +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -29,71 +29,6 @@ R="RUMOURED" O="OMNIPRESENT" U="UNRETENTIVE" -# The child zones (step1, step2) beneath these zones represent the various -# steps of unsigning a zone. -for zn in going-insecure.kasp going-insecure-dynamic.kasp; do - # Step 1: - # Set up a zone with dnssec-policy that is going insecure. - setup step1.$zn - echo "$zone" >>zones - T="now-10d" - ksktimes="-P $T -A $T -P sync $T" - zsktimes="-P $T -A $T" - KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) - ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) - cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" - cp $infile $zonefile - $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - - # Step 2: - # Set up a zone with dnssec-policy that is going insecure. Don't add - # this zone to the zones file, because this zone is no longer expected - # to be fully signed. - setup step2.$zn - # The DS was withdrawn from the parent zone 26 hours ago. - Trem="now-26h" - ksktimes="-P $T -A $T -P sync $T" - zsktimes="-P $T -A $T" - KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) - ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) - $SETTIME -s -g $H -k $O $T -r $O $T -d $U $Trem -D ds $Trem "$KSK" >settime.out.$zone.1 2>&1 - $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 - # Fake lifetime of old algorithm keys. - echo "Lifetime: 0" >>"${KSK}.state" - echo "Lifetime: 5184000" >>"${ZSK}.state" - cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" - cp $infile $zonefile - $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 -done - -# This zone is going straight to "none" policy. This is undefined behavior. -setup step1.going-straight-to-none.kasp -echo "$zone" >>zones -TactN="now" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$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+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# This zone is going straight to "none" policy. This is undefined behavior. -setup step1.going-straight-to-none-dynamic.kasp -echo "$zone" >>zones -TactN="now" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$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+2w -o $zone -O full -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - # # The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK # algorithm rollover. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 069f8a32b0..28d182a607 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -372,166 +372,6 @@ dnssec_verify # interval. check_next_key_event 3600 -# -# Testing going insecure. -# - -# -# Zone step1.going-insecure.kasp -# -set_zone "step1.going-insecure.kasp" -set_policy "unsigning" "2" "7200" -set_server "ns6" "10.53.0.6" - -# Policy parameters. -# Lksk: 0 -# Lzsk: 60 days (5184000 seconds) -# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (1h) -# Iret(KSK): 1d2h (93600 seconds) -# Iret(ZSK): RRSIG TTL (1d) + Dprp (5m) + Dsgn (9d) + retire-safety (1h) -# Iret(ZSK): 10d1h5m (867900 seconds) -Lksk=0 -Lzsk=5184000 -IretKSK=93600 -IretZSK=867900 - -init_migration_insecure() { - key_clear "KEY1" - set_keyrole "KEY1" "ksk" - set_keylifetime "KEY1" "${Lksk}" - set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" - set_keysigning "KEY1" "yes" - set_zonesigning "KEY1" "no" - - set_keystate "KEY1" "GOAL" "omnipresent" - set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" - set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" - set_keystate "KEY1" "STATE_DS" "omnipresent" - - key_clear "KEY2" - set_keyrole "KEY2" "zsk" - set_keylifetime "KEY2" "${Lzsk}" - set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" - set_keysigning "KEY2" "no" - set_zonesigning "KEY2" "yes" - - set_keystate "KEY2" "GOAL" "omnipresent" - set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" - set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" - - key_clear "KEY3" - key_clear "KEY4" -} -init_migration_insecure - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# We have set the timing metadata to now - 10 days (864000 seconds). -rollover_predecessor_keytimes -864000 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-insecure-dynamic.kasp -# - -set_zone "step1.going-insecure-dynamic.kasp" -set_dynamic -set_policy "unsigning" "2" "7200" -set_server "ns6" "10.53.0.6" -init_migration_insecure - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# We have set the timing metadata to now - 10 days (864000 seconds). -rollover_predecessor_keytimes -864000 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-straight-to-none.kasp -# -set_zone "step1.going-straight-to-none.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# 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" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# The first key is immediately published and activated. -created=$(key_get KEY1 CREATED) -set_keytime "KEY1" "PUBLISHED" "${created}" -set_keytime "KEY1" "ACTIVE" "${created}" -set_keytime "KEY1" "SYNCPUBLISH" "${created}" -# Key lifetime is unlimited, so not setting RETIRED and REMOVED. -check_keytimes - -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-straight-to-none-dynamic.kasp -# -set_zone "step1.going-straight-to-none-dynamic.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# 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" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# The first key is immediately published and activated. -created=$(key_get KEY1 CREATED) -set_keytime "KEY1" "PUBLISHED" "${created}" -set_keytime "KEY1" "ACTIVE" "${created}" -set_keytime "KEY1" "SYNCPUBLISH" "${created}" -# Key lifetime is unlimited, so not setting RETIRED and REMOVED. -check_keytimes - -check_apex -check_subdomain -dnssec_verify - # Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy # changes). echo_i "reconfig dnssec-policy to trigger algorithm rollover" @@ -581,206 +421,6 @@ wait_for_done_signing() { status=$((status + ret)) } -# -# Testing going insecure. -# - -# -# Zone: step1.going-insecure.kasp -# -set_zone "step1.going-insecure.kasp" -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" -# Expect a CDS/CDNSKEY Delete Record. -set_cdsdelete - -# Key goal states should be HIDDEN. -init_migration_insecure -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY2" "GOAL" "hidden" -# The DS may be removed if we are going insecure. -set_keystate "KEY1" "STATE_DS" "unretentive" - -# Various signing policy checks. -check_keys -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Tell named that the DS has been removed. -rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the DS becomes HIDDEN. This happens after the -# parent propagation delay, and DS TTL: -# 1h + 1d = 25h = 90000 seconds. -check_next_key_event 90000 - -# -# Zone: step2.going-insecure.kasp -# -set_zone "step2.going-insecure.kasp" -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" - -# The DS is long enough removed from the zone to be considered HIDDEN. -# This means the DNSKEY and the KSK signatures can be removed. -set_keystate "KEY1" "STATE_DS" "hidden" -set_keystate "KEY1" "STATE_DNSKEY" "unretentive" -set_keystate "KEY1" "STATE_KRRSIG" "unretentive" -set_keysigning "KEY1" "no" - -set_keystate "KEY2" "STATE_DNSKEY" "unretentive" -set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" -set_zonesigning "KEY2" "no" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -# Next key event is when the DNSKEY becomes HIDDEN. This happens after the -# propagation delay, plus DNSKEY TTL: -# 5m + 2h = 125m = 7500 seconds. -check_next_key_event 7500 - -# -# Zone: step1.going-insecure-dynamic.kasp -# -set_zone "step1.going-insecure-dynamic.kasp" -set_dynamic -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" -# Expect a CDS/CDNSKEY Delete Record. -set_cdsdelete - -# Key goal states should be HIDDEN. -init_migration_insecure -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY2" "GOAL" "hidden" -# The DS may be removed if we are going insecure. -set_keystate "KEY1" "STATE_DS" "unretentive" - -# Various signing policy checks. -check_keys -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Tell named that the DS has been removed. -rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the DS becomes HIDDEN. This happens after the -# parent propagation delay, retire safety delay, and DS TTL: -# 1h + 1d = 25h = 90000 seconds. -check_next_key_event 90000 - -# -# Zone: step2.going-insecure-dynamic.kasp -# -set_zone "step2.going-insecure-dynamic.kasp" -set_dynamic -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" - -# The DS is long enough removed from the zone to be considered HIDDEN. -# This means the DNSKEY and the KSK signatures can be removed. -set_keystate "KEY1" "STATE_DS" "hidden" -set_keystate "KEY1" "STATE_DNSKEY" "unretentive" -set_keystate "KEY1" "STATE_KRRSIG" "unretentive" -set_keysigning "KEY1" "no" - -set_keystate "KEY2" "STATE_DNSKEY" "unretentive" -set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" -set_zonesigning "KEY2" "no" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -# Next key event is when the DNSKEY becomes HIDDEN. This happens after the -# propagation delay, plus DNSKEY TTL: -# 5m + 2h = 125m = 7500 seconds. -check_next_key_event 7500 - -# -# Zone: step1.going-straight-to-none.kasp -# -set_zone "step1.going-straight-to-none.kasp" -set_policy "none" "1" "3600" -set_server "ns6" "10.53.0.6" - -# The zone will go bogus after signatures expire, but remains validly signed for now. - -# 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" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -dnssec_verify - -# -# Zone: step1.going-straight-to-none-dynamic.kasp -# -set_zone "step1.going-straight-to-none-dynamic.kasp" -set_policy "none" "1" "3600" -set_server "ns6" "10.53.0.6" - -# The zone will go bogus after signatures expire, but remains validly signed for now. - -# 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" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -dnssec_verify - # # Testing KSK/ZSK algorithm rollover. # diff --git a/bin/tests/system/rollover/ns6/kasp.conf.j2 b/bin/tests/system/rollover/ns6/kasp.conf.j2 index 38a1784acf..73f0d5789a 100644 --- a/bin/tests/system/rollover/ns6/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns6/kasp.conf.j2 @@ -28,6 +28,15 @@ dnssec-policy "long-lifetime" { }; }; +dnssec-policy "unsigning" { + dnskey-ttl 7200; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; + }; +}; + {% if RSASHA1_SUPPORTED == "1" %} dnssec-policy "rsasha1" { signatures-refresh P5D; diff --git a/bin/tests/system/rollover/ns6/named.conf.j2 b/bin/tests/system/rollover/ns6/named.conf.j2 index 03432878fe..917281ea84 100644 --- a/bin/tests/system/rollover/ns6/named.conf.j2 +++ b/bin/tests/system/rollover/ns6/named.conf.j2 @@ -76,3 +76,32 @@ zone unlimit-lifetime { file "unlimit-lifetime.db"; dnssec-policy short-lifetime; }; + +/* These zones are going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "unsigning"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + dnssec-policy "unsigning"; + inline-signing no; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "default"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "default"; + allow-update { any; }; +}; diff --git a/bin/tests/system/rollover/ns6/named2.conf.j2 b/bin/tests/system/rollover/ns6/named2.conf.j2 index b0cb1b6949..21b721508e 100644 --- a/bin/tests/system/rollover/ns6/named2.conf.j2 +++ b/bin/tests/system/rollover/ns6/named2.conf.j2 @@ -75,3 +75,46 @@ zone unlimit-lifetime { file "unlimit-lifetime.db"; dnssec-policy unlimited-lifetime; }; + +/* Zones for testing going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step2.going-insecure.kasp" { + type primary; + file "step2.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step2.going-insecure-dynamic.kasp" { + type primary; + file "step2.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "none"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "none"; + allow-update { any; }; +}; diff --git a/bin/tests/system/rollover/ns6/setup.sh b/bin/tests/system/rollover/ns6/setup.sh index f8ab6048e9..0f58df983c 100644 --- a/bin/tests/system/rollover/ns6/setup.sh +++ b/bin/tests/system/rollover/ns6/setup.sh @@ -34,3 +34,68 @@ for zn in dynamic2inline.kasp shorter-lifetime longer-lifetime limit-lifetime \ setup $zn cp template.db.in $zonefile done + +# The child zones (step1, step2) beneath these zones represent the various +# steps of unsigning a zone. +for zn in going-insecure.kasp going-insecure-dynamic.kasp; do + # Step 1: + # Set up a zone with dnssec-policy that is going insecure. + setup step1.$zn + echo "$zone" >>zones + T="now-10d" + S="now-12955mi" + keytimes="-P $T -A $T" + cdstimes="-P sync $S" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2) + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + + # Step 2: + # Set up a zone with dnssec-policy that is going insecure. Don't add + # this zone to the zones file, because this zone is no longer expected + # to be fully signed. + setup step2.$zn + # The DS was withdrawn from the parent zone 26 hours ago. + D="now-26h" + keytimes="-P $T -A $T -I $D -D now" + cdstimes="-P sync $S -D sync $D" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2) + $SETTIME -s -g $H -k $O $T -r $O $T -d $U $D -D ds $D "$KSK" >settime.out.$zone.1 2>&1 + $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 + # Fake lifetime of old algorithm keys. + echo "Lifetime: 0" >>"${KSK}.state" + echo "Lifetime: 5184000" >>"${ZSK}.state" + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +done + +# These zones are going straight to "none" policy. This is undefined behavior. +T="now-10d" +S="now-12955mi" +csktimes="-P $T -A $T -P sync $S" + +setup step1.going-straight-to-none.kasp +echo "$zone" >>zones +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$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+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +setup step1.going-straight-to-none-dynamic.kasp +echo "$zone" >>zones +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$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+2w -o $zone -O full -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 2d9f8275bb..1331591f53 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -387,18 +387,25 @@ def check_rollover_step(server, config, policy, step): keyrelationships = step.get("keyrelationships", None) smooth = step.get("smooth", False) ds_swap = step.get("ds-swap", True) + cds_delete = step.get("cds-delete", False) + check_keytimes = step.get("check-keytimes", True) + zone_signed = step.get("zone-signed", True) isctest.log.info(f"check rollover step {zone}") + if zone_signed: + isctest.kasp.check_dnssec_verify(server, zone) + ttl = int(config["dnskey-ttl"].total_seconds()) expected = isctest.kasp.policy_to_properties(ttl, keyprops) - isctest.kasp.check_dnssec_verify(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: + key = kp.key + # Set expected key timing metadata. kp.set_expected_keytimes(config) @@ -410,12 +417,19 @@ def check_rollover_step(server, config, policy, step): expected[suc].metadata["Predecessor"] = expected[prd].key.tag isctest.kasp.check_keyrelationships(keys, expected) + # Policy changes may retire keys, set expected timing metadata. + if kp.metadata["GoalState"] == "hidden" and "Retired" not in kp.timing: + retired = kp.key.get_timing("Inactive") + kp.timing["Retired"] = retired + kp.timing["Removed"] = retired + Iret( + config, zsk=key.is_zsk(), ksk=key.is_ksk() + ) + # Check that CDS publication/withdrawal is logged. if "KSK" not in kp.metadata: continue if kp.metadata["KSK"] == "no": continue - key = kp.key if ds_swap and kp.metadata["DSState"] == "rumoured": assert cdss is not None @@ -434,9 +448,11 @@ def check_rollover_step(server, config, policy, step): # 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) + if check_keytimes: + isctest.kasp.check_keytimes(keys, expected) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy) - isctest.kasp.check_apex(server, zone, ksks, zsks, cdss=cdss) + isctest.kasp.check_apex(server, zone, ksks, zsks, cdss=cdss, cds_delete=cds_delete) isctest.kasp.check_subdomain(server, zone, ksks, zsks, smooth=smooth) def check_next_key_event(): @@ -1278,6 +1294,9 @@ def test_rollover_policy_changes(servers): "zone-propagation-delay": timedelta(seconds=300), } + unsigning_config = default_config.copy() + unsigning_config["dnskey-ttl"] = timedelta(seconds=7200) + start_time = KeyTimingMetadata.now() # Test dynamic zones that switch to inline-signing. @@ -1299,6 +1318,7 @@ def test_rollover_policy_changes(servers): lifetime = { "P1Y": int(timedelta(days=365).total_seconds()), "P6M": int(timedelta(days=31 * 6).total_seconds()), + "P60D": int(timedelta(days=60).total_seconds()), } lifetime_update_tests = [ { @@ -1335,6 +1355,47 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test going insecure. + isctest.log.info("check going insecure") + offset = -timedelta(days=10) + offval = int(offset.total_seconds()) + zones = [ + "step1.going-insecure.kasp", + "step1.going-insecure-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": unsigning_config, + "policy": "unsigning", + "keyprops": [ + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + + # Test going straight to none. + isctest.log.info("check going straight to none") + zones = [ + "step1.going-straight-to-none.kasp", + "step1.going-straight-to-none-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": default_config, + "policy": "default", + "keyprops": [ + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + for step in steps: check_rollover_step(server, step["config"], step["policy"], step) @@ -1385,5 +1446,77 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test going insecure (after reconfig). + isctest.log.info("check going insecure (after reconfig)") + oldttl = unsigning_config["dnskey-ttl"] + offset = -timedelta(days=10) + offval = int(offset.total_seconds()) + zones = ["going-insecure.kasp", "going-insecure-dynamic.kasp"] + for parent in zones: + # Step 1. + # Key goal states should be HIDDEN. + # The DS may be removed if we are going insecure. + step = { + "zone": f"step1.{parent}", + "cdss": cdss, + "config": default_config, + "policy": "insecure", + "keyprops": [ + f"ksk 0 {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + ], + # Next key event is when the DS becomes HIDDEN. This + # happens after the# parent propagation delay plus DS TTL. + "nextev": default_config["ds-ttl"] + + default_config["parent-propagation-delay"], + # Going insecure, check for CDS/CDNSKEY DELETE, and skip key timing checks. + "cds-delete": True, + "check-keytimes": False, + } + steps.append(step) + + # Step 2. + # The DS is long enough removed from the zone to be considered + # HIDDEN. This means the DNSKEY and the KSK signatures can be + # removed. + step = { + "zone": f"step2.{parent}", + "cdss": cdss, + "config": default_config, + "policy": "insecure", + "keyprops": [ + f"ksk 0 {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:hidden dnskey:unretentive zrrsig:unretentive offset:{offval}", + ], + # Next key event is when the DNSKEY becomes HIDDEN. + # This happens after the propagation delay, plus DNSKEY TTL. + "nextev": oldttl + default_config["zone-propagation-delay"], + # Zone is no longer signed. + "zone-signed": False, + "check-keytimes": False, + } + steps.append(step) + + # Test going straight to none. + isctest.log.info("check going straight to none (after reconfig)") + zones = [ + "step1.going-straight-to-none.kasp", + "step1.going-straight-to-none-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": default_config, + "policy": None, + # These zones will go bogus after signatures expire, but + # remain validly signed for now. + "keyprops": [ + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + for step in steps: check_rollover_step(server, step["config"], step["policy"], step)