diff --git a/bin/tests/system/rollover-csk-roll1/common.py b/bin/tests/system/rollover-csk-roll1/common.py new file mode 120000 index 0000000000..64b8084c5a --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/common.py @@ -0,0 +1 @@ +../rollover/common.py \ No newline at end of file diff --git a/bin/tests/system/rollover-csk-roll1/ns3/kasp.conf.j2 b/bin/tests/system/rollover-csk-roll1/ns3/kasp.conf.j2 new file mode 100644 index 0000000000..30427737fc --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/ns3/kasp.conf.j2 @@ -0,0 +1,34 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "csk-roll1" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + purge-keys PT1H; + + cds-digest-types { "sha-384"; }; // use a different digest type for testing purposes + keys { + csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; + + zone-propagation-delay 1h; + max-zone-ttl P1D; + + parent-ds-ttl 1h; + parent-propagation-delay 1h; +}; diff --git a/bin/tests/system/rollover-csk-roll1/ns3/named.common.conf.j2 b/bin/tests/system/rollover-csk-roll1/ns3/named.common.conf.j2 new file mode 120000 index 0000000000..5dc26178cb --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/ns3/named.common.conf.j2 @@ -0,0 +1 @@ +../../rollover/ns3/named.common.conf.j2 \ No newline at end of file diff --git a/bin/tests/system/rollover-csk-roll1/ns3/named.conf.j2 b/bin/tests/system/rollover-csk-roll1/ns3/named.conf.j2 new file mode 100644 index 0000000000..2c4764e280 --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/ns3/named.conf.j2 @@ -0,0 +1,56 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +include "kasp.conf"; +include "named.common.conf"; + +zone "step1.csk-roll1.autosign" { + type primary; + file "step1.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step2.csk-roll1.autosign" { + type primary; + file "step2.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step3.csk-roll1.autosign" { + type primary; + file "step3.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step4.csk-roll1.autosign" { + type primary; + file "step4.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step5.csk-roll1.autosign" { + type primary; + file "step5.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step6.csk-roll1.autosign" { + type primary; + file "step6.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step7.csk-roll1.autosign" { + type primary; + file "step7.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; +zone "step8.csk-roll1.autosign" { + type primary; + file "step8.csk-roll1.autosign.db"; + dnssec-policy "csk-roll1"; +}; diff --git a/bin/tests/system/rollover-csk-roll1/ns3/template.db.in b/bin/tests/system/rollover-csk-roll1/ns3/template.db.in new file mode 120000 index 0000000000..ce6d526285 --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/ns3/template.db.in @@ -0,0 +1 @@ +../../rollover/ns3/template.db.in \ No newline at end of file diff --git a/bin/tests/system/rollover-csk-roll1/setup.sh b/bin/tests/system/rollover-csk-roll1/setup.sh new file mode 100644 index 0000000000..755876feda --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/setup.sh @@ -0,0 +1,312 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +cd "ns3" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" + echo "$zone" >>zones +} + +# Set in the key state files the Predecessor/Successor fields. +# Key $1 is the predecessor of key $2. +key_successor() { + id1=$(keyfile_to_key_id "$1") + id2=$(keyfile_to_key_id "$2") + echo "Predecessor: ${id1}" >>"${2}.state" + echo "Successor: ${id2}" >>"${1}.state" +} + +# Make lines shorter by storing key states in environment variables. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" + +# +# The zones at csk-roll1.autosign represent the various steps of a CSK rollover +# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.csk-roll1.autosign +TactN="now-7d" +keytimes="-P ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to introduce the new CSK. +setup step2.csk-roll1.autosign +# According to RFC 7583: +# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC +# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# IpubC = DprpC + TTLkey (+publish-safety) +# Ipub = IpubC +# Lcsk = Lksk = Lzsk +# +# Lcsk: 6mo (186d, 4464h) +# Dreg: N/A +# DprpC: 1h +# TTLkey: 1h +# publish-safety: 1h +# Ipub: 3h +# +# Tact(N) = now - Lcsk + Ipub = now - 186d + 3h +# = now - 4464h + 3h = now - 4461h +TactN="now-4461h" +keytimes="-P ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS and to roll signatures. +setup step3.csk-roll1.autosign +# According to RFC 7583: +# +# Tsbm(N+1) >= Trdy(N+1) +# KSK: Tact(N+1) = Tsbm(N+1) +# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1) +# KSK: Iret = DprpP + TTLds (+retire-safety) +# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety) +# +# Lcsk: 186d +# Dprp: 1h +# DprpP: 1h +# Dreg: N/A +# Dsgn: 25d +# TTLds: 1h +# TTLsig: 1d +# retire-safety: 2h +# Iret: 4h +# IretZ: 26d3h +# Ipub: 3h +# +# Tpub(N) = now - Lcsk = now - 186d +# Tact(N) = now - Lcsk + Dprp + TTLsig = now - 4439h +# Tret(N) = now +# Trem(N) = now + IretZ = now + 26d3h = now + 627h +# Tpub(N+1) = now - Ipub = now - 3h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now + Lcsk = now + 186d = now + 186d +# Trem(N+1) = now + Lcsk + IretZ = now + 186d + 26d3h = +# = now + 5091h +TpubN="now-186d" +TactN="now-4439h" +TretN="now" +TremN="now+627h" +TpubN1="now-3h" +TactN1="${TretN}" +TretN1="now+186d" +TremN1="now+5091h" +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# Some time later all the ZRRSIG records should be from the new CSK, and the +# DS should be swapped. The ZRRSIG records are all replaced after IretZ +# (which is 26d3h). The DS is swapped after Iret (which is 4h). +# In other words, the DS is swapped before all zone signatures are replaced. +setup step4.csk-roll1.autosign +# According to RFC 7583: +# Trem(N) = Tret(N) - Iret + IretZ +# now = Tsbm(N+1) + Iret +# +# Lcsk: 186d +# Iret: 4h +# IretZ: 26d3h +# +# Tpub(N) = now - Iret - Lcsk = now - 4h - 186d = now - 4468h +# Tret(N) = now - Iret = now - 4h = now - 4h +# Trem(N) = now - Iret + IretZ = now - 4h + 26d3h +# = now + 623h +# Tpub(N+1) = now - Iret - IpubC = now - 4h - 3h = now - 7h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now - Iret + Lcsk = now - 4h + 186d = now + 4460h +# Trem(N+1) = now - Iret + Lcsk + IretZ = now - 4h + 186d + 26d3h +# = now + 5087h +TpubN="now-4468h" +TactN="now-4443h" +TretN="now-4h" +TremN="now+623h" +TpubN1="now-7h" +TactN1="${TretN}" +TretN1="now+4460h" +TremN1="now+5087h" +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TactN1 -z $U $TactN1 -D ds $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $R $TactN1 -z $R $TactN1 -P ds $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# After the DS is swapped in step 4, also the KRRSIG records can be removed. +# At this time these have all become hidden. +setup step5.csk-roll1.autosign +# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). +TpubN="now-4470h" +TactN="now-4445h" +TretN="now-6h" +TremN="now+621h" +TpubN1="now-9h" +TactN1="${TretN}" +TretN1="now+4458h" +TremN1="now+5085h" +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $U now-2h -d $H now-2h -z $U $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O now-2h -z $R $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# After the retire interval has passed the predecessor DNSKEY can be +# removed from the zone. +setup step6.csk-roll1.autosign +# According to RFC 7583: +# Trem(N) = Tret(N) + IretZ +# Tret(N) = Tact(N) + Lcsk +# +# Lcsk: 186d +# Iret: 4h +# IretZ: 26d3h +# +# Tpub(N) = now - IretZ - Lcsk = now - 627h - 186d +# = now - 627h - 4464h = now - 5091h +# Tact(N) = now - 627h - 186d +# Tret(N) = now - IretZ = now - 627h +# Trem(N) = now +# Tpub(N+1) = now - IretZ - Ipub = now - 627h - 3h = now - 630h +# Tact(N+1) = Tret(N) +# Tret(N+1) = now - IretZ + Lcsk = now - 627h + 186d = now + 3837h +# Trem(N+1) = now + Lcsk = now + 186d +TpubN="now-5091h" +TactN="now-5066h" +TretN="now-627h" +TremN="now" +TpubN1="now-630h" +TactN1="${TretN}" +TretN1="now+3837h" +TremN1="now+186d" +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $H $TremN -d $H $TremN -z $U $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TremN -z $R $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 7: +# Some time later the predecessor DNSKEY enters the HIDDEN state. +setup step7.csk-roll1.autosign +# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). +TpubN="now-5093h" +TactN="now-5068h" +TretN="now-629h" +TremN="now-2h" +TpubN1="now-632h" +TactN1="${TretN}" +TretN1="now+3835h" +TremN1="now+4462h" +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 8: +# The predecessor DNSKEY can be purged. +setup step8.csk-roll1.autosign +TpubN="now-5094h" +TactN="now-5069h" +TretN="now-630h" +TremN="now-3h" +TpubN1="now-633h" +TactN1="${TretN}" +TretN1="now+3834h" +TremN1="now+4461h" +# Subtract purge-keys interval from all the times (1h). +keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" +newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" +CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $H $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Set key rollover relationship. +key_successor $CSK1 $CSK2 +# Sign zone. +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py b/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py new file mode 100644 index 0000000000..9a265a682c --- /dev/null +++ b/bin/tests/system/rollover-csk-roll1/tests_rollover_csk_roll1.py @@ -0,0 +1,226 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# pylint: disable=redefined-outer-name,unused-import + +from datetime import timedelta + +import isctest +from isctest.kasp import Ipub, Iret +from common import ( + pytestmark, + alg, + size, + TIMEDELTA, +) + + +CDSS = ["CDNSKEY", "CDS (SHA-384)"] +CONFIG = { + "dnskey-ttl": TIMEDELTA["PT1H"], + "ds-ttl": TIMEDELTA["PT1H"], + "max-zone-ttl": TIMEDELTA["P1D"], + "parent-propagation-delay": TIMEDELTA["PT1H"], + "publish-safety": TIMEDELTA["PT1H"], + "purge-keys": TIMEDELTA["PT1H"], + "retire-safety": TIMEDELTA["PT2H"], + "signatures-refresh": TIMEDELTA["P5D"], + "signatures-validity": TIMEDELTA["P30D"], + "zone-propagation-delay": TIMEDELTA["PT1H"], +} +POLICY = "csk-roll1" +CSK_LIFETIME = timedelta(days=31 * 6) +LIFETIME_POLICY = int(CSK_LIFETIME.total_seconds()) +IPUB = Ipub(CONFIG) +IRETZSK = Iret(CONFIG) +IRETKSK = Iret(CONFIG, zsk=False, ksk=True) +KEYTTLPROP = CONFIG["dnskey-ttl"] + CONFIG["zone-propagation-delay"] +SIGNDELAY = IRETZSK - IRETKSK - KEYTTLPROP +OFFSETS = {} +OFFSETS["step1-p"] = -int(timedelta(days=7).total_seconds()) +OFFSETS["step2-p"] = -int(CSK_LIFETIME.total_seconds() - IPUB.total_seconds()) +OFFSETS["step2-s"] = 0 +OFFSETS["step3-p"] = -int(CSK_LIFETIME.total_seconds()) +OFFSETS["step3-s"] = -int(IPUB.total_seconds()) +OFFSETS["step4-p"] = OFFSETS["step3-p"] - int(IRETKSK.total_seconds()) +OFFSETS["step4-s"] = OFFSETS["step3-s"] - int(IRETKSK.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(SIGNDELAY.total_seconds()) +OFFSETS["step6-s"] = OFFSETS["step5-s"] - int(SIGNDELAY.total_seconds()) +OFFSETS["step7-p"] = OFFSETS["step6-p"] - int(KEYTTLPROP.total_seconds()) +OFFSETS["step7-s"] = OFFSETS["step6-s"] - int(KEYTTLPROP.total_seconds()) +OFFSETS["step8-p"] = OFFSETS["step7-p"] - int(CONFIG["purge-keys"].total_seconds()) +OFFSETS["step8-s"] = OFFSETS["step7-s"] - int(CONFIG["purge-keys"].total_seconds()) + + +def test_csk_roll1_step1(alg, size, servers): + step = { + # Introduce the first key. This will immediately be active. + "zone": "step1.csk-roll1.autosign", + "cdss": CDSS, + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}", + ], + # Next key event is when the successor CSK needs to be published + # minus time already elapsed. This is Lcsk - Ipub + Dreg (we ignore + # registration delay). + "nextev": CSK_LIFETIME - IPUB - timedelta(days=7), + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step2(alg, size, servers): + step = { + # Successor CSK is prepublished (signs DNSKEY RRset, but not yet + # other RRsets). + # CSK1 goal: omnipresent -> hidden + # CSK2 goal: hidden -> omnipresent + # CSK2 dnskey: hidden -> rumoured + # CSK2 krrsig: hidden -> rumoured + "zone": "step2.csk-roll1.autosign", + "cdss": CDSS, + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{OFFSETS['step2-s']}", + ], + "keyrelationships": [0, 1], + # Next key event is when the successor CSK becomes OMNIPRESENT. + "nextev": IPUB, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step3(alg, size, servers): + step = { + # Successor CSK becomes omnipresent, meaning we can start signing + # the remainder of the zone with the successor CSK, and we can + # submit the DS. + "zone": "step3.csk-roll1.autosign", + "cdss": CDSS, + # Predecessor CSK will be removed, so moving to UNRETENTIVE. + # CSK1 zrrsig: omnipresent -> unretentive + # Successor CSK DNSKEY is OMNIPRESENT, so moving ZRRSIG to RUMOURED. + # CSK2 dnskey: rumoured -> omnipresent + # CSK2 krrsig: rumoured -> omnipresent + # CSK2 zrrsig: hidden -> rumoured + # The predecessor DS can be withdrawn and the successor DS can be + # introduced. + # CSK1 ds: omnipresent -> unretentive + # CSK2 ds: hidden -> rumoured + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{OFFSETS['step3-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{OFFSETS['step3-s']}", + ], + "keyrelationships": [0, 1], + # 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": IRETKSK, + # Set 'smooth' to true so expected signatures of subdomain are + # from the predecessor ZSK. + "smooth": True, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step4(alg, size, servers): + step = { + "zone": "step4.csk-roll1.autosign", + "cdss": CDSS, + # The predecessor CSK is no longer signing the DNSKEY RRset. + # CSK1 krrsig: omnipresent -> unretentive + # The predecessor DS is hidden. The successor DS is now omnipresent. + # CSK1 ds: unretentive -> hidden + # CSK2 ds: rumoured -> omnipresent + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:unretentive zrrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step4-s']}", + ], + "keyrelationships": [0, 1], + # Next key event is when the KRRSIG enters the HIDDEN state. + # This is the DNSKEY TTL plus zone propagation delay. + "nextev": KEYTTLPROP, + # We already swapped the DS in the previous step, so disable ds-swap. + "ds-swap": False, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step5(alg, size, servers): + step = { + "zone": "step5.csk-roll1.autosign", + "cdss": CDSS, + # The predecessor KRRSIG records are now all hidden. + # CSK1 krrsig: unretentive -> hidden + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:hidden zrrsig:unretentive ds:hidden offset:{OFFSETS['step5-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{OFFSETS['step5-s']}", + ], + "keyrelationships": [0, 1], + # Next key event is when the DNSKEY can be removed. This is when + # all ZRRSIG records have been replaced with signatures of the new + # CSK. + "nextev": SIGNDELAY, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step6(alg, size, servers): + step = { + "zone": "step6.csk-roll1.autosign", + "cdss": CDSS, + # The predecessor ZRRSIG records are now all hidden (so the DNSKEY + # can be removed). + # CSK1 dnskey: omnipresent -> unretentive + # CSK1 zrrsig: unretentive -> hidden + # CSK2 zrrsig: rumoured -> omnipresent + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step6-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}", + ], + "keyrelationships": [0, 1], + # Next key event is when the DNSKEY enters the HIDDEN state. + # This is the DNSKEY TTL plus zone propagation delay. + "nextev": KEYTTLPROP, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step7(alg, size, servers): + step = { + "zone": "step7.csk-roll1.autosign", + "cdss": CDSS, + # The predecessor CSK is now completely HIDDEN. + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{OFFSETS['step7-p']}", + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step7-s']}", + ], + "keyrelationships": [0, 1], + # Next key event is when the new successor needs to be published. + # This is the Lcsk, minus time passed since the key started signing, + # minus the prepublication time. + "nextev": CSK_LIFETIME - IRETZSK - IPUB - KEYTTLPROP, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) + + +def test_csk_roll1_step8(alg, size, servers): + step = { + "zone": "step8.csk-roll1.autosign", + "cdss": CDSS, + "keyprops": [ + f"csk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step8-s']}", + ], + "nextev": None, + } + isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step) diff --git a/bin/tests/system/rollover/ns3/kasp.conf.j2 b/bin/tests/system/rollover/ns3/kasp.conf.j2 index 4a78c5b83f..80e76fae87 100644 --- a/bin/tests/system/rollover/ns3/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns3/kasp.conf.j2 @@ -90,25 +90,3 @@ dnssec-policy "ksk-doubleksk" { parent-ds-ttl 3600; parent-propagation-delay PT1H; }; - -dnssec-policy "csk-roll1" { - signatures-refresh P5D; - signatures-validity 30d; - signatures-validity-dnskey 30d; - - dnskey-ttl 1h; - publish-safety PT1H; - retire-safety 2h; - purge-keys PT1H; - - cds-digest-types { "sha-384"; }; // use a different digest type for testing purposes - keys { - csk key-directory lifetime P6M algorithm @DEFAULT_ALGORITHM@; - }; - - zone-propagation-delay 1h; - max-zone-ttl P1D; - - parent-ds-ttl 1h; - parent-propagation-delay 1h; -}; diff --git a/bin/tests/system/rollover/ns3/named.conf.j2 b/bin/tests/system/rollover/ns3/named.conf.j2 index 6dc2383cce..7a19129ccd 100644 --- a/bin/tests/system/rollover/ns3/named.conf.j2 +++ b/bin/tests/system/rollover/ns3/named.conf.j2 @@ -145,47 +145,3 @@ zone "three-is-a-crowd.kasp" { /* Use same policy as KSK rollover test zones. */ dnssec-policy "ksk-doubleksk"; }; - -/* - * Zones for testing CSK rollover steps. - */ -zone "step1.csk-roll1.autosign" { - type primary; - file "step1.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step2.csk-roll1.autosign" { - type primary; - file "step2.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step3.csk-roll1.autosign" { - type primary; - file "step3.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step4.csk-roll1.autosign" { - type primary; - file "step4.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step5.csk-roll1.autosign" { - type primary; - file "step5.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step6.csk-roll1.autosign" { - type primary; - file "step6.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step7.csk-roll1.autosign" { - type primary; - file "step7.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; -zone "step8.csk-roll1.autosign" { - type primary; - file "step8.csk-roll1.autosign.db"; - dnssec-policy "csk-roll1"; -}; diff --git a/bin/tests/system/rollover/ns3/setup.sh b/bin/tests/system/rollover/ns3/setup.sh index bcb74bcbf1..881e3bd565 100644 --- a/bin/tests/system/rollover/ns3/setup.sh +++ b/bin/tests/system/rollover/ns3/setup.sh @@ -558,275 +558,3 @@ 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-roll1.autosign represent the various steps of a CSK rollover -# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover). -# - -# Step 1: -# Introduce the first key. This will immediately be active. -setup step1.csk-roll1.autosign -TactN="now-7d" -keytimes="-P ${TactN} -A ${TactN}" -CSK=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 2: -# It is time to introduce the new CSK. -setup step2.csk-roll1.autosign -# According to RFC 7583: -# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC -# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub -# IpubC = DprpC + TTLkey (+publish-safety) -# Ipub = IpubC -# Lcsk = Lksk = Lzsk -# -# Lcsk: 6mo (186d, 4464h) -# Dreg: N/A -# DprpC: 1h -# TTLkey: 1h -# publish-safety: 1h -# Ipub: 3h -# -# Tact(N) = now - Lcsk + Ipub = now - 186d + 3h -# = now - 4464h + 3h = now - 4461h -TactN="now-4461h" -keytimes="-P ${TactN} -A ${TactN}" -CSK=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 3: -# It is time to submit the DS and to roll signatures. -setup step3.csk-roll1.autosign -# According to RFC 7583: -# -# Tsbm(N+1) >= Trdy(N+1) -# KSK: Tact(N+1) = Tsbm(N+1) -# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1) -# KSK: Iret = DprpP + TTLds (+retire-safety) -# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety) -# -# Lcsk: 186d -# Dprp: 1h -# DprpP: 1h -# Dreg: N/A -# Dsgn: 25d -# TTLds: 1h -# TTLsig: 1d -# retire-safety: 2h -# Iret: 4h -# IretZ: 26d3h -# Ipub: 3h -# -# Tpub(N) = now - Lcsk = now - 186d -# Tact(N) = now - Lcsk + Dprp + TTLsig = now - 4439h -# Tret(N) = now -# Trem(N) = now + IretZ = now + 26d3h = now + 627h -# Tpub(N+1) = now - Ipub = now - 3h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now + Lcsk = now + 186d = now + 186d -# Trem(N+1) = now + Lcsk + IretZ = now + 186d + 26d3h = -# = now + 5091h -TpubN="now-186d" -TactN="now-4439h" -TretN="now" -TremN="now+627h" -TpubN1="now-3h" -TactN1="${TretN}" -TretN1="now+186d" -TremN1="now+5091h" -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN -z $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 -z $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 4: -# Some time later all the ZRRSIG records should be from the new CSK, and the -# DS should be swapped. The ZRRSIG records are all replaced after IretZ -# (which is 26d3h). The DS is swapped after Iret (which is 4h). -# In other words, the DS is swapped before all zone signatures are replaced. -setup step4.csk-roll1.autosign -# According to RFC 7583: -# Trem(N) = Tret(N) - Iret + IretZ -# now = Tsbm(N+1) + Iret -# -# Lcsk: 186d -# Iret: 4h -# IretZ: 26d3h -# -# Tpub(N) = now - Iret - Lcsk = now - 4h - 186d = now - 4468h -# Tret(N) = now - Iret = now - 4h = now - 4h -# Trem(N) = now - Iret + IretZ = now - 4h + 26d3h -# = now + 623h -# Tpub(N+1) = now - Iret - IpubC = now - 4h - 3h = now - 7h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now - Iret + Lcsk = now - 4h + 186d = now + 4460h -# Trem(N+1) = now - Iret + Lcsk + IretZ = now - 4h + 186d + 26d3h -# = now + 5087h -TpubN="now-4468h" -TactN="now-4443h" -TretN="now-4h" -TremN="now+623h" -TpubN1="now-7h" -TactN1="${TretN}" -TretN1="now+4460h" -TremN1="now+5087h" -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TactN1 -z $U $TactN1 -D ds $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $R $TactN1 -z $R $TactN1 -P ds $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 5: -# After the DS is swapped in step 4, also the KRRSIG records can be removed. -# At this time these have all become hidden. -setup step5.csk-roll1.autosign -# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). -TpubN="now-4470h" -TactN="now-4445h" -TretN="now-6h" -TremN="now+621h" -TpubN1="now-9h" -TactN1="${TretN}" -TretN1="now+4458h" -TremN1="now+5085h" -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $U now-2h -d $H now-2h -z $U $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O now-2h -z $R $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 6: -# After the retire interval has passed the predecessor DNSKEY can be -# removed from the zone. -setup step6.csk-roll1.autosign -# According to RFC 7583: -# Trem(N) = Tret(N) + IretZ -# Tret(N) = Tact(N) + Lcsk -# -# Lcsk: 186d -# Iret: 4h -# IretZ: 26d3h -# -# Tpub(N) = now - IretZ - Lcsk = now - 627h - 186d -# = now - 627h - 4464h = now - 5091h -# Tact(N) = now - 627h - 186d -# Tret(N) = now - IretZ = now - 627h -# Trem(N) = now -# Tpub(N+1) = now - IretZ - Ipub = now - 627h - 3h = now - 630h -# Tact(N+1) = Tret(N) -# Tret(N+1) = now - IretZ + Lcsk = now - 627h + 186d = now + 3837h -# Trem(N+1) = now + Lcsk = now + 186d -TpubN="now-5091h" -TactN="now-5066h" -TretN="now-627h" -TremN="now" -TpubN1="now-630h" -TactN1="${TretN}" -TretN1="now+3837h" -TremN1="now+186d" -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $H $TremN -d $H $TremN -z $U $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TremN -z $R $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 7: -# Some time later the predecessor DNSKEY enters the HIDDEN state. -setup step7.csk-roll1.autosign -# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h). -TpubN="now-5093h" -TactN="now-5068h" -TretN="now-629h" -TremN="now-2h" -TpubN1="now-632h" -TactN1="${TretN}" -TretN1="now+3835h" -TremN1="now+4462h" -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $U $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 8: -# The predecessor DNSKEY can be purged. -setup step8.csk-roll1.autosign -TpubN="now-5094h" -TactN="now-5069h" -TretN="now-630h" -TremN="now-3h" -TpubN1="now-633h" -TactN1="${TretN}" -TretN1="now+3834h" -TremN1="now+4461h" -# Subtract purge-keys interval from all the times (1h). -keytimes="-P ${TpubN} -P sync ${TactN} -A ${TpubN} -I ${TretN} -D ${TremN} -D sync ${TactN1}" -newtimes="-P ${TpubN1} -P sync ${TactN1} -A ${TactN1} -I ${TretN1} -D ${TremN1}" -CSK1=$($KEYGEN -k csk-roll1 -l kasp.conf $keytimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-roll1 -l kasp.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $H $TremN -r $H $TremN -d $H $TremN -z $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 -z $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Set key rollover relationship. -key_successor $CSK1 $CSK2 -# Sign zone. -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -G "cdnskey,cds:sha-384" -s now-1h -e now+30d -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 8c37f61026..00a318bd4e 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -748,194 +748,3 @@ def test_rollover_ksk_doubleksk(servers): isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy) isctest.kasp.check_apex(server, zone, ksks, zsks, cdss=cdss) isctest.kasp.check_subdomain(server, zone, ksks, zsks) - - -def test_rollover_csk_roll1(servers): - server = servers["ns3"] - policy = "csk-roll1" - cdss = ["CDNSKEY", "CDS (SHA-384)"] - config = { - "dnskey-ttl": timedelta(hours=1), - "ds-ttl": timedelta(seconds=3600), - "max-zone-ttl": timedelta(days=1), - "parent-propagation-delay": timedelta(hours=1), - "publish-safety": timedelta(hours=1), - "purge-keys": timedelta(hours=1), - "retire-safety": timedelta(hours=2), - "signatures-refresh": timedelta(days=5), - "signatures-validity": timedelta(days=30), - "zone-propagation-delay": timedelta(hours=1), - } - alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] - size = os.environ["DEFAULT_BITS"] - csk_lifetime = timedelta(days=31 * 6) - lifetime_policy = int(csk_lifetime.total_seconds()) - - ipub = Ipub(config) - iretZSK = Iret(config) - iretKSK = Iret(config, zsk=False, ksk=True) - keyttlprop = config["dnskey-ttl"] + config["zone-propagation-delay"] - signdelay = iretZSK - iretKSK - keyttlprop - offsets = {} - offsets["step1-p"] = -int(timedelta(days=7).total_seconds()) - offsets["step2-p"] = -int(csk_lifetime.total_seconds() - ipub.total_seconds()) - offsets["step2-s"] = 0 - offsets["step3-p"] = -int(csk_lifetime.total_seconds()) - offsets["step3-s"] = -int(ipub.total_seconds()) - offsets["step4-p"] = offsets["step3-p"] - int(iretKSK.total_seconds()) - offsets["step4-s"] = offsets["step3-s"] - int(iretKSK.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(signdelay.total_seconds()) - offsets["step6-s"] = offsets["step5-s"] - int(signdelay.total_seconds()) - offsets["step7-p"] = offsets["step6-p"] - int(keyttlprop.total_seconds()) - offsets["step7-s"] = offsets["step6-s"] - int(keyttlprop.total_seconds()) - offsets["step8-p"] = offsets["step7-p"] - int(config["purge-keys"].total_seconds()) - offsets["step8-s"] = offsets["step7-s"] - int(config["purge-keys"].total_seconds()) - - steps = [ - { - # Step 1. - # Introduce the first key. This will immediately be active. - "zone": "step1.csk-roll1.autosign", - "cdss": cdss, - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step1-p']}", - ], - # Next key event is when the successor CSK needs to be published - # minus time already elapsed. This is Lcsk - Ipub + Dreg (we ignore - # registration delay). - "nextev": csk_lifetime - ipub - timedelta(days=7), - }, - { - # Step 2. - # Successor CSK is prepublished (signs DNSKEY RRset, but not yet - # other RRsets). - # CSK1 goal: omnipresent -> hidden - # CSK2 goal: hidden -> omnipresent - # CSK2 dnskey: hidden -> rumoured - # CSK2 krrsig: hidden -> rumoured - "zone": "step2.csk-roll1.autosign", - "cdss": cdss, - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step2-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:hidden ds:hidden offset:{offsets['step2-s']}", - ], - "keyrelationships": [0, 1], - # Next key event is when the successor CSK becomes OMNIPRESENT. - "nextev": ipub, - }, - { - # Step 3. - # Successor CSK becomes omnipresent, meaning we can start signing - # the remainder of the zone with the successor CSK, and we can - # submit the DS. - "zone": "step3.csk-roll1.autosign", - "cdss": cdss, - # Predecessor CSK will be removed, so moving to UNRETENTIVE. - # CSK1 zrrsig: omnipresent -> unretentive - # Successor CSK DNSKEY is OMNIPRESENT, so moving ZRRSIG to RUMOURED. - # CSK2 dnskey: rumoured -> omnipresent - # CSK2 krrsig: rumoured -> omnipresent - # CSK2 zrrsig: hidden -> rumoured - # The predecessor DS can be withdrawn and the successor DS can be - # introduced. - # CSK1 ds: omnipresent -> unretentive - # CSK2 ds: hidden -> rumoured - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:unretentive ds:unretentive offset:{offsets['step3-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:rumoured offset:{offsets['step3-s']}", - ], - "keyrelationships": [0, 1], - # 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": iretKSK, - # Set 'smooth' to true so expected signatures of subdomain are - # from the predecessor ZSK. - "smooth": True, - }, - { - # Step 4. - "zone": "step4.csk-roll1.autosign", - "cdss": cdss, - # The predecessor CSK is no longer signing the DNSKEY RRset. - # CSK1 krrsig: omnipresent -> unretentive - # The predecessor DS is hidden. The successor DS is now omnipresent. - # CSK1 ds: unretentive -> hidden - # CSK2 ds: rumoured -> omnipresent - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:unretentive zrrsig:unretentive ds:hidden offset:{offsets['step4-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{offsets['step4-s']}", - ], - "keyrelationships": [0, 1], - # Next key event is when the KRRSIG enters the HIDDEN state. - # This is the DNSKEY TTL plus zone propagation delay. - "nextev": keyttlprop, - # We already swapped the DS in the previous step, so disable ds-swap. - "ds-swap": False, - }, - { - # Step 5. - "zone": "step5.csk-roll1.autosign", - "cdss": cdss, - # The predecessor KRRSIG records are now all hidden. - # CSK1 krrsig: unretentive -> hidden - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:hidden zrrsig:unretentive ds:hidden offset:{offsets['step5-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:omnipresent offset:{offsets['step5-s']}", - ], - "keyrelationships": [0, 1], - # Next key event is when the DNSKEY can be removed. This is when - # all ZRRSIG records have been replaced with signatures of the new - # CSK. - "nextev": signdelay, - }, - { - # Step 6. - "zone": "step6.csk-roll1.autosign", - "cdss": cdss, - # The predecessor ZRRSIG records are now all hidden (so the DNSKEY - # can be removed). - # CSK1 dnskey: omnipresent -> unretentive - # CSK1 zrrsig: unretentive -> hidden - # CSK2 zrrsig: rumoured -> omnipresent - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:unretentive krrsig:hidden zrrsig:hidden ds:hidden offset:{offsets['step6-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step6-s']}", - ], - "keyrelationships": [0, 1], - # Next key event is when the DNSKEY enters the HIDDEN state. - # This is the DNSKEY TTL plus zone propagation delay. - "nextev": keyttlprop, - }, - { - # Step 7. - "zone": "step7.csk-roll1.autosign", - "cdss": cdss, - # The predecessor CSK is now completely HIDDEN. - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{offsets['step7-p']}", - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step7-s']}", - ], - "keyrelationships": [0, 1], - # Next key event is when the new successor needs to be published. - # This is the Lcsk, minus time passed since the key started signing, - # minus the prepublication time. - "nextev": csk_lifetime - iretZSK - ipub - keyttlprop, - }, - { - # Step 8. - # Predecessor CSK is now purged. - "zone": "step8.csk-roll1.autosign", - "cdss": cdss, - "keyprops": [ - f"csk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step8-s']}", - ], - "nextev": None, - }, - ] - - for step in steps: - sctest.kasp.check_rollover_step(server, config, policy, step)