From: Matthijs Mekking Date: Thu, 17 Oct 2019 13:50:52 +0000 (+0200) Subject: Test ZSK and KSK rollover X-Git-Tag: v9.15.6~26^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=36c72bf3c3653603a3f6efe4fc47ec1011f72949;p=thirdparty%2Fbind9.git Test ZSK and KSK rollover Add tests for ZSK Pre-Publication and KSK Double-KSK rollover. Includes tests for next key event is scheduled at the right time. --- diff --git a/bin/tests/system/kasp/ns3/named.conf.in b/bin/tests/system/kasp/ns3/named.conf.in index 880f3fd50c7..c7a830dc3ab 100644 --- a/bin/tests/system/kasp/ns3/named.conf.in +++ b/bin/tests/system/kasp/ns3/named.conf.in @@ -33,6 +33,7 @@ controls { }; include "policies/kasp.conf"; +include "policies/autosign.conf"; /* Zones that are getting initially signed */ @@ -120,3 +121,115 @@ zone "ecdsa384.kasp" { file "ecdsa384.kasp.db"; dnssec-policy "ecdsa384"; }; + +/* + * Zones in different signing states. + */ + +/* + * Zone that has expired signatures. + */ +zone "expired-sigs.autosign" { + type master; + file "expired-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has valid, fresh signatures. + */ +zone "fresh-sigs.autosign" { + type master; + file "fresh-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has unfresh signatures. + */ +zone "unfresh-sigs.autosign" { + type master; + file "unfresh-sigs.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has missing private ZSK. + */ +zone "zsk-missing.autosign" { + type master; + file "zsk-missing.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zone that has inactive ZSK. + */ +zone "zsk-retired.autosign" { + type master; + file "zsk-retired.autosign.db"; + dnssec-policy "autosign"; +}; + +/* + * Zones for testing ZSK Pre-Publication steps. + */ +zone "step1.zsk-prepub.autosign" { + type master; + file "step1.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step2.zsk-prepub.autosign" { + type master; + file "step2.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step3.zsk-prepub.autosign" { + type master; + file "step3.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step4.zsk-prepub.autosign" { + type master; + file "step4.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; +zone "step5.zsk-prepub.autosign" { + type master; + file "step5.zsk-prepub.autosign.db"; + dnssec-policy "zsk-prepub"; +}; + +/* + * Zones for testing KSK Double-KSK steps. + */ +zone "step1.ksk-doubleksk.autosign" { + type master; + file "step1.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step2.ksk-doubleksk.autosign" { + type master; + file "step2.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step3.ksk-doubleksk.autosign" { + type master; + file "step3.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step4.ksk-doubleksk.autosign" { + type master; + file "step4.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step5.ksk-doubleksk.autosign" { + type master; + file "step5.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; +zone "step6.ksk-doubleksk.autosign" { + type master; + file "step6.ksk-doubleksk.autosign.db"; + dnssec-policy "ksk-doubleksk"; +}; diff --git a/bin/tests/system/kasp/ns3/policies/autosign.conf b/bin/tests/system/kasp/ns3/policies/autosign.conf new file mode 100644 index 00000000000..3a0d028d009 --- /dev/null +++ b/bin/tests/system/kasp/ns3/policies/autosign.conf @@ -0,0 +1,66 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy "autosign" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 300; + + keys { + ksk key-directory P2Y 13; + zsk key-directory P1Y 13; + }; +}; + +dnssec-policy "zsk-prepub" { + + signatures-refresh P1W; + signatures-validity P2W; + signatures-validity-dnskey P2W; + + dnskey-ttl 3600; + publish-safety P1D; + retire-safety P2D; + + keys { + ksk key-directory P2Y 13; + zsk key-directory P30D 13; + }; + + zone-propagation-delay PT1H; + zone-max-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; + + keys { + ksk key-directory P60D 13; + zsk key-directory P1Y 13; + }; + + zone-propagation-delay PT1H; + zone-max-ttl 1d; + + parent-ds-ttl 3600; + parent-registration-delay P1D; + parent-propagation-delay PT1H; +}; diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index b2fcaa7edbc..b384fa730bd 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -22,6 +22,23 @@ setup() { echo $zone >> zones } +private_type_record() { + _zone=$1 + _algorithm=$2 + _keyfile=$3 + + _id=$(keyfile_to_key_id "$_keyfile") + + printf "%s. 0 IN TYPE65534 \# 5 %02x%04x0000\n" $_zone $_algorithm $_id +} + + +# Make lines shorter by storing key states in environment variables. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" + # # Set up zones that will be initially signed. # @@ -48,3 +65,294 @@ zone="pregenerated.kasp" $KEYGEN -k rsasha1 -l policies/kasp.conf $zone > keygen.out.$zone.1 2>&1 $KEYGEN -k rsasha1 -l policies/kasp.conf $zone > keygen.out.$zone.2 2>&1 +# +# Set up zones that are already signed. +# + +# These signatures are set to expire long in the past, update immediately. +setup expired-sigs.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2` +T="now-6mo" +$SETTIME -s -P $T -A $T -g $O -d $O $T -k $O $T -r $O $T $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $T -A $T -g $O -k $O $T -z $O $T $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# These signatures are still good, and can be reused. +setup fresh-sigs.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2` +T="now-6mo" +$SETTIME -s -P $T -A $T -g $O -d $O $T -k $O $T -r $O $T $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $T -A $T -g $O -k $O $T -z $O $T $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# These signatures are still good, but not fresh enough, update immediately. +setup unfresh-sigs.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2` +T="now-6mo" +$SETTIME -s -P $T -A $T -g $O -d $O $T -k $O $T -r $O $T $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $T -A $T -g $O -k $O $T -z $O $T $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1w -e now+1w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# These signatures are already expired, and the private ZSK is missing. +setup zsk-missing.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2` +T="now-6mo" +$SETTIME -s -P $T -A $T -g $O -d $O $T -k $O $T -r $O $T $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $T -A $T -g $O -k $O $T -z $O $T $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 +rm -f ${ZSK}.private + +# These signatures are already expired, and the private ZSK is retired. +setup zsk-retired.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 300 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 300 $zone 2> keygen.out.$zone.2` +T="now-6mo" +$SETTIME -s -P $T -A $T -g $O -d $O $T -k $O $T -r $O $T $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $T -A $T -g $O -k $O $T -z $O $T $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 +$SETTIME -s -I now -g HIDDEN $ZSK > 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 +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 3600 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.2` +TactN="now" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -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 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to pre-publish the successor ZSK. +setup step2.zsk-prepub.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 3600 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.2` +# According to RFC 7583: Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# Also: Ipub = Dprp + TTLkey (+publish-safety) +# so: Tact(N) = Tpub(N+1) + Ipub - Lzsk = now + (1d2h) - 30d = +# now + 26h - 30d = now − 694h +TactN="now-694h" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -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 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $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 +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 3600 $zone 2> keygen.out.$zone.1` +ZSK1=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.2` +ZSK2=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.3` +# According to RFC 7583: Tpub(N+1) <= Tact(N) + Lzsk - Ipub +# Also: Tret(N) = Tact(N+1) = Tact(N) + Lzsk +# so: Tact(N) = Tact(N+1) - Lzsk = now - 30d +# and: Tpub(N+1) = Tact(N+1) - Ipub = now - 26h +# and: Tret(N+1) = Tact(N+1) + Lzsk +TactN="now-30d" +TpubN1="now-26h" +TretN1="now+30d" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -I now -g $H -k $O $TactN -z $O $TactN $ZSK1 > settime.out.$zone.2 2>&1 +$SETTIME -s -S $ZSK1 -i 0 $ZSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A now -I $TretN1 -g $O -k $R $TpubN1 -z $H $TpubN1 $ZSK2 > settime.out.$zone.4 2>&1 +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK1 >> "$infile" +private_type_record $zone 13 $ZSK2 >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $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 +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 3600 $zone 2> keygen.out.$zone.1` +ZSK1=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.2` +ZSK2=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.3` +# According to RFC 7583: Tret(N) = Tact(N) + Lzsk +# Also: Tdea(N) = Tret(N) + Iret +# Also: Iret = Dsgn + Dprp + TTLsig (+retire-safety) +# so: Tact(N) = Tdea(N) - Iret - Lzsk = now - (1w1h1d2d) - 30d = +# now - (10d1h) - 30d = now - 961h +# and: Tret(N) = Tdea(N) - Iret = now - (10d1h) = now - 241h +# and: Tpub(N+1) = Tdea(N) - Iret - Ipub = now - (10d1h) - 26h = +# now - 267h +# and: Tact(N+1) = Tdea(N) - Iret = Tret(N) +# and: Tret(N+1) = Tdea(N) - Iret + Lzsk = now - (10d1h) + 30d = +# now + 479h +TactN="now-961h" +TretN="now-241h" +TpubN1="now-267h" +TactN1="${TretN}" +TretN1="now+479h" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -I $TretN -g $H -k $O $TactN -z $U $TretN $ZSK1 > settime.out.$zone.2 2>&1 +$SETTIME -s -S $ZSK1 -i 0 $ZSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A $TactN1 -I $TretN1 -g $O -k $O $TactN1 -z $R $TactN1 $ZSK2 > settime.out.$zone.4 2>&1 +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile" +$SIGNER -PS -x -s now-2w -e now-1mi -o $zone -O full -f $zonefile $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 +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 3600 $zone 2> keygen.out.$zone.1` +ZSK1=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.2` +ZSK2=`$KEYGEN -a ECDSAP256SHA256 -L 3600 $zone 2> keygen.out.$zone.3` +# Substract DNSKEY TTL from all the times (1h). +TactN="now-962h" +TretN="now-242h" +TpubN1="now-268h" +TactN1="${TretN}" +TretN1="now+478h" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -I $TretN -D now -g $H -k $U $TretN -z $U $TretN $ZSK1 > settime.out.$zone.2 2>&1 +$SETTIME -s -S $ZSK1 -i 0 $ZSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A $TactN1 -I $TretN1 -g $O -k $O $TactN1 -z $R $TactN1 $ZSK2 > settime.out.$zone.4 2>&1 +cat template.db.in "${KSK}.key" "${ZSK1}.key" "${ZSK2}.key" > "$infile" +private_type_record $zone 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK1 >> "$infile" +private_type_record $zone 13 $ZSK2 >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $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 +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 7200 $zone 2> keygen.out.$zone.2` +TactN="now" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -z $O $TactN $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" > "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# Step 2: +# It is time to submit the introduce the new KSK. +setup step2.ksk-doubleksk.autosign +KSK=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.1` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 7200 $zone 2> keygen.out.$zone.2` +# According to RFC 7583: Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC +# Also: IpubC = DprpC + TTLkey (+publish-safety) +# so: Tact(N) = Tpub(N+1) - Lksk + Dreg + IpubC = now - 60d + (1d3h) +# now - 1440h + 27h = now - 1413h +TactN="now-1413h" +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -r $O $TactN -d $O $TactN $KSK > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -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 13 $KSK >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# Step 3: +# It is time to submit the DS. +setup step3.ksk-doubleksk.autosign +KSK1=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.1` +KSK2=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.2` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 7200 $zone 2> keygen.out.$zone.3` +# According to RFC 7583: Tsbm(N+1) >= Trdy(N+1) +# Also: Tact(N+1) = Tsbm(N+1) + Dreg +# so: Tact(N) = Tsbm(N+1) + Dreg - Lksk = now + 1d - 60d = now - 59d +# and: Tret(N) = Tsbm(N+1) + Dreg = now + 1d +# and: Tpub(N+1) <= Tsbm(N+1) - IpubC = now + 27h +# and: Tret(N+1) = Tsbm(N+1) + Dreg + Lksk = 1d + 60d +TactN="now-59d" +TretN="now+1d" +TpubN1="now-27h" +TretN1="now+61d" +$SETTIME -s -P $TactN -A $TactN -I $TretN -g $H -k $O $TactN -r $O $TactN -d $O $TactN $KSK1 > settime.out.$zone.1 2>&1 +$SETTIME -s -S $KSK1 -i 0 $KSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A $TretN -I $TretN1 -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 $KSK2 > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -z $O $TactN $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK1 >> "$infile" +private_type_record $zone 13 $KSK2 >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 + +# Step 4: +# The DS should be swapped now. +setup step4.ksk-doubleksk.autosign +KSK1=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.1` +KSK2=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.2` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 7200 $zone 2> keygen.out.$zone.3` +# According to RFC 7583: Tdea(N) = Tret(N) + Iret +# Also: Tret(N) = Tsbm(N+1) + Dreg +# Also: Tact(N+1) = Tret(N) +# Also: Iret = DprpP + TTLds (+retire-safety) +# so: Tact(N) = Tdea(N) - Lksk - Iret = now - 60d - 2d2h = now - 1490h +# and: Tret(N) = Tdea(N) - Iret = now - 2d2h = 50h +# and: Tpub(N+1) = Tdea(N) - Iret - Dreg - IpubC = now - 50h - 1d - 1d3h = now - 101h +# and: Tsbm(N+1) = Tdea(N) - Iret - Dreg = now - 50h - 1d = now - 74h +# and: Tact(N+1) = Tret(N) +# and: Tret(N+1) = Tdea(N) + Lksk - Iret = now + 60d - 2d2h = now + 1390h +TactN="now-1490h" +TretN="now-50h" +TpubN1="now-101h" +TsbmN1="now-74h" +TactN1="${TretN}" +TretN1="now+1390h" +$SETTIME -s -P $TactN -A $TactN -I $TretN -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 $KSK1 > settime.out.$zone.1 2>&1 +$SETTIME -s -S $KSK1 -i 0 $KSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A $TactN1 -I $TretN1 -g $O -k $O $TsbmN1 -r $O $TsbmN1 -d $R $TsbmN1 $KSK2 > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -z $O $TactN $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK1 >> "$infile" +private_type_record $zone 13 $KSK2 >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $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 +KSK1=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.1` +KSK2=`$KEYGEN -a ECDSAP256SHA256 -f KSK -L 7200 $zone 2> keygen.out.$zone.2` +ZSK=`$KEYGEN -a ECDSAP256SHA256 -L 7200 $zone 2> keygen.out.$zone.3` +# Substract DNSKEY TTL from all the times (2h). +TactN="now-1492h" +TretN="now-52h" +TpubN1="now-102h" +TsbmN1="now-75h" +TactN1="${TretN}" +TretN1="now+1388h" +$SETTIME -s -P $TactN -A $TactN -I $TretN -g $H -k $U $TretN -r $U $TretN -d $H $TretN $KSK1 > settime.out.$zone.1 2>&1 +$SETTIME -s -S $KSK1 -i 0 $KSK2 > settime.out.$zone.3 2>&1 +$SETTIME -s -P $TpubN1 -A $TactN1 -I $TretN1 -g $O -k $O $TactN1 -r $O $TactN1 -d $O $TactN1 $KSK2 > settime.out.$zone.1 2>&1 +$SETTIME -s -P $TactN -A $TactN -g $O -k $O $TactN -z $O $TactN $ZSK > settime.out.$zone.2 2>&1 +cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" > "$infile" +private_type_record $zone 13 $KSK1 >> "$infile" +private_type_record $zone 13 $KSK2 >> "$infile" +private_type_record $zone 13 $ZSK >> "$infile" +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index f4b06b91ef7..6bd1d3db948 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -1080,5 +1080,407 @@ dnssec_verify # TODO: ED25519 and ED448. +# +# Zone: expired-sigs.autosign. +# +zone_properties "ns3" "expired-sigs.autosign" "autosign" "300" "2" +# Both KSK and ZSK stay OMNIPRESENT. +key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY1" "published" "active" "retired" "none" "none" +key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent" +key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" +key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none" +key_timings "KEY2" "published" "active" "retired" "none" "none" +# Expect only two keys. +key_clear "KEY3" + +check_keys +check_apex +check_subdomain +dnssec_verify + +# Verify all signatures have been refreshed. +check_rrsig_refresh() { + # Apex. + _qtypes="DNSKEY SOA NS NSEC" + for _qtype in $_qtypes + do + n=$((n+1)) + echo_i "check ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)" + ret=0 + dig_with_opts $ZONE @10.53.0.3 $_qtype > dig.out.$DIR.test$n || log_error "dig ${ZONE} ${_qtype} failed" + grep "status: NOERROR" dig.out.$DIR.test$n > /dev/null || log_error "mismatch status in DNS response" + grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" dig.out.$DIR.test$n > rrsig.out.$ZONE.$_qtype || log_error "missing RRSIG (${_qtype}) record in response" + # If this exact RRSIG is also in the zone file it is not refreshed. + _rrsig=`cat rrsig.out.$ZONE.$_qtype` + grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + done + + # Below apex. + _labels="a b c ns3" + for _label in $_labels; + do + _qtypes="A NSEC" + for _qtype in $_qtypes + do + n=$((n+1)) + echo_i "check ${_label} ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)" + ret=0 + dig_with_opts "${_label}.${ZONE}" @10.53.0.3 $_qtype > dig.out.$DIR.test$n || log_error "dig ${_label}.${ZONE} ${_qtype} failed" + grep "status: NOERROR" dig.out.$DIR.test$n > /dev/null || log_error "mismatch status in DNS response" + grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" dig.out.$DIR.test$n > rrsig.out.$ZONE.$_qtype || log_error "missing RRSIG (${_qtype}) record in response" + _rrsig=`cat rrsig.out.$ZONE.$_qtype` + grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + done + done +} + +check_rrsig_refresh + +# +# Zone: fresh-sigs.autosign. +# +zone_properties "ns3" "fresh-sigs.autosign" "autosign" "300" "2" +# key_properties, key_timings and key_states same as above. +check_keys +check_apex +check_subdomain +dnssec_verify + +# Verify signature reuse. +check_rrsig_reuse() { + # Apex. + _qtypes="NS NSEC" + for _qtype in $_qtypes + do + n=$((n+1)) + echo_i "check ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)" + ret=0 + dig_with_opts $ZONE @10.53.0.3 $_qtype > dig.out.$DIR.test$n || log_error "dig ${ZONE} ${_qtype} failed" + grep "status: NOERROR" dig.out.$DIR.test$n > /dev/null || log_error "mismatch status in DNS response" + grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" dig.out.$DIR.test$n > rrsig.out.$ZONE.$_qtype || log_error "missing RRSIG (${_qtype}) record in response" + # If this exact RRSIG is also in the zone file it is not refreshed. + _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < rrsig.out.$ZONE.$_qtype) + grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + done + + # Below apex. + _labels="a b c ns3" + for _label in $_labels; + do + _qtypes="A NSEC" + for _qtype in $_qtypes + do + n=$((n+1)) + echo_i "check ${_label} ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)" + ret=0 + dig_with_opts "${_label}.${ZONE}" @10.53.0.3 $_qtype > dig.out.$DIR.test$n || log_error "dig ${_label}.${ZONE} ${_qtype} failed" + grep "status: NOERROR" dig.out.$DIR.test$n > /dev/null || log_error "mismatch status in DNS response" + grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" dig.out.$DIR.test$n > rrsig.out.$ZONE.$_qtype || log_error "missing RRSIG (${_qtype}) record in response" + _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < rrsig.out.$ZONE.$_qtype) + grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}" + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) + done + done +} + +check_rrsig_reuse + +# +# Zone: unfresh-sigs.autosign. +# +zone_properties "ns3" "unfresh-sigs.autosign" "autosign" "300" "2" +# key_properties, key_timings and key_states same as above. +check_keys +check_apex +check_subdomain +dnssec_verify +check_rrsig_refresh + +# +# Zone: zsk-missing.autosign. +# +zone_properties "ns3" "zsk-missing.autosign" "autosign" "300" "2" +# KSK stays OMNIPRESENT. +key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY1" "published" "active" "retired" "none" "none" +key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent" +# key_properties, key_timings and key_states same as above. +# TODO + +# +# Zone: zsk-retired.autosign. +# +zone_properties "ns3" "zsk-retired.autosign" "autosign" "300" "3" +# KSK properties, timings and states same as above. +# The ZSK goal is set to HIDDEN but records stay OMNIPRESENT until the new ZSK +# is active. +key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY2" "published" "active" "retired" "none" "none" +key_states "KEY2" "hidden" "omnipresent" "omnipresent" "none" "none" +# A new ZSK should be introduced, so expect a key with goal OMNIPRESENT, +# the DNSKEY introduced (RUMOURED) and the signatures HIDDEN. +key_properties "KEY3" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "no" +key_timings "KEY3" "published" "active" "retired" "none" "none" +key_states "KEY3" "omnipresent" "rumoured" "hidden" "none" "none" + +# +# Testing ZSK Pre-Publication rollover. +# + +# +# Zone: step1.zsk-prepub.autosign. +# +zone_properties "ns3" "step1.zsk-prepub.autosign" "zsk-prepub" "3600" "2" +# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. +key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY1" "published" "active" "retired" "none" "none" +key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent" +key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" +key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none" +key_timings "KEY2" "published" "active" "retired" "none" "none" +# Initially only two keys. +key_clear "KEY3" +check_keys +check_apex +check_subdomain +dnssec_verify + +check_next_key_event() { + _expect=$1 + + n=$((n+1)) + echo_i "check next key event for zone ${ZONE} ($n)" + ret=0 + grep "zone ${ZONE}.*: next key event in .* seconds" "${DIR}/named.run" > keyevent.out.$ZONE.test$n || log_error "no next key event for zone ${ZONE}" + + _time=$(awk '{print $10}' < keyevent.out.$ZONE.test$n) + + # The next key event time must within 10 seconds of the + # expected time. + _expectmin=$((_expect-10)) + _expectmax=$((_expect+10)) + + test $_expectmin -le $_time || log_error "bad next key event time ${_time} for zone ${ZONE} (expect ${_expect})" + test $_expectmax -ge $_time || log_error "bad next key event time ${_time} for zone ${ZONE} (expect ${_expect})" + + test "$ret" -eq 0 || echo_i "failed" + status=$((status+ret)) +} + +# 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. +# +zone_properties "ns3" "step2.zsk-prepub.autosign" "zsk-prepub" "3600" "3" +# KSK (KEY1) doesn't change. +# ZSK (KEY2) remains active, no change in properties/timings/states. +# New ZSK (KEY3) is prepublished. +key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" +key_states "KEY3" "omnipresent" "rumoured" "hidden" "none" "none" +key_timings "KEY3" "published" "active" "retired" "none" "none" +check_keys +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. +# +zone_properties "ns3" "step3.zsk-prepub.autosign" "zsk-prepub" "3600" "3" +# KSK (KEY1) doesn't change. +# ZSK (KEY2) properties and timing metadata same as above. +# ZSK (KEY2) no longer is actively signing, RRSIG state in UNRETENTIVE. +# New ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. +key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" +key_states "KEY2" "hidden" "omnipresent" "unretentive" "none" "none" + +key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" +key_states "KEY3" "omnipresent" "omnipresent" "rumoured" "none" "none" +check_keys +check_apex +# Subdomain still has good signatures of ZSK (KEY2) +key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" +key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" +check_subdomain +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. +# +zone_properties "ns3" "step4.zsk-prepub.autosign" "zsk-prepub" "3600" "3" +# KSK (KEY1) doesn't change. +# ZSK (KEY2) properties and timing metadata same as above. +# ZSK (KEY2) DNSKEY is no longer needed. +# ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED. +key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" +key_states "KEY2" "hidden" "unretentive" "hidden" "none" "none" +key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" +key_states "KEY3" "omnipresent" "omnipresent" "omnipresent" "none" "none" +check_keys +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. +# +zone_properties "ns3" "step5.zsk-prepub.autosign" "zsk-prepub" "3600" "3" +# KSK (KEY1) doesn't change. +# ZSK (KEY2) properties and timing metadata same as above. +# ZSK (KEY3) DNSKEY is now completely HIDDEN and removed. +key_timings "KEY2" "published" "active" "retired" "none" "removed" +key_states "KEY2" "hidden" "hidden" "hidden" "none" "none" +# ZSK (KEY3) remains actively signing, staying in OMNIPRESENT. +check_keys +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 + +# +# Testing KSK Double-KSK rollover. +# + +# +# Zone: step1.ksk-doubleksk.autosign. +# +zone_properties "ns3" "step1.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "2" +# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. +key_properties "KEY1" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY1" "published" "active" "retired" "none" "none" +key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent" +key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" +key_timings "KEY2" "published" "active" "retired" "none" "none" +key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none" +# Initially only two keys. +key_clear "KEY3" +check_keys +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 - DS registration delay. The +# prepublication time is DNSKEY TTL plus publish safety plus the zone +# propagation delay. For the ksk-doubleksk policy that means: +# 60d - (1d3h) - (1d) = 5000400 seconds. +check_next_key_event 5000400 + +# +# Zone: step2.ksk-doubleksk.autosign. +# +zone_properties "ns3" "step2.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" +# ZSK (KEY2) doesn't change. +# KSK (KEY1) remains active, no change in properties/timings/states. +# New KSK (KEY3) is prepublished (and signs DNSKEY RRset). +key_properties "KEY3" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "yes" +key_states "KEY3" "omnipresent" "rumoured" "none" "rumoured" "hidden" +key_timings "KEY3" "published" "active" "retired" "none" "none" +check_keys +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. +# +zone_properties "ns3" "step3.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" +# ZSK (KEY2) doesn't change. +# KSK (KEY1) DS will be removed, so it is UNRETENTIVE. +key_states "KEY1" "hidden" "omnipresent" "none" "omnipresent" "unretentive" +# New KSK (KEY3) has its DS submitted. +key_states "KEY3" "omnipresent" "omnipresent" "none" "omnipresent" "rumoured" +check_keys +check_apex +check_subdomain +dnssec_verify + +# 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 +# registration delay plus 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: 1d + 1h + 3600s + 2d = 3d2h = +# 266400 seconds. +check_next_key_event 266400 + +# +# Zone: step4.ksk-doubleksk.autosign. +# +zone_properties "ns3" "step4.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" +# ZSK (KEY2) doesn't change. +# KSK (KEY1) DNSKEY can be removed. +key_properties "KEY1" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "no" +key_states "KEY1" "hidden" "unretentive" "none" "unretentive" "hidden" +# New KSK (KEY3) DS is now OMNIPRESENT. +key_states "KEY3" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent" +check_keys +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. +# +zone_properties "ns3" "step5.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" +# ZSK (KEY2) doesn't change. +# KSK (KEY1) DNSKEY is now HIDDEN. +key_states "KEY1" "hidden" "hidden" "none" "hidden" "hidden" +# New KSK (KEY3) stays OMNIPRESENT. +check_keys +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 Dreg minus Iret minus DNSKEY TTL. For the +# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h = +# 5184000 - 97200 - 86400 - 180000 - 7200 = 4813200 seconds. +check_next_key_event 4813200 + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1