Convert ksk rollover test case to pytest

Move the 'ksk-doubleksk' zones to the rollover test dir and convert KSK
rollover test to pytest.

Since the 'ksk-doubleksk' policy publishes different CDNSKEY/CDS RRsets,
update the 'check_rollover_step' to check which CDNSKEY/CDS RRsets should
be published and which should be prohibited. Update 'isctest.kasp'
accordingly.

We are changing the ZSK lifetime to unlimited in this test case as it
is of no importance (this actually discovered a bug in setting the
next time the keymgr should run).
This commit is contained in:
Matthijs Mekking 2025-03-18 14:20:54 +01:00
parent bd6c70bd67
commit 9ff7609614
8 changed files with 471 additions and 602 deletions

View file

@ -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

View file

@ -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.
*/

View file

@ -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).

View file

@ -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).
#

View file

@ -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;
};

View file

@ -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";
};

View file

@ -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

View file

@ -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)