diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 5beb8f2632..8233f1807b 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -335,7 +335,7 @@ class Key: return value def get_signing_state( - self, offline_ksk=False, zsk_missing=False + self, offline_ksk=False, zsk_missing=False, smooth=False ) -> Tuple[bool, bool]: """ This returns the signing state derived from the key states, KRRSIGState @@ -348,6 +348,11 @@ class Key: If 'zsk_missing' is set to True, it means the ZSK private key file is missing, and the KSK should take over signing the RRset, and the expected zone signing state (zsigning) is reversed. + + If 'smooth' is set to True, it means a smooth ZSK rollover is + initiated. Signatures are being replaced gradually during a ZSK + rollover, so the existing signatures of the predecessor ZSK are still + being used, thus the predecessor is expected to be signing. """ # Fetch key timing metadata. now = KeyTimingMetadata.now() @@ -364,6 +369,8 @@ class Key: ksigning = krrsigstate in ["rumoured", "omnipresent"] zrrsigstate = self.get_metadata("ZRRSIGState", must_exist=False) zsigning = zrrsigstate in ["rumoured", "omnipresent"] + if smooth: + zsigning = zrrsigstate in ["unretentive", "omnipresent"] if ksigning: assert self.is_ksk() @@ -787,7 +794,7 @@ def check_dnssecstatus(server, zone, keys, policy=None, view=None): def _check_signatures( - signatures, covers, fqdn, keys, offline_ksk=False, zsk_missing=False + signatures, covers, fqdn, keys, offline_ksk=False, zsk_missing=False, smooth=False ): numsigs = 0 zrrsig = True @@ -800,7 +807,7 @@ def _check_signatures( continue ksigning, zsigning = key.get_signing_state( - offline_ksk=offline_ksk, zsk_missing=zsk_missing + offline_ksk=offline_ksk, zsk_missing=zsk_missing, smooth=smooth ) alg = key.get_metadata("Algorithm") @@ -838,7 +845,7 @@ def _check_signatures( def check_signatures( - rrset, covers, fqdn, ksks, zsks, offline_ksk=False, zsk_missing=False + rrset, covers, fqdn, ksks, zsks, offline_ksk=False, zsk_missing=False, smooth=False ): # Check if signatures with covering type are signed with the right keys. # The right keys are the ones that expect a signature and have the @@ -854,10 +861,22 @@ def check_signatures( signatures.append(rrsig) numsigs += _check_signatures( - signatures, covers, fqdn, ksks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + signatures, + covers, + fqdn, + ksks, + offline_ksk=offline_ksk, + zsk_missing=zsk_missing, + smooth=smooth, ) numsigs += _check_signatures( - signatures, covers, fqdn, zsks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + signatures, + covers, + fqdn, + zsks, + offline_ksk=offline_ksk, + zsk_missing=zsk_missing, + smooth=smooth, ) assert numsigs == len(signatures) @@ -1042,7 +1061,9 @@ def check_apex( ) -def check_subdomain(server, zone, ksks, zsks, offline_ksk=False, tsig=None): +def check_subdomain( + server, zone, ksks, zsks, offline_ksk=False, smooth=False, tsig=None +): # Test an RRset below the apex and verify it is signed correctly. fqdn = f"{zone}." qname = f"a.{zone}." @@ -1060,7 +1081,9 @@ def check_subdomain(server, zone, ksks, zsks, offline_ksk=False, tsig=None): else: assert match in rrset.to_text() - check_signatures(rrsigs, qtype, fqdn, ksks, zsks, offline_ksk=offline_ksk) + check_signatures( + rrsigs, qtype, fqdn, ksks, zsks, offline_ksk=offline_ksk, smooth=smooth + ) def verify_update_is_signed(server, fqdn, qname, qtype, rdata, ksks, zsks, tsig=None): diff --git a/bin/tests/system/kasp/ns3/named-fips.conf.in b/bin/tests/system/kasp/ns3/named-fips.conf.in index dbbc6e0f37..9247a12350 100644 --- a/bin/tests/system/kasp/ns3/named-fips.conf.in +++ b/bin/tests/system/kasp/ns3/named-fips.conf.in @@ -324,40 +324,6 @@ zone "zsk-retired.autosign" { dnssec-policy "autosign"; }; -/* - * Zones for testing ZSK Pre-Publication steps. - */ -zone "step1.zsk-prepub.autosign" { - type primary; - file "step1.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; -zone "step2.zsk-prepub.autosign" { - type primary; - file "step2.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; -zone "step3.zsk-prepub.autosign" { - type primary; - file "step3.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; -zone "step4.zsk-prepub.autosign" { - type primary; - file "step4.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; -zone "step5.zsk-prepub.autosign" { - type primary; - file "step5.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; -zone "step6.zsk-prepub.autosign" { - type primary; - file "step6.zsk-prepub.autosign.db"; - dnssec-policy "zsk-prepub"; -}; - /* * Zones for testing KSK Double-KSK steps. */ diff --git a/bin/tests/system/kasp/ns3/policies/autosign.conf.in b/bin/tests/system/kasp/ns3/policies/autosign.conf.in index 062885ad24..29fabc40c8 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 "zsk-prepub" { - - signatures-refresh P1W; - signatures-validity P2W; - signatures-validity-dnskey P2W; - - dnskey-ttl 3600; - publish-safety P1D; - retire-safety P2D; - purge-keys PT1H; - - keys { - ksk key-directory lifetime P2Y algorithm @DEFAULT_ALGORITHM@; - zsk key-directory lifetime P30D algorithm @DEFAULT_ALGORITHM@; - }; - - zone-propagation-delay PT1H; - max-zone-ttl 1d; -}; - dnssec-policy "ksk-doubleksk" { signatures-refresh P1W; diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index 827bca18c0..4e4cc1d808 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -281,268 +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 zsk-prepub.autosign represent the various steps of a ZSK -# Pre-Publication rollover. -# - -# Step 1: -# Introduce the first key. This will immediately be active. -setup step1.zsk-prepub.autosign -TactN="now" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 -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: -# It is time to pre-publish the successor ZSK. -setup step2.zsk-prepub.autosign -# According to RFC 7583: -# -# Tpub(N+1) <= Tact(N) + Lzsk - Ipub -# Ipub = Dprp + TTLkey (+publish-safety) -# -# |3| |4| |5| |6| -# | | | | -# Key N |<-------Lzsk------>| -# | | | | -# Key N+1 | |<-Ipub->|<-->| -# | | | | -# Key N Tact -# Key N+1 Tpub Trdy Tact -# -# Tnow -# -# Lzsk: 30d -# Dprp: 1h -# TTLkey: 1h -# publish-safety: 1d -# Ipub: 26h -# -# Tact(N) = Tnow + Ipub - Lzsk = now + 26h - 30d -# = now + 26h - 30d = now − 694h -TactN="now-694h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 -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 3: -# After the publication interval has passed the DNSKEY of the successor ZSK -# is OMNIPRESENT and the zone can thus be signed with the successor ZSK. -setup step3.zsk-prepub.autosign -# According to RFC 7583: -# -# Tpub(N+1) <= Tact(N) + Lzsk - Ipub -# Tret(N) = Tact(N+1) = Tact(N) + Lzsk -# Trem(N) = Tret(N) + Iret -# Iret = Dsgn + Dprp + TTLsig (+retire-safety) -# -# |3| |4| |5| |6| |7| |8| -# | | | | | | -# Key N |<-------Lzsk------>|<-Iret->|<--->| -# | | | | | | -# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - - -# | | | | | | -# Key N Tact Tret Tdea Trem -# Key N+1 Tpub Trdy Tact -# -# Tnow -# -# Lzsk: 30d -# Ipub: 26h -# Dsgn: 1w -# Dprp: 1h -# TTLsig: 1d -# retire-safety: 2d -# Iret: 10d1h = 241h -# -# Tact(N) = Tnow - Lzsk = now - 30d -# Tret(N) = now -# Trem(N) = Tnow + Iret = now + 241h -# Tpub(N+1) = Tnow - Ipub = now - 26h -# Tret(N+1) = Tnow + Lzsk = now + 30d -# Trem(N+1) = Tnow + Lzsk + Iret = now + 30d + 241h -# = now + 961h -TactN="now-30d" -TretN="now" -TremN="now+241h" -TpubN1="now-26h" -TactN1="now" -TretN1="now+30d" -TremN1="now+961h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -z $H $TpubN1 "$ZSK2" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $ZSK1 $ZSK2 -# Sign zone. -cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 4: -# After the retire interval has passed the predecessor DNSKEY can be -# removed from the zone. -setup step4.zsk-prepub.autosign -# According to RFC 7583: -# -# Tret(N) = Tact(N) + Lzsk -# Tdea(N) = Tret(N) + Iret -# -# |3| |4| |5| |6| |7| |8| -# | | | | | | -# Key N |<-------Lzsk------>|<-Iret->|<--->| -# | | | | | | -# Key N+1 | |<-Ipub->|<-->|<---Lzsk---- - - -# | | | | | | -# Key N Tact Tret Tdea Trem -# Key N+1 Tpub Trdy Tact -# -# Tnow -# -# Lzsk: 30d -# Ipub: 26h -# Iret: 241h -# -# Tact(N) = Tnow - Iret - Lzsk -# = now - 241h - 30d = now - 241h - 720h -# = now - 961h -# Tret(N) = Tnow - Iret = now - 241h -# Trem(N) = Tnow -# Tpub(N+1) = Tnow - Iret - Ipub -# = now - 241h - 26h -# = now - 267h -# Tact(N+1) = Tnow - Iret = Tret(N) -# Tret(N+1) = Tnow - Iret + Lzsk -# = now - 241h + 30d = now - 241h + 720h -# = now + 479h -# Trem(N+1) = Tnow + Lzsk = now + 30d -TactN="now-961h" -TretN="now-241h" -TremN="now" -TpubN1="now-267h" -TactN1="${TretN}" -TretN1="now+479h" -TremN1="now+30d" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $O $TactN -z $U $TretN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -z $R $TactN1 "$ZSK2" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $ZSK1 $ZSK2 -# Sign zone. -cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" -cp $infile $zonefile -$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 5: -# The predecessor DNSKEY is removed long enough that is has become HIDDEN. -setup step5.zsk-prepub.autosign -# Subtract DNSKEY TTL from all the times (1h). -# Tact(N) = now - 961h - 1h = now - 962h -# Tret(N) = now - 241h - 1h = now - 242h -# Tdea(N) = now - 2d - 1h = now - 49h -# Trem(N) = now - 1h -# Tpub(N+1) = now - 267h - 1h = now - 268h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now + 479h - 1h = now + 478h -# Trem(N+1) = now + 30d - 1h = now + 719h -TactN="now-962h" -TretN="now-242h" -TremN="now-1h" -TdeaN="now-49h" -TpubN1="now-268h" -TactN1="${TretN}" -TretN1="now+478h" -TremN1="now+719h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $U $TdeaN -z $H $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $ZSK1 $ZSK2 -# Sign zone. -cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 6: -# The predecessor DNSKEY can be purged. -setup step6.zsk-prepub.autosign -# Subtract purge-keys interval from all the times (1h). -# Tact(N) = now - 962h - 1h = now - 963h -# Tret(N) = now - 242h - 1h = now - 243h -# Tdea(N) = now - 49h - 1h = now - 50h -# Trem(N) = now - 1h - 1h = now - 2h -# Tpub(N+1) = now - 268h - 1h = now - 269h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now + 478h - 1h = now + 477h -# Trem(N+1) = now + 719h - 1h = now + 718h -TactN="now-963h" -TretN="now-243h" -TremN="now-2h" -TdeaN="now-50h" -TpubN1="now-269h" -TactN1="${TretN}" -TretN1="now+477h" -TremN1="now+718h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $H $TdeaN -z $H $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -z $O $TdeaN "$ZSK2" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $ZSK1 $ZSK2 -# Sign zone. -cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 - # # The zones at ksk-doubleksk.autosign represent the various steps of a KSK # Double-KSK rollover. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index ae5f3b9774..26759298b0 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -241,29 +241,6 @@ check_next_key_event() { } -# -# Testing ZSK Pre-Publication rollover. -# - -# Policy parameters. -# Lksk: 2 years (63072000 seconds) -# Lzsk: 30 days (2592000 seconds) -# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (2d) -# Iret(KSK): 3d1h (262800 seconds) -# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d) -# Iret(ZSK): 10d1h (867600 seconds) -Lksk=63072000 -Lzsk=2592000 -IretKSK=262800 -IretZSK=867600 - -# -# Zone: step1.zsk-prepub.autosign. -# -set_zone "step1.zsk-prepub.autosign" -set_policy "zsk-prepub" "2" "3600" -set_server "ns3" "10.53.0.3" - set_retired_removed() { _Lkey=$2 _Iret=$3 @@ -289,231 +266,6 @@ rollover_predecessor_keytimes() { [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}" } -# Key properties. -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" - -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" -# Both KSK (KEY1) and ZSK (KEY2) start in 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" -# Initially only two keys. -key_clear "KEY3" -key_clear "KEY4" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# These keys are immediately published and activated. -rollover_predecessor_keytimes 0 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the successor ZSK needs to be published. That is -# the ZSK lifetime - prepublication time. The prepublication time is DNSKEY -# TTL plus publish safety plus the zone propagation delay. For the -# zsk-prepub policy that means: 30d - 3600s + 1d + 1h = 2498400 seconds. -check_next_key_event 2498400 - -# -# Zone: step2.zsk-prepub.autosign. -# -set_zone "step2.zsk-prepub.autosign" -set_policy "zsk-prepub" "3" "3600" -set_server "ns3" "10.53.0.3" -# New ZSK (KEY3) is prepublished, but not yet signing. -key_clear "KEY3" -set_keyrole "KEY3" "zsk" -set_keylifetime "KEY3" "${Lzsk}" -set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY3" "no" -set_zonesigning "KEY3" "no" -# Key states. -set_keystate "KEY2" "GOAL" "hidden" -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_ZRRSIG" "hidden" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys were activated 694 hours ago (2498400 seconds). -rollover_predecessor_keytimes -2498400 -# - The new ZSK is published now. -created=$(key_get KEY3 CREATED) -set_keytime "KEY3" "PUBLISHED" "${created}" -# - The new ZSK becomes active when the DNSKEY is OMNIPRESENT. -# Ipub: TTLkey (1h) + Dprp (1h) + publish-safety (1d) -# Ipub: 26 hour (93600 seconds). -IpubZSK=93600 -set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubZSK}" -set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the successor ZSK becomes OMNIPRESENT. That is the -# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For -# the zsk-prepub policy, this means: 3600s + 1h + 1d = 93600 seconds. -check_next_key_event 93600 - -# -# Zone: step3.zsk-prepub.autosign. -# -set_zone "step3.zsk-prepub.autosign" -set_policy "zsk-prepub" "3" "3600" -set_server "ns3" "10.53.0.3" -# ZSK (KEY2) no longer is actively signing, RRSIG state in UNRETENTIVE. -# New ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. -set_zonesigning "KEY2" "no" -set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" -set_zonesigning "KEY3" "yes" -set_keystate "KEY3" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY3" "STATE_ZRRSIG" "rumoured" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys are activated 30 days ago (2592000 seconds). -rollover_predecessor_keytimes -2592000 -# - The new ZSK is published 26 hours ago (93600 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -93600 -set_keytime "KEY3" "ACTIVE" "${created}" -set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -# Subdomain still has good signatures of ZSK (KEY2). -# Set expected zone signing on for KEY2 and off for KEY3, -# testing whether signatures which are still valid are being reused. -set_zonesigning "KEY2" "yes" -set_zonesigning "KEY3" "no" -check_subdomain -# Restore the expected zone signing properties. -set_zonesigning "KEY2" "no" -set_zonesigning "KEY3" "yes" -dnssec_verify - -# Next key event is when all the RRSIG records have been replaced with -# signatures of the new ZSK, in other words when ZRRSIG becomes OMNIPRESENT. -# That is Dsgn plus the maximum zone TTL plus the zone propagation delay plus -# retire-safety. For the zsk-prepub policy that means: 1w (because 2w validity -# and refresh within a week) + 1d + 1h + 2d = 10d1h = 867600 seconds. -check_next_key_event 867600 - -# -# Zone: step4.zsk-prepub.autosign. -# -set_zone "step4.zsk-prepub.autosign" -set_policy "zsk-prepub" "3" "3600" -set_server "ns3" "10.53.0.3" -# ZSK (KEY2) DNSKEY is no longer needed. -# ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. -set_keystate "KEY2" "STATE_DNSKEY" "unretentive" -set_keystate "KEY2" "STATE_ZRRSIG" "hidden" -set_keystate "KEY3" "STATE_ZRRSIG" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys are activated 961 hours ago (3459600 seconds). -rollover_predecessor_keytimes -3459600 -# - The new ZSK is published 267 hours ago (961200 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -961200 -published=$(key_get KEY3 PUBLISHED) -set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}" -set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the DNSKEY enters the HIDDEN state. This is the -# DNSKEY TTL plus zone propagation delay. For the zsk-prepub policy this is: -# 3600s + 1h = 7200s -check_next_key_event 7200 - -# -# Zone: step5.zsk-prepub.autosign. -# -set_zone "step5.zsk-prepub.autosign" -set_policy "zsk-prepub" "3" "3600" -set_server "ns3" "10.53.0.3" -# ZSK (KEY2) DNSKEY is now completely HIDDEN and removed. -set_keystate "KEY2" "STATE_DNSKEY" "hidden" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys are activated 962 hours ago (3463200 seconds). -rollover_predecessor_keytimes -3463200 -# - The new ZSK is published 268 hours ago (964800 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -964800 -published=$(key_get KEY3 PUBLISHED) -set_addkeytime "KEY3" "ACTIVE" "${published}" "${IpubZSK}" -set_retired_removed "KEY3" "${Lzsk}" "${IretZSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the new successor needs to be published. This is the -# ZSK lifetime minus Iret minus Ipub minus DNSKEY TTL. For the zsk-prepub -# policy this is: 30d - 867600s - 93600s - 3600s = 1627200 seconds. -check_next_key_event 1627200 - -# -# Zone: step6.zsk-prepub.autosign. -# -set_zone "step6.zsk-prepub.autosign" -set_policy "zsk-prepub" "2" "3600" -set_server "ns3" "10.53.0.3" -# ZSK (KEY2) DNSKEY is purged. -key_clear "KEY2" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - # # Testing KSK Double-KSK rollover. # diff --git a/bin/tests/system/rollover/ns3/kasp.conf.j2 b/bin/tests/system/rollover/ns3/kasp.conf.j2 index f432cfc6c0..209d72cb09 100644 --- a/bin/tests/system/rollover/ns3/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns3/kasp.conf.j2 @@ -48,3 +48,22 @@ dnssec-policy "enable-dnssec" { csk lifetime unlimited algorithm @DEFAULT_ALGORITHM_NUMBER@; }; }; + +dnssec-policy "zsk-prepub" { + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 3600; + publish-safety P1D; + retire-safety P2D; + purge-keys PT1H; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P30D algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay PT1H; + max-zone-ttl 1d; +}; diff --git a/bin/tests/system/rollover/ns3/named.conf.j2 b/bin/tests/system/rollover/ns3/named.conf.j2 index c65404a8ca..309014cb1b 100644 --- a/bin/tests/system/rollover/ns3/named.conf.j2 +++ b/bin/tests/system/rollover/ns3/named.conf.j2 @@ -91,3 +91,37 @@ zone "step4.enable-dnssec.autosign" { file "step4.enable-dnssec.autosign.db"; dnssec-policy "enable-dnssec"; }; + +/* + * Zones for testing ZSK Pre-Publication steps. + */ +zone "step1.zsk-prepub.autosign" { + type primary; + file "step1.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step2.zsk-prepub.autosign" { + type primary; + file "step2.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step3.zsk-prepub.autosign" { + type primary; + file "step3.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step4.zsk-prepub.autosign" { + type primary; + file "step4.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step5.zsk-prepub.autosign" { + type primary; + file "step5.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step6.zsk-prepub.autosign" { + type primary; + file "step6.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; diff --git a/bin/tests/system/rollover/ns3/setup.sh b/bin/tests/system/rollover/ns3/setup.sh index ac6a47924c..23920a0ab8 100644 --- a/bin/tests/system/rollover/ns3/setup.sh +++ b/bin/tests/system/rollover/ns3/setup.sh @@ -140,3 +140,180 @@ 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. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.zsk-prepub.autosign +TactN="now-7d" +keytimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +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: +# It is time to pre-publish the successor ZSK. +setup step2.zsk-prepub.autosign +# According to RFC 7583: +# Tact(N) = now + Ipub - Lzsk = now + 26h - 30d +# = now + 26h - 30d = now − 694h +TactN="now-694h" +keytimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +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 3: +# After the publication interval has passed the DNSKEY of the successor ZSK +# is OMNIPRESENT and the zone can thus be signed with the successor ZSK. +setup step3.zsk-prepub.autosign +# According to RFC 7583: +# Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# Tact(N+1) = Tact(N) + Lzsk +# +# Tact(N) = now - Lzsk = now - 30d +# Tpub(N+1) = now - Ipub = now - 26h +# Tact(N+1) = now +# Tret(N) = now +# Trem(N) = now + Iret = now + Dsign + Dprp + TTLsig + retire-safety = 8d1h = now + 241h +TactN="now-30d" +TpubN1="now-26h" +TactN1="now" +TremN="now+241h" +keytimes="-P ${TactN} -A ${TactN}" +oldtimes="-P ${TactN} -A ${TactN} -I ${TactN1} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $oldtimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -z $H $TpubN1 "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 4: +# After the retire interval has passed the predecessor DNSKEY can be +# removed from the zone. +setup step4.zsk-prepub.autosign +# Lzsk: 30d +# Ipub: 26h +# Dsgn: 1w +# Dprp: 1h +# TTLsig: 1d +# retire-safety: 2d +# +# According to RFC 7583: +# Iret = Dsgn + Dprp + TTLsig (+retire-safety) +# Iret = 1w + 1h + 1d + 2d = 10d1h = 241h +# +# Tact(N) = now - Iret - Lzsk +# = now - 241h - 30d = now - 241h - 720h +# = now - 961h +# Tpub(N+1) = now - Iret - Ipub +# = now - 241h - 26h +# = now - 267h +# Tact(N+1) = now - Iret = now - 241h +TactN="now-961h" +TpubN1="now-267h" +TactN1="now-241h" +TremN="now" +keytimes="-P ${TactN} -A ${TactN}" +oldtimes="-P ${TactN} -A ${TactN} -I ${TactN1} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $oldtimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $U $TactN1 "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $R $TactN1 "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +cp $infile $zonefile +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The predecessor DNSKEY is removed long enough that is has become HIDDEN. +setup step5.zsk-prepub.autosign +# Subtract DNSKEY TTL + zone-propagation-delay from all the times (2h). +# Tact(N) = now - 961h - 2h = now - 963h +# Tpub(N+1) = now - 267h - 2h = now - 269h +# Tact(N+1) = now - 241h - 2h = now - 243h +# Trem(N) = Tact(N+1) + Iret = now -2h +TactN="now-963h" +TremN="now-2h" +TpubN1="now-269h" +TactN1="now-243h" +TremN="now-2h" +keytimes="-P ${TactN} -A ${TactN}" +oldtimes="-P ${TactN} -A ${TactN} -I ${TactN1} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $oldtimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $U $TremN -z $H $TremN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $O $TremN "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 6: +# The predecessor DNSKEY can be purged. +setup step6.zsk-prepub.autosign +# Subtract purge-keys interval from all the times (1h). +TactN="now-964h" +TremN="now-3h" +TpubN1="now-270h" +TactN1="now-244h" +TremN="now-3h" +keytimes="-P ${TactN} -A ${TactN}" +oldtimes="-P ${TactN} -A ${TactN} -I ${TactN1} -D ${TremN}" +newtimes="-P ${TpubN1} -A ${TactN1}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $oldtimes $zone 2>keygen.out.$zone.2) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $newtimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $H $TremN -z $H $TremN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -z $O $TremN "$ZSK2" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $ZSK1 $ZSK2 +# Sign zone. +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$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 + + diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index 05e1e9753c..45e252307e 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -384,7 +384,17 @@ def test_rollover_multisigner(servers): isctest.kasp.check_dnssec_verify(server, zone) -def check_rollover_step(server, zone, config, policy, keyprops, nextev): +def check_rollover_step(server, config, policy, step): + zone = step["zone"] + keyprops = step["keyprops"] + nextev = step["nextev"] + keyrelationships = None + if step.get("keyrelationships"): + keyrelationships = step["keyrelationships"] + smooth = False + if step.get("smooth"): + smooth = step["smooth"] + ttl = int(config["dnskey-ttl"].total_seconds()) expected = isctest.kasp.policy_to_properties(ttl, keyprops) isctest.kasp.check_zone_is_signed(server, zone) @@ -394,8 +404,17 @@ def check_rollover_step(server, zone, config, policy, keyprops, nextev): isctest.kasp.check_keys(zone, keys, expected) for kp in expected: + # Set expected key timing metadata. kp.set_expected_keytimes(config) + # Set rollover relationships. + if keyrelationships is not None: + prd = keyrelationships[0] + suc = keyrelationships[1] + expected[prd].metadata["Successor"] = expected[suc].key.tag + expected[suc].metadata["Predecessor"] = expected[prd].key.tag + isctest.kasp.check_keyrelationships(keys, expected) + # Check that CDS publication/withdrawal is logged. if "KSK" not in kp.metadata: continue @@ -420,7 +439,7 @@ def check_rollover_step(server, zone, config, policy, keyprops, nextev): 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_subdomain(server, zone, ksks, zsks, smooth=smooth) isctest.kasp.check_dnssec_verify(server, zone) def check_next_key_event(): @@ -510,6 +529,143 @@ def test_rollover_enable_dnssec(servers): ] for step in steps: - check_rollover_step( - server, step["zone"], config, policy, step["keyprops"], step["nextev"] - ) + check_rollover_step(server, config, policy, step) + + +def test_rollover_zsk_prepublication(servers): + server = servers["ns3"] + policy = "zsk-prepub" + config = { + "dnskey-ttl": timedelta(seconds=3600), + "ds-ttl": timedelta(days=1), + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(days=1), + "purge-keys": timedelta(hours=1), + "retire-safety": timedelta(days=2), + "signatures-refresh": timedelta(days=7), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(hours=1), + } + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + zsk_lifetime = timedelta(days=30) + lifetime_policy = int(zsk_lifetime.total_seconds()) + + ipub = Ipub(config) + iret = Iret(config, rollover=True) + keyttlprop = config["dnskey-ttl"] + config["zone-propagation-delay"] + offsets = {} + offsets["step1-p"] = -int(timedelta(days=7).total_seconds()) + offsets["step2-p"] = -int(zsk_lifetime.total_seconds() - ipub.total_seconds()) + offsets["step2-s"] = 0 + offsets["step3-p"] = -int(zsk_lifetime.total_seconds()) + offsets["step3-s"] = -int(ipub.total_seconds()) + offsets["step4-p"] = offsets["step3-p"] - int(iret.total_seconds()) + offsets["step4-s"] = offsets["step3-s"] - int(iret.total_seconds()) + offsets["step5-p"] = offsets["step4-p"] - int(keyttlprop.total_seconds()) + offsets["step5-s"] = offsets["step4-s"] - int(keyttlprop.total_seconds()) + offsets["step6-p"] = offsets["step5-p"] - int(config["purge-keys"].total_seconds()) + offsets["step6-s"] = offsets["step5-s"] - int(config["purge-keys"].total_seconds()) + + steps = [ + { + # Step 1. + # Introduce the first key. This will immediately be active. + "zone": "step1.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step1-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step1-p']}", + ], + # Next key event is when the successor ZSK needs to be published. + # That is the ZSK lifetime - prepublication time (minus time + # already passed). + "nextev": zsk_lifetime - ipub - timedelta(days=7), + }, + { + # Step 2. + # It is time to pre-publish the successor ZSK. + # ZSK1 goal: omnipresent -> hidden + # ZSK2 goal: hidden -> omnipresent + # ZSK2 dnskey: hidden -> rumoured + "zone": "step2.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step2-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step2-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden offset:{offsets['step2-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the successor ZSK becomes OMNIPRESENT. + # That is the DNSKEY TTL plus the zone propagation delay + "nextev": ipub, + }, + { + # Step 3. + # Predecessor ZSK is no longer actively signing. Successor ZSK is + # now actively signing. + # ZSK1 zrrsig: omnipresent -> unretentive + # ZSK2 dnskey: rumoured -> omnipresent + # ZSK2 zrrsig: hidden -> rumoured + "zone": "step3.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step3-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:unretentive offset:{offsets['step3-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{offsets['step3-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when all the RRSIG records have been replaced + # with signatures of the new ZSK, in other words when ZRRSIG + # becomes OMNIPRESENT. + "nextev": iret, + # Set 'smooth' to true so expected signatures of subdomain are + # from the predecessor ZSK. + "smooth": True, + }, + { + # Step 4. + # Predecessor ZSK is no longer needed. All RRsets are signed with + # the successor ZSK. + # ZSK1 dnskey: omnipresent -> unretentive + # ZSK1 zrrsig: unretentive -> hidden + # ZSK2 zrrsig: rumoured -> omnipresent + "zone": "step4.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step4-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:hidden dnskey:unretentive zrrsig:hidden offset:{offsets['step4-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step4-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the DNSKEY enters the HIDDEN state. + # This is the DNSKEY TTL plus zone propagation delay. + "nextev": keyttlprop, + }, + { + # Step 5. + # Predecessor ZSK is now removed. + # ZSK1 dnskey: unretentive -> hidden + "zone": "step5.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step5-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:hidden dnskey:hidden zrrsig:hidden offset:{offsets['step5-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step5-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the new successor needs to be published. + # This is the ZSK lifetime minus Iret minus Ipub minus time + # elapsed. + "nextev": zsk_lifetime - iret - ipub - keyttlprop, + }, + { + # Step 6. + # Predecessor ZSK is now purged. + "zone": "step6.zsk-prepub.autosign", + "keyprops": [ + f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step6-p']}", + f"zsk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step6-s']}", + ], + "nextev": None, + }, + ] + + for step in steps: + check_rollover_step(server, config, policy, step)