diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 8233f1807b..537ebce0ba 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -909,8 +909,9 @@ def _check_dnskeys(dnskeys, keys, cdnskey=False): has_dnskey = True break - if not cdnskey: - assert has_dnskey + if not published or removed: + if not cdnskey: + assert has_dnskey if has_dnskey: numkeys += 1 @@ -940,22 +941,13 @@ def check_dnskeys(rrset, ksks, zsks, cdnskey=False): assert numkeys == len(dnskeys) -def check_cds(rrset, keys): +def check_cds(cdss, keys, alg): # Check if the correct CDS records are published. If the current time # is between the timing metadata 'publish' and 'delete', the key must have - # a DNSKEY record published. If 'cdnskey' is True, check against CDNSKEY - # records instead. + # a CDS record published. now = KeyTimingMetadata.now() numcds = 0 - cdss = [] - for rr in rrset: - 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}" - cdss.append(cds) - for key in keys: assert key.is_ksk() @@ -965,19 +957,31 @@ def check_cds(rrset, keys): removed = delete is not None and delete <= now if not published or removed: for cds in cdss: - assert not key.cds_equals(cds, "SHA-256") + assert not key.cds_equals(cds, alg) continue has_cds = False for cds in cdss: - if key.cds_equals(cds, "SHA-256"): + if key.cds_equals(cds, alg): has_cds = True break - assert has_cds - numcds += 1 + if not published or removed: + assert has_cds - assert numcds == len(cdss) + if has_cds: + numcds += 1 + + return numcds + + +def check_cds_prohibit(cdss, keys, alg): + # Check if the CDS records are not published. This does not take into + # account the timing metadata, just making sure that the given algorithm + # does not get published. + for key in keys: + for cds in cdss: + assert not key.cds_equals(cds, alg) def check_cdslog(server, zone, key, substr): @@ -1015,12 +1019,15 @@ def _query_rrset(server, fqdn, qtype, tsig=None): def check_apex( - server, zone, ksks, zsks, offline_ksk=False, zsk_missing=False, tsig=None + server, zone, ksks, zsks, cdss=None, 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. fqdn = f"{zone}." + if cdss is None: + cdss = ["CDNSKEY", "CDS (SHA-256)"] + # test dnskey query dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY, tsig=tsig) check_dnskeys(dnskeys, ksks, zsks) @@ -1044,7 +1051,12 @@ def check_apex( # test cdnskey query cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig) - check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + + if "CDNSKEY" in cdss: + check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + else: + assert len(cdnskeys) == 0 + if len(cdnskeys) > 0: assert len(rrsigs) > 0 check_signatures( @@ -1053,13 +1065,30 @@ def check_apex( # test cds query cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig) - check_cds(cds, ksks) + 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 + + 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) + 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( server, zone, ksks, zsks, offline_ksk=False, smooth=False, 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 9247a12350..85636adbb4 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 KSK Double-KSK steps. - */ -zone "step1.ksk-doubleksk.autosign" { - type primary; - file "step1.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; -zone "step2.ksk-doubleksk.autosign" { - type primary; - file "step2.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; -zone "step3.ksk-doubleksk.autosign" { - type primary; - file "step3.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; -zone "step4.ksk-doubleksk.autosign" { - type primary; - file "step4.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; -zone "step5.ksk-doubleksk.autosign" { - type primary; - file "step5.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; -zone "step6.ksk-doubleksk.autosign" { - type primary; - file "step6.ksk-doubleksk.autosign.db"; - dnssec-policy "ksk-doubleksk"; -}; - /* * Zones for testing CSK rollover steps. */ diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index 4e4cc1d808..cf4d0a98e8 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -281,283 +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 ksk-doubleksk.autosign represent the various steps of a KSK -# Double-KSK rollover. -# - -# Step 1: -# Introduce the first key. This will immediately be active. -setup step1.ksk-doubleksk.autosign -TactN="now" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN}" -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 $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" -cp $infile $zonefile -$SIGNER -S -x -G "cds:sha-256" -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 submit the introduce the new KSK. -setup step2.ksk-doubleksk.autosign -# According to RFC 7583: -# -# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC -# IpubC = DprpC + TTLkey (+publish-safety) -# -# |1| |2| |3| |4| -# | | | | -# Key N |<-IpubC->|<--->|<-Dreg->|<-----Lksk--- - - -# | | | | -# Key N+1 | | | | -# | | | | -# Key N Tpub Trdy Tsbm Tact -# Key N+1 -# -# (continued ...) -# -# |5| |6| |7| |8| |9| |10| -# | | | | | | -# Key N - - --------------Lksk------->|<-Iret->|<----->| -# | | | | | | -# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - -# | | | | | | -# Key N Tret Tdea Trem -# Key N+1 Tpub Trdy Tsbm Tact -# -# Tnow -# -# Lksk: 60d -# Dreg: 1d -# DprpC: 1h -# TTLkey: 2h -# publish-safety: 1d -# IpubC: 27h -# -# Tact(N) = Tnow - Lksk + Dreg + IpubC = now - 60d + 27h -# = now - 1440h + 27h = now - 1413h -TactN="now-1413h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN}" -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 $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 -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 3: -# It is time to submit the DS. -setup step3.ksk-doubleksk.autosign -# According to RFC 7583: -# -# Tsbm(N+1) >= Trdy(N+1) -# Tact(N+1) = Tsbm(N+1) + Dreg -# Iret = DprpP + TTLds (+retire-safety) -# -# |5| |6| |7| |8| |9| |10| -# | | | | | | -# Key N - - --------------Lksk------->|<-Iret->|<----->| -# | | | | | | -# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - -# | | | | | | -# Key N Tret Tdea Trem -# Key N+1 Tpub Trdy Tsbm Tact -# -# Tnow -# -# Lksk: 60d -# Dreg: N/A -# DprpP: 1h -# TTLds: 1h -# retire-safety: 2d -# Iret: 50h -# DprpC: 1h -# TTLkey: 2h -# publish-safety: 1d -# IpubC: 27h -# -# Tact(N) = Tnow + Lksk = now - 60d = now - 60d -# Tret(N) = now -# Trem(N) = Tnow + Iret = now + 50h -# Tpub(N+1) = Tnow - IpubC = now - 27h -# Tsbm(N+1) = now -# Tact(N+1) = Tret(N) -# Tret(N+1) = Tnow + Lksk = now + 60d -# Trem(N+1) = Tnow + Lksk + Iret = now + 60d + 50h -# = now + 1440h + 50h = 1490h -TactN="now-60d" -TretN="now" -TremN="now+50h" -TpubN1="now-27h" -TsbmN1="now" -TactN1="${TretN}" -TretN1="now+60d" -TremN1="now+1490h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $KSK1 $KSK2 -# Sign zone. -cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 4: -# The DS should be swapped now. -setup step4.ksk-doubleksk.autosign -# According to RFC 7583: -# -# Tret(N) = Tsbm(N+1) -# Tdea(N) = Tret(N) + Iret -# Tact(N+1) = Tret(N) -# -# |5| |6| |7| |8| |9| |10| -# | | | | | | -# Key N - - --------------Lksk------->|<-Iret->|<----->| -# | | | | | | -# Key N+1 |<-IpubC->|<--->|<-Dreg->|<--------Lksk----- - - -# | | | | | | -# Key N Tret Tdea Trem -# Key N+1 Tpub Trdy Tsbm Tact -# -# Tnow -# -# Lksk: 60d -# Dreg: N/A -# Iret: 50h -# -# Tact(N) = Tnow - Lksk - Iret = now - 60d - 50h -# = now - 1440h - 50h = now - 1490h -# Tret(N) = Tnow - Iret = now - 50h -# Trem(N) = Tnow -# Tpub(N+1) = Tnow - Iret - IpubC = now - 50h - 27h -# = now - 77h -# Tsbm(N+1) = Tnow - Iret = now - 50h -# Tact(N+1) = Tret(N) -# Tret(N+1) = Tnow + Lksk - Iret = now + 60d - 50h = now + 1390h -# Trem(N+1) = Tnow + Lksk = now + 60d -TactN="now-1490h" -TretN="now-50h" -TremN="now" -TpubN1="now-77h" -TsbmN1="now-50h" -TactN1="${TretN}" -TretN1="now+1390h" -TremN1="now+60d" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -D ds $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 -P ds $TsbmN1 "$KSK2" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $KSK1 $KSK2 -# Sign zone. -cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -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.ksk-doubleksk.autosign -# Subtract DNSKEY TTL from all the times (2h). -# Tact(N) = now - 1490h - 2h = now - 1492h -# Tret(N) = now - 50h - 2h = now - 52h -# Trem(N) = now - 2h -# Tpub(N+1) = now - 77h - 2h = now - 79h -# Tsbm(N+1) = now - 50h - 2h = now - 52h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now + 1390h - 2h = now + 1388h -# Trem(N+1) = now + 60d - 2h = now + 1442h -TactN="now-1492h" -TretN="now-52h" -TremN="now-2h" -TpubN1="now-79h" -TsbmN1="now-52h" -TactN1="${TretN}" -TretN1="now+1388h" -TremN1="now+1442h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $KSK1 $KSK2 -# Sign zone. -cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -G "cds:sha-256" -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.ksk-doubleksk.autosign -# Subtract purge-keys interval from all the times (1h). -# Tact(N) = now - 1492h - 1h = now - 1493h -# Tret(N) = now - 52h - 1h = now - 53h -# Trem(N) = now - 2h - 1h = now - 3h -# Tpub(N+1) = now - 79h - 1h = now - 80h -# Tsbm(N+1) = now - 52h - 1h = now - 53h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now + 1388h - 1h = now + 1387h -# Trem(N+1) = now + 1442h - 1h = now + 1441h -TactN="now-1493h" -TretN="now-53h" -TremN="now-3h" -TpubN1="now-80h" -TsbmN1="now-53h" -TactN1="${TretN}" -TretN1="now+1387h" -TremN1="now+1441h" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN} -D ${TremN}" -newtimes="-P ${TpubN1} -A ${TretN} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) -$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 -# Set key rollover relationship. -key_successor $KSK1 $KSK2 -# Sign zone. -cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - # # The zones at csk-roll.autosign represent the various steps of a CSK rollover # (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 26759298b0..b8de25dd80 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -266,273 +266,6 @@ rollover_predecessor_keytimes() { [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}" } -# -# Testing KSK Double-KSK rollover. -# - -# Policy parameters. -# Lksk: 60 days (16070400 seconds) -# Lzsk: 1 year (31536000 seconds) -# Iret(KSK): DS TTL (1h) + DprpP (1h) + retire-safety (2d) -# Iret(KSK): 50h (180000 seconds) -# Iret(ZSK): RRSIG TTL (1d) + Dprp (1h) + Dsgn (1w) + retire-safety (2d) -# Iret(ZSK): 10d1h (867600 seconds) -Lksk=5184000 -Lzsk=31536000 -IretKSK=180000 -IretZSK=867600 - -# -# Zone: step1.ksk-doubleksk.autosign. -# -set_zone "step1.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "2" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" -# 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 KSK needs to be published. That is -# the KSK lifetime - prepublication time. The prepublication time is -# DNSKEY TTL plus publish safety plus the zone propagation delay. -# For the ksk-doubleksk policy that means: 60d - (1d3h) = 5086800 seconds. -check_next_key_event 5086800 - -# -# Zone: step2.ksk-doubleksk.autosign. -# -set_zone "step2.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "3" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" -# New KSK (KEY3) is prepublished (and signs DNSKEY RRset). -key_clear "KEY3" -set_keyrole "KEY3" "ksk" -set_keylifetime "KEY3" "${Lksk}" -set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY3" "yes" -set_zonesigning "KEY3" "no" -# Key states. -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_KRRSIG" "rumoured" -set_keystate "KEY3" "STATE_DS" "hidden" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys were activated 1413 hours ago (5086800 seconds). -rollover_predecessor_keytimes -5086800 -# - The new KSK is published now. -created=$(key_get KEY3 CREATED) -set_keytime "KEY3" "PUBLISHED" "${created}" -# The new KSK should publish the CDS after the prepublication time. -# TTLkey: 2h -# DprpC: 1h -# publish-safety: 1d -# IpubC: 27h (97200 seconds) -IpubC=97200 -set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${IpubC}" -set_addkeytime "KEY3" "ACTIVE" "${created}" "${IpubC}" -set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the successor KSK becomes OMNIPRESENT. That is the -# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For -# the ksk-doubleksk policy, this means: 7200s + 1h + 1d = 97200 seconds. -check_next_key_event 97200 - -# -# Zone: step3.ksk-doubleksk.autosign. -# -set_zone "step3.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "3" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" - -# The DNSKEY RRset has become omnipresent. -# Check keys before we tell named that we saw the DS has been replaced. -set_keystate "KEY3" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY3" "STATE_KRRSIG" "omnipresent" -# The old DS (KEY1) can be withdrawn and the new DS (KEY3) can be introduced. -set_keystate "KEY1" "STATE_DS" "unretentive" -set_keystate "KEY3" "STATE_DS" "rumoured" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# Check that CDS publication is logged. -check_cdslog "$DIR" "$ZONE" KEY3 - -# Set expected key times: -# - The old keys were activated 60 days ago (5184000 seconds). -rollover_predecessor_keytimes -5184000 -# - The new KSK is published 27 hours ago (97200 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -97200 -# - The new KSK CDS is published now. -set_keytime "KEY3" "SYNCPUBLISH" "${created}" -syncpub=$(key_get KEY3 SYNCPUBLISH) -set_keytime "KEY3" "ACTIVE" "${syncpub}" -set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" - -# Continue signing policy checks. -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# We ignore any parent registration delay, so set the DS publish time to now. -rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" -rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE" -# Next key event is when the predecessor DS has been replaced with the -# successor DS and enough time has passed such that the all validators that -# have this DS RRset cached only know about the successor DS. This is the -# the retire interval, which is the parent propagation delay plus the DS TTL -# plus the retire-safety. For the ksk-double-ksk policy this means: -# 1h + 3600s + 2d = 2d2h = 180000 seconds. -check_next_key_event 180000 - -# -# Zone: step4.ksk-doubleksk.autosign. -# -set_zone "step4.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "3" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" -# KSK (KEY1) DNSKEY can be removed. -set_keysigning "KEY1" "no" -set_keystate "KEY1" "STATE_DNSKEY" "unretentive" -set_keystate "KEY1" "STATE_KRRSIG" "unretentive" -set_keystate "KEY1" "STATE_DS" "hidden" -# New KSK (KEY3) DS is now OMNIPRESENT. -set_keystate "KEY3" "STATE_DS" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys were activated 1490 hours ago (5364000 seconds). -rollover_predecessor_keytimes -5364000 -# - The new KSK is published 77 hours ago (277200 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -277200 -published=$(key_get KEY3 PUBLISHED) -set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}" -syncpub=$(key_get KEY3 SYNCPUBLISH) -set_keytime "KEY3" "ACTIVE" "${syncpub}" -set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" - -# 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 ksk-doubleksk policy this is: -# 7200s + 1h = 10800s -check_next_key_event 10800 - -# -# Zone: step5.ksk-doubleksk.autosign. -# -set_zone "step5.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "3" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" -# KSK (KEY1) DNSKEY is now HIDDEN. -set_keystate "KEY1" "STATE_DNSKEY" "hidden" -set_keystate "KEY1" "STATE_KRRSIG" "hidden" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old KSK is activated 1492 hours ago (5371200 seconds). -rollover_predecessor_keytimes -5371200 -# - The new KSK is published 79 hours ago (284400 seconds). -created=$(key_get KEY3 CREATED) -set_addkeytime "KEY3" "PUBLISHED" "${created}" -284400 -published=$(key_get KEY3 PUBLISHED) -set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" "${IpubC}" -syncpub=$(key_get KEY3 SYNCPUBLISH) -set_keytime "KEY3" "ACTIVE" "${syncpub}" -set_retired_removed "KEY3" "${Lksk}" "${IretKSK}" - -# Various 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 -# KSK lifetime minus Ipub minus Iret minus DNSKEY TTL. For the -# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h = -# 5184000 - 97200 - 180000 - 7200 = 4813200 seconds. -check_next_key_event 4899600 - -# -# Zone: step6.ksk-doubleksk.autosign. -# -set_zone "step6.ksk-doubleksk.autosign" -set_policy "ksk-doubleksk" "2" "7200" -CDNSKEY="no" -set_server "ns3" "10.53.0.3" -# KSK (KEY1) DNSKEY is purged. -key_clear "KEY1" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - # # Testing CSK key rollover (1). # diff --git a/bin/tests/system/rollover/ns3/kasp.conf.j2 b/bin/tests/system/rollover/ns3/kasp.conf.j2 index 209d72cb09..80e76fae87 100644 --- a/bin/tests/system/rollover/ns3/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns3/kasp.conf.j2 @@ -67,3 +67,26 @@ dnssec-policy "zsk-prepub" { zone-propagation-delay PT1H; max-zone-ttl 1d; }; + +dnssec-policy "ksk-doubleksk" { + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 2h; + publish-safety P1D; + retire-safety P2D; + purge-keys PT1H; + + cdnskey no; + keys { + ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay PT1H; + max-zone-ttl 1d; + + parent-ds-ttl 3600; + parent-propagation-delay PT1H; +}; diff --git a/bin/tests/system/rollover/ns3/named.conf.j2 b/bin/tests/system/rollover/ns3/named.conf.j2 index 309014cb1b..141d75c0e2 100644 --- a/bin/tests/system/rollover/ns3/named.conf.j2 +++ b/bin/tests/system/rollover/ns3/named.conf.j2 @@ -125,3 +125,37 @@ zone "step6.zsk-prepub.autosign" { file "step6.zsk-prepub.autosign.db"; dnssec-policy "zsk-prepub"; }; + +/* + * Zones for testing KSK Double-KSK steps. + */ +zone "step1.ksk-doubleksk.autosign" { + type primary; + file "step1.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step2.ksk-doubleksk.autosign" { + type primary; + file "step2.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step3.ksk-doubleksk.autosign" { + type primary; + file "step3.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step4.ksk-doubleksk.autosign" { + type primary; + file "step4.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step5.ksk-doubleksk.autosign" { + type primary; + file "step5.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step6.ksk-doubleksk.autosign" { + type primary; + file "step6.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; diff --git a/bin/tests/system/rollover/ns3/setup.sh b/bin/tests/system/rollover/ns3/setup.sh index 23920a0ab8..dd13005a3d 100644 --- a/bin/tests/system/rollover/ns3/setup.sh +++ b/bin/tests/system/rollover/ns3/setup.sh @@ -316,4 +316,203 @@ 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. +# +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.ksk-doubleksk.autosign +TactN="now-7d" +keytimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $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" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -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 submit the introduce the new KSK. +setup step2.ksk-doubleksk.autosign +# Lksk: 60d +# Dreg: n/a +# DprpC: 1h +# TTLds: 1d +# TTLkey: 2h +# publish-safety: 1d +# retire-safety: 2d +# +# According to RFC 7583: +# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC +# IpubC = DprpC + TTLkey (+publish-safety) +# +# IpubC = 27h +# Tact(N) = now - Lksk + Dreg + IpubC = now - 60d + 27h +# = now - 1440h + 27h = now - 1413h +TactN="now-1413h" +keytimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $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 -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS. +setup step3.ksk-doubleksk.autosign +# According to RFC 7583: +# Iret = DprpP + TTLds (+retire-safety) +# +# Iret = 50h +# Tpub(N) = now - Lksk = now - 60d = now - 60d +# Tact(N) = now - 1413h +# Tret(N) = now +# Trem(N) = now + Iret = now + 50h +# Tpub(N+1) = now - IpubC = now - 27h +# Tact(N+1) = now +# Tret(N+1) = now + Lksk = now + 60d +# Trem(N+1) = now + Lksk + Iret = now + 60d + 50h +# = now + 1440h + 50h = 1490h +TpubN="now-60d" +TactN="now-1413h" +TretN="now" +TremN="now+50h" +TpubN1="now-27h" +TactN1="now" +TretN1="now+60d" +TremN1="now+1490h" +ksktimes="-P ${TpubN} -A ${TpubN} -P sync ${TactN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TpubN} -A ${TpubN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $O $TpubN -r $O $TpubN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN -z $O $TpubN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS should be swapped now. +setup step4.ksk-doubleksk.autosign +# Tpub(N) = now - Lksk - Iret = now - 60d - 50h +# = now - 1440h - 50h = now - 1490h +# Tact(N) = now - 1490h + 27h = now - 1463h +# Tret(N) = now - Iret = now - 50h +# Trem(N) = now +# Tpub(N+1) = now - Iret - IpubC = now - 50h - 27h +# = now - 77h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + Lksk - Iret = now + 60d - 50h = now + 1390h +# Trem(N+1) = now + Lksk = now + 60d +TpubN="now-1490h" +TactN="now-1463h" +TretN="now-50h" +TremN="now" +TpubN1="now-77h" +TactN1="${TretN}" +TretN1="now+1390h" +TremN1="now+60d" +ksktimes="-P ${TpubN} -A ${TpubN} -P sync ${TactN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TpubN} -A ${TpubN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TretN -D ds $TretN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $R $TactN1 -P ds $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -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.ksk-doubleksk.autosign +# Subtract DNSKEY TTL + zone-propagation-delay from all the times (3h). +# Tpub(N) = now - 1490h - 3h = now - 1493h +# Tact(N) = now - 1463h - 3h = now - 1466h +# Tret(N) = now - 50h - 3h = now - 53h +# Trem(N) = now - 3h +# Tpub(N+1) = now - 77h - 3h = now - 80h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + 1390h - 3h = now + 1387h +# Trem(N+1) = now + 60d - 3h = now + 1441h +TpubN="now-1493h" +TactN="now-1466h" +TretN="now-53h" +TremN="now-3h" +TpubN1="now-80h" +TactN1="${TretN}" +TretN1="now+1387h" +TremN1="now+1441h" +ksktimes="-P ${TpubN} -A ${TpubN} -P sync ${TactN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TpubN} -A ${TpubN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $U $TretN -r $U $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -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.ksk-doubleksk.autosign +# Subtract purge-keys interval from all the times (1h). +TpubN="now-1494h" +TactN="now-1467h" +TretN="now-54h" +TremN="now-4h" +TpubN1="now-81h" +TactN1="${TretN}" +TretN1="now+1386h" +TremN1="now+1440h" +ksktimes="-P ${TpubN} -A ${TpubN} -P sync ${TactN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TactN1} -I ${TretN1} -D ${TremN1}" +zsktimes="-P ${TpubN} -A ${TpubN}" +KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3) +$SETTIME -s -g $H -k $H $TretN -r $H $TretN -d $H $TretN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1 +# Set key rollover relationship. +key_successor $KSK1 $KSK2 +# Sign zone. +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -G "cds:sha-256" -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 45e252307e..2fc796b1ad 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -388,6 +388,9 @@ def check_rollover_step(server, config, policy, step): zone = step["zone"] keyprops = step["keyprops"] nextev = step["nextev"] + cdss = [] + if step.get("cdss"): + cdss = step["cdss"] keyrelationships = None if step.get("keyrelationships"): keyrelationships = step["keyrelationships"] @@ -423,9 +426,13 @@ def check_rollover_step(server, config, policy, step): 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)") + assert cdss is not None + + for algstr in ["CDNSKEY", "CDS (SHA-256)", "CDS (SHA-384)"]: + if algstr in cdss: + isctest.kasp.check_cdslog(server, zone, key, algstr) + else: + isctest.kasp.check_cdslog_prohibit(server, zone, key, algstr) # The DS can be introduced. We ignore any parent registration delay, # so set the DS publish time to now. @@ -451,6 +458,7 @@ def check_rollover_step(server, config, policy, step): def test_rollover_enable_dnssec(servers): server = servers["ns3"] policy = "enable-dnssec" + cdss = ["CDNSKEY", "CDS (SHA-256)"] config = { "dnskey-ttl": timedelta(seconds=300), "ds-ttl": timedelta(hours=2), @@ -480,6 +488,7 @@ def test_rollover_enable_dnssec(servers): { # Step 1. "zone": "step1.enable-dnssec.autosign", + "cdss": cdss, "keyprops": [ f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{offsets['step1']}", ], @@ -490,6 +499,7 @@ def test_rollover_enable_dnssec(servers): { # Step 2. "zone": "step2.enable-dnssec.autosign", + "cdss": cdss, # The DNSKEY is omnipresent, but the zone signatures not yet. # Thus, the DS remains hidden. # dnskey: rumoured -> omnipresent @@ -504,6 +514,7 @@ def test_rollover_enable_dnssec(servers): { # Step 3. "zone": "step3.enable-dnssec.autosign", + "cdss": cdss, # All signatures should be omnipresent, so the DS can be submitted. # zrrsig: rumoured -> omnipresent # ds: hidden -> rumoured @@ -517,6 +528,7 @@ def test_rollover_enable_dnssec(servers): { # Step 4. "zone": "step4.enable-dnssec.autosign", + "cdss": cdss, # DS has been published long enough. # ds: rumoured -> omnipresent "keyprops": [ @@ -669,3 +681,153 @@ def test_rollover_zsk_prepublication(servers): for step in steps: check_rollover_step(server, config, policy, step) + + +def test_rollover_ksk_doubleksk(servers): + server = servers["ns3"] + policy = "ksk-doubleksk" + cdss = ["CDS (SHA-256)"] + config = { + "dnskey-ttl": timedelta(hours=2), + "ds-ttl": timedelta(seconds=3600), + "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), + } + ttl = int(config["dnskey-ttl"].total_seconds()) + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + ksk_lifetime = timedelta(days=60) + lifetime_policy = int(ksk_lifetime.total_seconds()) + + ipub = Ipub(config) + ipubc = IpubC(config) + iret = Iret(config, zsk=False, ksk=True) + keyttlprop = config["dnskey-ttl"] + config["zone-propagation-delay"] + offsets = {} + offsets["step1-p"] = -int(timedelta(days=7).total_seconds()) + offsets["step2-p"] = -int(ksk_lifetime.total_seconds() - ipubc.total_seconds()) + offsets["step2-s"] = 0 + offsets["step3-p"] = -int(ksk_lifetime.total_seconds()) + offsets["step3-s"] = -int(ipubc.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.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step1-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step1-p']}", + ], + # Next key event is when the successor KSK needs to be published. + # That is the KSK lifetime - prepublication time (minus time + # already passed). + "nextev": ksk_lifetime - ipub - timedelta(days=7), + }, + { + # Step 2. + # Successor KSK is prepublished (and signs DNSKEY RRset). + # KSK1 goal: omnipresent -> hidden + # KSK2 goal: hidden -> omnipresent + # KSK2 dnskey: hidden -> rumoured + # KSK2 krrsig: hidden -> rumoured + "zone": "step2.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step2-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step2-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{offsets['step2-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the successor KSK becomes OMNIPRESENT. + "nextev": ipub, + }, + { + # Step 3. + # The successor DNSKEY RRset has become omnipresent. The + # predecessor DS can be withdrawn and the successor DS can be + # introduced. + # KSK1 ds: omnipresent -> unretentive + # KSK2 dnskey: rumoured -> omnipresent + # KSK2 krrsig: rumoured -> omnipresent + # KSK2 ds: hidden -> rumoured + "zone": "step3.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step3-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offsets['step3-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{offsets['step3-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the predecessor DS has been replaced with + # the successor DS and enough time has passed such that the all + # validators that have this DS RRset cached only know about the + # successor DS. This is the the retire interval. + "nextev": iret, + }, + { + # Step 4. + # The predecessor DNSKEY may be removed, the successor DS is + # omnipresent. + # KSK1 dnskey: omnipresent -> unretentive + # KSK1 krrsig: omnipresent -> unretentive + # KSK1 ds: unretentive -> hidden + # KSK2 ds: rumoured -> omnipresent + "zone": "step4.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step4-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{offsets['step4-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds: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. + # The predecessor DNSKEY is long enough removed from the zone it + # has become hidden. + # KSK1 dnskey: unretentive -> hidden + # KSK1 krrsig: unretentive -> hidden + "zone": "step5.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step5-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{offsets['step5-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step5-s']}", + ], + "keyrelationships": [1, 2], + # Next key event is when the new successor needs to be published. + # This is the KSK lifetime minus Ipub minus Iret minus time elapsed. + "nextev": ksk_lifetime - ipub - iret - keyttlprop, + }, + { + # Step 6. + # Predecessor KSK is now purged. + "zone": "step6.ksk-doubleksk.autosign", + "cdss": cdss, + "keyprops": [ + f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step6-p']}", + f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step6-s']}", + ], + "nextev": None, + }, + ] + + for step in steps: + check_rollover_step(server, config, policy, step)