2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

Convert zsk rollover test case to pytest

Move the 'zsk-prepub' zones to the rollover test dir and convert ZSK
rollover test to pytest.

We need a way to signal a smooth rollover is going on. Signatures are
being replaced gradually during a ZSK rollover, so the existing
signatures of the predecessor ZSK are still being used. Add a smooth
operator to set the right expectations on what signatures are being
used.

Setting expected key relationships is a bit crude: a list of two
elements where the first element is the index of the expected keys that
is the predecessor, and the second element is the index of the expected
keys that is the successor.

We are changing the KSK lifetime to unlimited in this test case as it
is of no importance.
This commit is contained in:
Matthijs Mekking 2025-03-18 12:18:34 +01:00
parent 233fdb8d52
commit bd6c70bd67
9 changed files with 422 additions and 577 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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