diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 0ea1c774ea..51bf22f089 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -16,7 +16,7 @@ from pathlib import Path import re import subprocess import time -from typing import Dict, List, Optional, Union +from typing import Dict, List, Optional, Tuple, Union from datetime import datetime, timedelta, timezone @@ -332,6 +332,55 @@ class Key: ) return value + def get_signing_state( + self, offline_ksk=False, zsk_missing=False + ) -> Tuple[bool, bool]: + """ + This returns the signing state derived from the key states, KRRSIGState + and ZRRSIGState. + + If 'offline_ksk' is set to True, we determine the signing state from + the timing metadata. If 'zsigning' is True, ensure the current time is + between the Active and Retired timing metadata. + + 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. + """ + # Fetch key timing metadata. + now = KeyTimingMetadata.now() + activate = self.get_timing("Activate") + assert activate is not None # to silence mypy - its implied by line above + inactive = self.get_timing("Inactive", must_exist=False) + + active = now >= activate + retired = inactive is not None and inactive <= now + signing = active and not retired + + # Fetch key state metadata. + krrsigstate = self.get_metadata("KRRSIGState", must_exist=False) + ksigning = krrsigstate in ["rumoured", "omnipresent"] + zrrsigstate = self.get_metadata("ZRRSIGState", must_exist=False) + zsigning = zrrsigstate in ["rumoured", "omnipresent"] + + if ksigning: + assert self.is_ksk() + if zsigning: + assert self.is_zsk() + + # If the ZSK private key file is missing, revers the zone signing state. + if zsk_missing: + zsigning = not zsigning + + # If testing offline KSK, retrieve the signing state from the key timing + # metadata. + if offline_ksk and signing and self.is_zsk(): + assert zsigning + if offline_ksk and signing and self.is_ksk(): + ksigning = signing + + return ksigning, zsigning + def ttl(self) -> int: with open(self.keyfile, "r", encoding="utf-8") as file: for line in file: @@ -772,8 +821,9 @@ def check_dnssecstatus(server, zone, keys, policy=None, view=None): assert f"key: {key.tag}" in response -def _check_signatures(signatures, covers, fqdn, keys): - now = KeyTimingMetadata.now() +def _check_signatures( + signatures, covers, fqdn, keys, offline_ksk=False, zsk_missing=False +): numsigs = 0 zrrsig = True if covers in [dns.rdatatype.DNSKEY, dns.rdatatype.CDNSKEY, dns.rdatatype.CDS]: @@ -781,23 +831,16 @@ def _check_signatures(signatures, covers, fqdn, keys): krrsig = not zrrsig for key in keys: - activate = key.get_timing("Activate") - inactive = key.get_timing("Inactive", must_exist=False) + ksigning, zsigning = key.get_signing_state( + offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) - active = now >= activate - retired = inactive is not None and inactive <= now - signing = active and not retired alg = key.get_metadata("Algorithm") rtype = dns.rdatatype.to_text(covers) expect = rf"IN RRSIG {rtype} {alg} (\d) (\d+) (\d+) (\d+) {key.tag} {fqdn}" - if not signing: - for rrsig in signatures: - assert re.search(expect, rrsig) is None - continue - - if zrrsig and key.is_zsk(): + if zrrsig and zsigning: has_rrsig = False for rrsig in signatures: if re.search(expect, rrsig) is not None: @@ -806,11 +849,11 @@ def _check_signatures(signatures, covers, fqdn, keys): assert has_rrsig, f"Expected signature but not found: {expect}" numsigs += 1 - if zrrsig and not key.is_zsk(): + if zrrsig and not zsigning: for rrsig in signatures: assert re.search(expect, rrsig) is None - if krrsig and key.is_ksk(): + if krrsig and ksigning: has_rrsig = False for rrsig in signatures: if re.search(expect, rrsig) is not None: @@ -819,14 +862,16 @@ def _check_signatures(signatures, covers, fqdn, keys): assert has_rrsig, f"Expected signature but not found: {expect}" numsigs += 1 - if krrsig and not key.is_ksk(): + if krrsig and not ksigning: for rrsig in signatures: assert re.search(expect, rrsig) is None return numsigs -def check_signatures(rrset, covers, fqdn, ksks, zsks): +def check_signatures( + rrset, covers, fqdn, ksks, zsks, offline_ksk=False, zsk_missing=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 # correct role. @@ -840,8 +885,12 @@ def check_signatures(rrset, covers, fqdn, ksks, zsks): rrsig = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" signatures.append(rrsig) - numsigs += _check_signatures(signatures, covers, fqdn, ksks) - numsigs += _check_signatures(signatures, covers, fqdn, zsks) + numsigs += _check_signatures( + signatures, covers, fqdn, ksks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) + numsigs += _check_signatures( + signatures, covers, fqdn, zsks, offline_ksk=offline_ksk, zsk_missing=zsk_missing + ) assert numsigs == len(signatures) @@ -965,7 +1014,9 @@ def _query_rrset(server, fqdn, qtype, tsig=None): return rrs, rrsigs -def check_apex(server, zone, ksks, zsks, tsig=None): +def check_apex( + server, zone, ksks, zsks, offline_ksk=False, zsk_missing=False, tsig=None +): # Test the apex of a zone. This checks that the SOA and DNSKEY RRsets # are signed correctly and with the appropriate keys. fqdn = f"{zone}." @@ -973,30 +1024,44 @@ def check_apex(server, zone, ksks, zsks, tsig=None): # test dnskey query dnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.DNSKEY, tsig=tsig) check_dnskeys(dnskeys, ksks, zsks) - check_signatures(rrsigs, dns.rdatatype.DNSKEY, fqdn, ksks, zsks) + check_signatures( + rrsigs, dns.rdatatype.DNSKEY, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) # test soa query soa, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.SOA, tsig=tsig) assert len(soa) == 1 assert f"{zone}. {DEFAULT_TTL} IN SOA" in soa[0].to_text() - check_signatures(rrsigs, dns.rdatatype.SOA, fqdn, ksks, zsks) + check_signatures( + rrsigs, + dns.rdatatype.SOA, + fqdn, + ksks, + zsks, + offline_ksk=offline_ksk, + zsk_missing=zsk_missing, + ) # test cdnskey query cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig) check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) if len(cdnskeys) > 0: assert len(rrsigs) > 0 - check_signatures(rrsigs, dns.rdatatype.CDNSKEY, fqdn, ksks, zsks) + check_signatures( + rrsigs, dns.rdatatype.CDNSKEY, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) # test cds query cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig) check_cds(cds, ksks) if len(cds) > 0: assert len(rrsigs) > 0 - check_signatures(rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks) + check_signatures( + rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) -def check_subdomain(server, zone, ksks, zsks, tsig=None): +def check_subdomain(server, zone, ksks, zsks, offline_ksk=False, tsig=None): # Test an RRset below the apex and verify it is signed correctly. fqdn = f"{zone}." qname = f"a.{zone}." @@ -1014,7 +1079,7 @@ def check_subdomain(server, zone, ksks, zsks, tsig=None): else: assert match in rrset.to_text() - check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + check_signatures(rrsigs, qtype, fqdn, ksks, zsks, offline_ksk=offline_ksk) def verify_update_is_signed(server, fqdn, qname, qtype, rdata, ksks, zsks, tsig=None): @@ -1046,6 +1111,98 @@ def verify_update_is_signed(server, fqdn, qname, qtype, rdata, ksks, zsks, tsig= return True +def verify_rrsig_is_refreshed( + server, fqdn, zonefile, qname, qtype, ksks, zsks, tsig=None +): + """ + Verify signature for RRset has been refreshed. + """ + response = _query(server, qname, qtype, tsig=tsig) + + if response.rcode() != dns.rcode.NOERROR: + return False + + rrtype = dns.rdatatype.to_text(qtype) + match = f"{qname}. {DEFAULT_TTL} IN {rrtype}" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + elif not match in rrset.to_text(): + return False + + if len(rrsigs) == 0: + return False + + tmp_zonefile = f"{zonefile}.tmp" + isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + "-o", + tmp_zonefile, + "-f", + "raw", + fqdn, + zonefile, + ], + ) + + zone = dns.zone.from_file(tmp_zonefile, fqdn) + for rrsig in rrsigs: + if isctest.util.zone_contains(zone, rrsig): + return False + + # Zone is updated, ready to verify the signatures. + check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + + return True + + +def verify_rrsig_is_reused(server, fqdn, zonefile, qname, qtype, ksks, zsks, tsig=None): + """ + Verify signature for RRset has been reused. + """ + response = _query(server, qname, qtype, tsig=tsig) + + assert response.rcode() == dns.rcode.NOERROR + + rrtype = dns.rdatatype.to_text(qtype) + match = f"{qname}. {DEFAULT_TTL} IN {rrtype}" + rrsigs = [] + for rrset in response.answer: + if rrset.match( + dns.name.from_text(qname), dns.rdataclass.IN, dns.rdatatype.RRSIG, qtype + ): + rrsigs.append(rrset) + else: + assert match in rrset.to_text() + + tmp_zonefile = f"{zonefile}.tmp" + isctest.run.cmd( + [ + os.environ["CHECKZONE"], + "-D", + "-q", + "-o", + tmp_zonefile, + "-f", + "raw", + fqdn, + zonefile, + ], + ) + + zone = dns.zone.from_file(tmp_zonefile, dns.name.from_text(fqdn), relativize=False) + for rrsig in rrsigs: + assert isctest.util.zone_contains(zone, rrsig) + + check_signatures(rrsigs, qtype, fqdn, ksks, zsks) + + def next_key_event_equals(server, zone, next_event): if next_event is None: # No next key event check. @@ -1140,6 +1297,7 @@ def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]: Then, optional data for specific tests may follow: - "goal", "dnskey", "krrsig", "zrrsig", "ds", followed by a value, sets the given state to the specific value + - "missing", set if the private key file for this key is not available. - "offset", an offset for testing key rollover timings """ proplist = [] @@ -1190,6 +1348,8 @@ def policy_to_properties(ttl, keys: List[str]) -> List[KeyProperties]: elif line[i].startswith("offset:"): keyval = line[i].split(":") keyprop.properties["offset"] = timedelta(seconds=int(keyval[1])) + elif line[i] == "missing": + keyprop.properties["private"] = False else: assert False, f"undefined optional data {line[i]}" diff --git a/bin/tests/system/isctest/mark.py b/bin/tests/system/isctest/mark.py index b1a720227a..facf1038d5 100644 --- a/bin/tests/system/isctest/mark.py +++ b/bin/tests/system/isctest/mark.py @@ -56,6 +56,12 @@ def with_tsan(*args): # pylint: disable=unused-argument return feature_test("--tsan") +def with_algorithm(name: str): + key = f"{name}_SUPPORTED" + assert key in os.environ, f"{key} env variable undefined" + return pytest.mark.skipif(os.getenv(key) != "1", reason=f"{name} is not supported") + + without_fips = pytest.mark.skipif( feature_test("--have-fips-mode"), reason="FIPS support enabled in the build" ) diff --git a/bin/tests/system/kasp/ns3/setup.sh b/bin/tests/system/kasp/ns3/setup.sh index 6985b6f7e2..b6062dad22 100644 --- a/bin/tests/system/kasp/ns3/setup.sh +++ b/bin/tests/system/kasp/ns3/setup.sh @@ -200,13 +200,14 @@ $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" $SIGNER -PS -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}" $infile >signer.out.$zone.1 2>&1 +# Treat the next zones as if they were signed six months ago. +T="now-6mo" +keytimes="-P $T -A $T" + # These signatures are set to expire long in the past, update immediately. setup expired-sigs.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" @@ -217,19 +218,18 @@ $SIGNER -PS -x -s now-2mo -e now-1mo -o $zone -O raw -f "${zonefile}.signed" $in # The DNSKEY's TTLs do not match the policy. setup dnskey-ttl-mismatch.autosign -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 $zsktimes $zone 2>keygen.out.$zone.2) +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 30 $keytimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $T -z $O $T "$ZSK " >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" cp $infile $zonefile $SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 # These signatures are still good, and can be reused. setup fresh-sigs.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" @@ -240,11 +240,8 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil # These signatures are still good, but not fresh enough, update immediately. setup unfresh-sigs.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" @@ -255,11 +252,13 @@ $SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infil # These signatures are still good, but the private KSK is missing. setup ksk-missing.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" +# KSK file will be gone missing, so we set expected times during setup. +TI="now+550d" # Lifetime of 2 years minus 6 months equals 550 days +TD="now+13226h" # 550 days plus retire time of 1 day 2 hours equals 13226 hours +TS="now-257755mi" # 6 months minus 1 day, 5 minutes equals 257695 minutes +ksktimes="$keytimes -P sync $TS -I $TI -D $TD" KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" @@ -274,10 +273,11 @@ rm -f "${KSK}".private # These signatures are still good, but the private ZSK is missing. setup zsk-missing.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +# ZSK file will be gone missing, so we set expected times during setup. +TI="now+185d" # Lifetime of 1 year minus 6 months equals 185 days +TD="now+277985mi" # 185 days plus retire time (sign delay, retire safety, propagation, zone TTL) +zsktimes="$keytimes -I $TI -D $TD" +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 @@ -294,11 +294,8 @@ rm -f "${ZSK}".private # These signatures are still good, but the key files will be removed # before a second run of reconfiguring keys. setup keyfiles-missing.autosign -T="now-6mo" -ksktimes="-P $T -A $T -P sync $T" -zsktimes="-P $T -A $T" -KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $zsktimes $zone 2>keygen.out.$zone.2) +KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $keytimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 $keytimes $zone 2>keygen.out.$zone.2) $SETTIME -s -g $O -d $O $T -k $O $T -r $O $T "$KSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" @@ -309,7 +306,6 @@ $SIGNER -S -x -s now-1w -e now+1w -o $zone -O raw -f "${zonefile}.signed" $infil # These signatures are already expired, and the private ZSK is retired. setup zsk-retired.autosign -T="now-6mo" ksktimes="-P $T -A $T -P sync $T" zsktimes="-P $T -A $T -I now" KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 300 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index ca294bab01..11335fdfa4 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -400,462 +400,10 @@ set_keytimes_algorithm_policy() { set_addkeytime "KEY3" "REMOVED" "${retired}" 867900 } -# -# Zone: rsasha1.kasp. -# -if [ $RSASHA1_SUPPORTED = 1 ]; then - set_zone "rsasha1.kasp" - set_policy "rsasha1" "3" "1234" - set_server "ns3" "10.53.0.3" - # Key properties. - key_clear "KEY1" - set_keyrole "KEY1" "ksk" - set_keylifetime "KEY1" "315360000" - set_keyalgorithm "KEY1" "5" "RSASHA1" "2048" - set_keysigning "KEY1" "yes" - set_zonesigning "KEY1" "no" - - key_clear "KEY2" - set_keyrole "KEY2" "zsk" - set_keylifetime "KEY2" "157680000" - set_keyalgorithm "KEY2" "5" "RSASHA1" "2048" - set_keysigning "KEY2" "no" - set_zonesigning "KEY2" "yes" - - key_clear "KEY3" - set_keyrole "KEY3" "zsk" - set_keylifetime "KEY3" "31536000" - set_keyalgorithm "KEY3" "5" "RSASHA1" "2000" - set_keysigning "KEY3" "no" - set_zonesigning "KEY3" "yes" - - # KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait. - # ZSK: DNSKEY, RRSIG (zsk) published. - set_keystate "KEY1" "GOAL" "omnipresent" - set_keystate "KEY1" "STATE_DNSKEY" "rumoured" - set_keystate "KEY1" "STATE_KRRSIG" "rumoured" - set_keystate "KEY1" "STATE_DS" "hidden" - - set_keystate "KEY2" "GOAL" "omnipresent" - set_keystate "KEY2" "STATE_DNSKEY" "rumoured" - set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" - - set_keystate "KEY3" "GOAL" "omnipresent" - set_keystate "KEY3" "STATE_DNSKEY" "rumoured" - set_keystate "KEY3" "STATE_ZRRSIG" "rumoured" - # Three keys only. - key_clear "KEY4" - - check_keys - check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - set_keytimes_algorithm_policy - check_keytimes - check_apex - check_subdomain - dnssec_verify -fi - -# -# Zone: unlimited.kasp. -# -set_zone "unlimited.kasp" -set_policy "unlimited" "1" "1234" -set_server "ns3" "10.53.0.3" -key_clear "KEY1" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_csk_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: keystore.kasp. -# -set_zone "keystore.kasp" -set_policy "keystore" "2" "303" -set_server "ns3" "10.53.0.3" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "0" -set_keydir "KEY1" "ns3/ksk" -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" "0" -set_keydir "KEY2" "ns3/zsk" -set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" - -# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait. -# ZSK: DNSKEY, RRSIG (zsk) published. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "rumoured" -set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" -# Two keys only. -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# Reuse set_keytimes_csk_policy to set the KEY1 keytimes. -set_keytimes_csk_policy -created=$(key_get KEY2 CREATED) -set_keytime "KEY2" "PUBLISHED" "${created}" -set_keytime "KEY2" "ACTIVE" "${created}" -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: inherit.kasp. -# -set_zone "inherit.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" - -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "315360000" -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -key_clear "KEY2" -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "157680000" -set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" - -key_clear "KEY3" -set_keyrole "KEY3" "zsk" -set_keylifetime "KEY3" "31536000" -set_keyalgorithm "KEY3" "8" "RSASHA256" "3072" -set_keysigning "KEY3" "no" -set_zonesigning "KEY3" "yes" -# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait. -# ZSK: DNSKEY, RRSIG (zsk) published. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "rumoured" -set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" - -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_ZRRSIG" "rumoured" -# Three keys only. -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: dnssec-keygen.kasp. -# -set_zone "dnssec-keygen.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: some-keys.kasp. -# -set_zone "some-keys.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy "pregenerated" -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: pregenerated.kasp. -# -# There are more pregenerated keys than needed, hence the number of keys is -# six, not three. -set_zone "pregenerated.kasp" -set_policy "rsasha256" "6" "1234" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy "pregenerated" -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: rumoured.kasp. -# -# There are three keys in rumoured state. -set_zone "rumoured.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -# Activation date is a day later. -set_addkeytime "KEY1" "ACTIVE" $(key_get KEY1 ACTIVE) 86400 -set_addkeytime "KEY1" "RETIRED" $(key_get KEY1 RETIRED) 86400 -set_addkeytime "KEY1" "REMOVED" $(key_get KEY1 REMOVED) 86400 -set_addkeytime "KEY2" "ACTIVE" $(key_get KEY2 ACTIVE) 86400 -set_addkeytime "KEY2" "RETIRED" $(key_get KEY2 RETIRED) 86400 -set_addkeytime "KEY2" "REMOVED" $(key_get KEY2 REMOVED) 86400 -set_addkeytime "KEY3" "ACTIVE" $(key_get KEY3 ACTIVE) 86400 -set_addkeytime "KEY3" "RETIRED" $(key_get KEY3 RETIRED) 86400 -set_addkeytime "KEY3" "REMOVED" $(key_get KEY3 REMOVED) 86400 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: secondary.kasp. -# -set_zone "secondary.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Update zone. -n=$((n + 1)) -echo_i "check that we correctly sign the zone after IXFR for zone ${ZONE} ($n)" -ret=0 -cp ns2/secondary.kasp.db.in2 ns2/secondary.kasp.db -rndccmd 10.53.0.2 reload "$ZONE" >/dev/null || log_error "rndc reload zone ${ZONE} failed" - -_wait_for_done_subdomains() { - ret=0 - dig_with_opts "a.${ZONE}" "@${SERVER}" A >"dig.out.$DIR.test$n.a" || return 1 - grep "status: NOERROR" "dig.out.$DIR.test$n.a" >/dev/null || return 1 - grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" >/dev/null || return 1 - check_signatures $_qtype "dig.out.$DIR.test$n.a" "ZSK" - if [ $ret -gt 0 ]; then return $ret; fi - - dig_with_opts "d.${ZONE}" "@${SERVER}" A >"dig.out.$DIR.test$n.d" || return 1 - grep "status: NOERROR" "dig.out.$DIR.test$n.d" >/dev/null || return 1 - grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n.d" >/dev/null || return 1 - check_signatures $_qtype "dig.out.$DIR.test$n.d" "ZSK" - return $ret -} -retry_quiet 5 _wait_for_done_subdomains || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - # TODO: we might want to test: # - configuring a zone with too many active keys (should trigger retire). # - configuring a zone with keys not matching the policy. -# -# Zone: rsasha1-nsec3.kasp. -# -if [ $RSASHA1_SUPPORTED = 1 ]; then - set_zone "rsasha1-nsec3.kasp" - set_policy "rsasha1-nsec3" "3" "1234" - set_server "ns3" "10.53.0.3" - # Key properties. - set_keyalgorithm "KEY1" "7" "NSEC3RSASHA1" "2048" - set_keyalgorithm "KEY2" "7" "NSEC3RSASHA1" "2048" - set_keyalgorithm "KEY3" "7" "NSEC3RSASHA1" "2000" - # Key timings and states same as above. - - check_keys - check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - set_keytimes_algorithm_policy - check_keytimes - check_apex - check_subdomain - dnssec_verify -fi - -# -# Zone: rsasha256.kasp. -# -set_zone "rsasha256.kasp" -set_policy "rsasha256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" -set_keyalgorithm "KEY3" "8" "RSASHA256" "3072" -# Key timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: rsasha512.kasp. -# -set_zone "rsasha512.kasp" -set_policy "rsasha512" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyalgorithm "KEY1" "10" "RSASHA512" "2048" -set_keyalgorithm "KEY2" "10" "RSASHA512" "2048" -set_keyalgorithm "KEY3" "10" "RSASHA512" "3072" -# Key timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: ecdsa256.kasp. -# -set_zone "ecdsa256.kasp" -set_policy "ecdsa256" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256" -set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256" -# Key timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: ecdsa512.kasp. -# -set_zone "ecdsa384.kasp" -set_policy "ecdsa384" "3" "1234" -set_server "ns3" "10.53.0.3" -# Key properties. -set_keyalgorithm "KEY1" "14" "ECDSAP384SHA384" "384" -set_keyalgorithm "KEY2" "14" "ECDSAP384SHA384" "384" -set_keyalgorithm "KEY3" "14" "ECDSAP384SHA384" "384" -# Key timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_algorithm_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: ed25519.kasp. -# -if [ $ED25519_SUPPORTED = 1 ]; then - set_zone "ed25519.kasp" - set_policy "ed25519" "3" "1234" - set_server "ns3" "10.53.0.3" - # Key properties. - set_keyalgorithm "KEY1" "15" "ED25519" "256" - set_keyalgorithm "KEY2" "15" "ED25519" "256" - set_keyalgorithm "KEY3" "15" "ED25519" "256" - # Key timings and states same as above. - - check_keys - check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - set_keytimes_algorithm_policy - check_keytimes - check_apex - check_subdomain - dnssec_verify -fi - -# -# Zone: ed448.kasp. -# -if [ $ED448_SUPPORTED = 1 ]; then - set_zone "ed448.kasp" - set_policy "ed448" "3" "1234" - set_server "ns3" "10.53.0.3" - # Key properties. - set_keyalgorithm "KEY1" "16" "ED448" "456" - set_keyalgorithm "KEY2" "16" "ED448" "456" - set_keyalgorithm "KEY3" "16" "ED448" "456" - # Key timings and states same as above. - - check_keys - check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - set_keytimes_algorithm_policy - check_keytimes - check_apex - check_subdomain - dnssec_verify -fi - # Set key times for 'autosign' policy. set_keytimes_autosign_policy() { # The KSK was published six months ago (with settime). @@ -889,256 +437,39 @@ set_keytimes_autosign_policy() { set_addkeytime "KEY2" "REMOVED" "${retired}" 695100 } -# -# Zone: expired-sigs.autosign. -# -set_zone "expired-sigs.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "63072000" -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" "31536000" -set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" - -# Both KSK and ZSK stay 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" -# Expect only two keys. -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_autosign_policy -check_keytimes -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" "@${SERVER}" "$_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}" "@${SERVER}" "$_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: dnskey-ttl-mismatch.autosign -# -set_zone "dnskey-ttl-mismatch.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "63072000" -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" "31536000" -set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" - -# Both KSK and ZSK stay 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" -# Expect only two keys. -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_autosign_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone: fresh-sigs.autosign. -# -set_zone "fresh-sigs.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_autosign_policy -check_keytimes -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" "@${SERVER}" "$_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 signed zone file it is not refreshed. - _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' <"rrsig.out.$ZONE.$_qtype") - $CHECKZONE -f raw -F text -s full -o zone.out.${ZONE}.test$n "${ZONE}" "${DIR}/${ZONE}.db.signed" >/dev/null - grep "${_rrsig}" zone.out.${ZONE}.test$n >/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}" "@${SERVER}" "$_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" - # If this exact RRSIG is also in the signed zone file it is not refreshed. - _rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' <"rrsig.out.$ZONE.$_qtype") - $CHECKZONE -f raw -F text -s full -o zone.out.${ZONE}.test$n "${ZONE}" "${DIR}/${ZONE}.db.signed" >/dev/null - grep "${_rrsig}" zone.out.${ZONE}.test$n >/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. -# -set_zone "unfresh-sigs.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -set_keytimes_autosign_policy -check_keytimes -check_apex -check_subdomain -dnssec_verify -check_rrsig_refresh - -# -# Zone: ksk-missing.autosign. -# -set_zone "ksk-missing.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. -# Skip checking the private file, because it is missing. -key_set "KEY1" "PRIVATE" "no" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Restore the PRIVATE variable. -key_set "KEY1" "PRIVATE" "yes" - -# -# Zone: zsk-missing.autosign. -# -set_zone "zsk-missing.autosign" -set_policy "autosign" "2" "300" -set_server "ns3" "10.53.0.3" -# Key properties, timings and states same as above. -# Skip checking the private file, because it is missing. -key_set "KEY2" "PRIVATE" "no" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# For the apex, we expect the SOA to be signed with the KSK because the ZSK is -# offline. Temporary treat KEY1 as a zone signing key too. -set_keyrole "KEY1" "csk" -set_zonesigning "KEY1" "yes" -set_zonesigning "KEY2" "no" -check_apex -set_keyrole "KEY1" "ksk" -set_zonesigning "KEY1" "no" -set_zonesigning "KEY2" "yes" -check_subdomain -dnssec_verify - -# Restore the PRIVATE variable. -key_set "KEY2" "PRIVATE" "yes" - # # Zone: zsk-retired.autosign. # set_zone "zsk-retired.autosign" set_policy "autosign" "3" "300" set_server "ns3" "10.53.0.3" +# Key properties. +key_clear "KEY1" +set_keyrole "KEY1" "ksk" +set_keylifetime "KEY1" "63072000" +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" "31536000" +set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" +set_keysigning "KEY2" "no" +set_zonesigning "KEY2" "yes" + +# Both KSK and ZSK stay 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" +# Expect only two keys. +key_clear "KEY3" +key_clear "KEY4" # The third key is not yet expected to be signing. set_keyrole "KEY3" "zsk" set_keylifetime "KEY3" "31536000" @@ -1185,7 +516,7 @@ check_keytimes check_apex check_subdomain dnssec_verify -check_rrsig_refresh +#check_rrsig_refresh # Load again, make sure the purged key is not an issue when verifying keys. echo_i "load keys for $ZONE, making sure a recently purged key is not an issue when verifying keys ($n)" @@ -1196,164 +527,6 @@ grep "zone $ZONE/IN (signed): zone_rekey:zone_verifykeys failed: some key files test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -# -# Zone: legacy-keys.kasp. -# -set_zone "legacy-keys.kasp" -# This zone has two active keys and two old keys left in key directory, so -# expect 4 key files. -set_policy "migrate-to-dnssec-policy" "4" "1234" -set_server "ns3" "10.53.0.3" - -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "16070400" -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -key_clear "KEY2" -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "16070400" -set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" -# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait. -# ZSK: DNSKEY, RRSIG (zsk) published. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "rumoured" -set_keystate "KEY2" "STATE_ZRRSIG" "rumoured" -# Two keys only. -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Make sure the correct legacy keys were used (and not the removed predecessor -# keys). -n=$((n + 1)) -echo_i "check correct keys were used when migrating zone ${ZONE} to dnssec-policy ($n)" -ret=0 -kskfile=$(cat ns3/legacy-keys.kasp.ksk) -basefile=$(key_get KEY1 BASEFILE) -echo_i "filename: $basefile (expect $kskfile)" -test "$DIR/$kskfile" = "$basefile" || ret=1 -zskfile=$(cat ns3/legacy-keys.kasp.zsk) -basefile=$(key_get KEY2 BASEFILE) -echo_i "filename: $basefile (expect $zskfile)" -test "$DIR/$zskfile" = "$basefile" || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# KSK times. -created=$(key_get KEY1 CREATED) -keyfile=$(key_get KEY1 BASEFILE) -grep "; Publish:" "${keyfile}.key" >published.test${n}.key1 -published=$(awk '{print $3}' published.test${n}.key2 -published=$(awk '{print $3}' /dev/null || log_error "rndc loadkeys zone ${ZONE} failed" -wait_for_log 3 "zone $ZONE/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" $DIR/named.run || ret=1 -# Check keys again, make sure no new keys are created. -set_policy "autosign" "0" "300" -key_clear "KEY1" -key_clear "KEY2" -check_keys -# Zone is still signed correctly. -dnssec_verify - # # Test dnssec-policy inheritance. # diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py index 7ffa22e740..63efab4dd5 100644 --- a/bin/tests/system/kasp/tests_kasp.py +++ b/bin/tests/system/kasp/tests_kasp.py @@ -21,6 +21,7 @@ import pytest pytest.importorskip("dns", minversion="2.0.0") import isctest +import isctest.mark from isctest.kasp import ( KeyProperties, KeyTimingMetadata, @@ -80,11 +81,76 @@ pytestmark = pytest.mark.extra_artifacts( ) -def check_all(server, zone, policy, ksks, zsks, tsig=None): +kasp_config = { + "dnskey-ttl": timedelta(seconds=1234), + "ds-ttl": timedelta(days=1), + "key-directory": "{keydir}", + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=5), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), +} + +autosign_config = { + "dnskey-ttl": timedelta(seconds=300), + "ds-ttl": timedelta(days=1), + "key-directory": "{keydir}", + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=7), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), +} + +lifetime = { + "P10Y": int(timedelta(days=10 * 365).total_seconds()), + "P5Y": int(timedelta(days=5 * 365).total_seconds()), + "P2Y": int(timedelta(days=2 * 365).total_seconds()), + "P1Y": int(timedelta(days=365).total_seconds()), + "P30D": int(timedelta(days=30).total_seconds()), + "P6M": int(timedelta(days=31 * 6).total_seconds()), +} + + +def autosign_properties(alg, size): + return [ + f"ksk {lifetime['P2Y']} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk {lifetime['P1Y']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + ] + + +def rsa1_properties(alg): + return [ + f"ksk {lifetime['P10Y']} {alg} 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk {lifetime['P5Y']} {alg} 2048 goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"zsk {lifetime['P1Y']} {alg} 2000 goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + + +def fips_properties(alg, bits=None): + sizes = [2048, 2048, 3072] + if bits is not None: + sizes = [bits, bits, bits] + + return [ + f"ksk {lifetime['P10Y']} {alg} {sizes[0]} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk {lifetime['P5Y']} {alg} {sizes[1]} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + f"zsk {lifetime['P1Y']} {alg} {sizes[2]} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ] + + +def check_all(server, zone, policy, ksks, zsks, zsk_missing=False, tsig=None): isctest.kasp.check_dnssecstatus(server, zone, ksks + zsks, policy=policy) - isctest.kasp.check_apex(server, zone, ksks, zsks, tsig=tsig) + isctest.kasp.check_apex( + server, zone, ksks, zsks, zsk_missing=zsk_missing, tsig=tsig + ) isctest.kasp.check_subdomain(server, zone, ksks, zsks, tsig=tsig) - isctest.kasp.check_dnssec_verify(server, zone) + isctest.kasp.check_dnssec_verify(server, zone, tsig=tsig) def set_keytimes_default_policy(kp): @@ -103,6 +169,522 @@ def set_keytimes_default_policy(kp): kp.timing["ZRRSIGChange"] = kp.timing["Active"] +def cb_ixfr_is_signed(expected_updates, params, ksks=None, zsks=None): + zone = params["zone"] + policy = params["policy"] + servers = params["servers"] + + isctest.log.info(f"check that the zone {zone} is correctly signed after ixfr") + isctest.log.debug( + f"expected updates {expected_updates} policy {policy} ksks {ksks} zsks {zsks}" + ) + shutil.copyfile(f"ns2/{zone}.db.in2", f"ns2/{zone}.db") + servers["ns2"].rndc(f"reload {zone}", log=False) + + def update_is_signed(): + parts = update.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + rdata = parts[2] + return isctest.kasp.verify_update_is_signed( + servers["ns3"], zone, qname, qtype, rdata, ksks, zsks + ) + + for update in expected_updates: + isctest.run.retry_with_timeout(update_is_signed, timeout=5) + + +def cb_rrsig_refresh(params, ksks=None, zsks=None): + zone = params["zone"] + servers = params["servers"] + + isctest.log.info(f"check that the zone {zone} refreshes expired signatures") + + def rrsig_is_refreshed(): + parts = query.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + return isctest.kasp.verify_rrsig_is_refreshed( + servers["ns3"], zone, f"ns3/{zone}.db.signed", qname, qtype, ksks, zsks + ) + + queries = [ + f"{zone} DNSKEY", + f"{zone} SOA", + f"{zone} NS", + f"{zone} NSEC", + f"a.{zone} A", + f"a.{zone} NSEC", + f"b.{zone} A", + f"b.{zone} NSEC", + f"c.{zone} A", + f"c.{zone} NSEC", + f"ns3.{zone} A", + f"ns3.{zone} NSEC", + ] + + for query in queries: + isctest.run.retry_with_timeout(rrsig_is_refreshed, timeout=5) + + +def cb_rrsig_reuse(params, ksks=None, zsks=None): + zone = params["zone"] + servers = params["servers"] + + isctest.log.info(f"check that the zone {zone} reuses fresh signatures") + + def rrsig_is_reused(): + parts = query.split() + qname = parts[0] + qtype = dns.rdatatype.from_text(parts[1]) + return isctest.kasp.verify_rrsig_is_reused( + servers["ns3"], zone, f"ns3/{zone}.db.signed", qname, qtype, ksks, zsks + ) + + queries = [ + f"{zone} NS", + f"{zone} NSEC", + f"a.{zone} A", + f"a.{zone} NSEC", + f"b.{zone} A", + f"b.{zone} NSEC", + f"c.{zone} A", + f"c.{zone} NSEC", + f"ns3.{zone} A", + f"ns3.{zone} NSEC", + ] + + for query in queries: + rrsig_is_reused() + + +def cb_legacy_keys(params, ksks=None, zsks=None): + zone = params["zone"] + keydir = params["config"]["key-directory"] + + isctest.log.info(f"check that the zone {zone} uses correct legacy keys") + + assert len(ksks) == 1 + assert len(zsks) == 1 + + # This assumes the zone has a policy that dictates one KSK and one ZSK. + # The right keys to be used are stored in "{zone}.ksk" and "{zone}.zsk". + with open(f"{keydir}/{zone}.ksk", "r", encoding="utf-8") as file: + kskfile = file.read() + with open(f"{keydir}/{zone}.zsk", "r", encoding="utf-8") as file: + zskfile = file.read() + + assert f"{keydir}/{kskfile}".strip() == ksks[0].path + assert f"{keydir}/{zskfile}".strip() == zsks[0].path + + +def cb_remove_keyfiles(params, ksks=None, zsks=None): + zone = params["zone"] + servers = params["servers"] + keydir = params["config"]["key-directory"] + + isctest.log.info( + "check that removing key files does not create new keys to be generated" + ) + + for k in ksks + zsks: + os.remove(k.keyfile) + os.remove(k.privatefile) + os.remove(k.statefile) + + with servers["ns3"].watch_log_from_here() as watcher: + servers["ns3"].rndc(f"loadkeys {zone}", log=False) + watcher.wait_for_line( + f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" + ) + + # Check keys again, make sure no new keys are created. + keys = isctest.kasp.keydir_to_keylist(zone, keydir) + isctest.kasp.check_keys(zone, keys, []) + # Zone is still signed correctly. + isctest.kasp.check_dnssec_verify(servers["ns3"], zone) + + +@pytest.mark.parametrize( + "params", + [ + pytest.param( + { + "zone": "rsasha1.kasp", + "policy": "rsasha1", + "config": kasp_config, + "key-properties": rsa1_properties(5), + }, + id="rsasha1.kasp", + marks=isctest.mark.with_algorithm("RSASHA1"), + ), + pytest.param( + { + "zone": "rsasha1-nsec3.kasp", + "policy": "rsasha1", + "config": kasp_config, + "key-properties": rsa1_properties(7), + }, + id="rsasha1-nsec3.kasp", + marks=isctest.mark.with_algorithm("RSASHA1"), + ), + pytest.param( + { + "zone": "dnskey-ttl-mismatch.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": autosign_properties( + os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] + ), + }, + id="dnskey-ttl-mismatch.autosign", + ), + pytest.param( + { + "zone": "expired-sigs.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": autosign_properties( + os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] + ), + "additional-tests": [ + { + "callback": cb_rrsig_refresh, + "arguments": [], + }, + ], + }, + id="expired-sigs.autosign", + ), + pytest.param( + { + "zone": "fresh-sigs.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": autosign_properties( + os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] + ), + "additional-tests": [ + { + "callback": cb_rrsig_reuse, + "arguments": [], + }, + ], + }, + id="fresh-sigs.autosign", + ), + pytest.param( + { + "zone": "unfresh-sigs.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": autosign_properties( + os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] + ), + "additional-tests": [ + { + "callback": cb_rrsig_refresh, + "arguments": [], + }, + ], + }, + id="unfresh-sigs.autosign", + ), + pytest.param( + { + "zone": "keyfiles-missing.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": autosign_properties( + os.environ["DEFAULT_ALGORITHM_NUMBER"], os.environ["DEFAULT_BITS"] + ), + "additional-tests": [ + { + "callback": cb_remove_keyfiles, + "arguments": [], + }, + ], + }, + id="keyfiles-missing.autosign", + ), + pytest.param( + { + "zone": "ksk-missing.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": [ + f"ksk 63072000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent missing", + f"zsk 31536000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent", + ], + }, + id="ksk-missing.autosign", + ), + pytest.param( + { + "zone": "zsk-missing.autosign", + "policy": "autosign", + "config": autosign_config, + "offset": -timedelta(days=30 * 6), + "key-properties": [ + f"ksk 63072000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent", + f"zsk 31536000 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent missing", + ], + }, + id="zsk-missing.autosign", + ), + pytest.param( + { + "zone": "dnssec-keygen.kasp", + "policy": "rsasha256", + "config": kasp_config, + "key-properties": fips_properties(8), + }, + id="dnssec-keygen.kasp", + ), + pytest.param( + { + "zone": "ecdsa256.kasp", + "policy": "ecdsa256", + "config": kasp_config, + "key-properties": fips_properties(13, bits=256), + }, + id="ecdsa256.kasp", + ), + pytest.param( + { + "zone": "ecdsa384.kasp", + "policy": "ecdsa384", + "config": kasp_config, + "key-properties": fips_properties(14, bits=384), + }, + id="ecdsa384.kasp", + ), + pytest.param( + { + "zone": "inherit.kasp", + "policy": "rsasha256", + "config": kasp_config, + "key-properties": fips_properties(8), + }, + id="inherit.kasp", + ), + pytest.param( + { + "zone": "keystore.kasp", + "policy": "keystore", + "config": { + "dnskey-ttl": timedelta(seconds=303), + "ds-ttl": timedelta(days=1), + "key-directory": "{keydir}", + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=5), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(minutes=5), + }, + "key-directories": ["{keydir}/ksk", "{keydir}/zsk"], + "key-properties": [ + f"ksk unlimited {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk unlimited {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ], + }, + id="keystore.kasp", + ), + pytest.param( + { + "zone": "legacy-keys.kasp", + "policy": "migrate-to-dnssec-policy", + "config": kasp_config, + "pregenerated": True, + "key-properties": [ + "ksk 16070400 8 2048 goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + "zsk 16070400 8 2048 goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ], + "additional-tests": [ + { + "callback": cb_legacy_keys, + "arguments": [], + }, + ], + }, + id="legacy-keys.kasp", + ), + pytest.param( + { + "zone": "pregenerated.kasp", + "policy": "rsasha256", + "config": kasp_config, + "pregenerated": True, + "key-properties": fips_properties(8), + }, + id="pregenerated.kasp", + ), + pytest.param( + { + "zone": "rsasha256.kasp", + "policy": "rsasha256", + "config": kasp_config, + "key-properties": fips_properties(8), + }, + id="rsasha256.kasp", + ), + pytest.param( + { + "zone": "rsasha512.kasp", + "policy": "rsasha512", + "config": kasp_config, + "key-properties": fips_properties(10), + }, + id="rsasha512.kasp", + ), + pytest.param( + { + "zone": "rumoured.kasp", + "policy": "rsasha256", + "config": kasp_config, + "rumoured": True, + "key-properties": fips_properties(8), + }, + id="rumoured.kasp", + ), + pytest.param( + { + "zone": "secondary.kasp", + "policy": "rsasha256", + "config": kasp_config, + "key-properties": fips_properties(8), + "additional-tests": [ + { + "callback": cb_ixfr_is_signed, + "arguments": [ + [ + "a.secondary.kasp. A 10.0.0.11", + "d.secondary.kasp. A 10.0.0.4", + ], + ], + }, + ], + }, + id="secondary.kasp", + ), + pytest.param( + { + "zone": "some-keys.kasp", + "policy": "rsasha256", + "config": kasp_config, + "pregenerated": True, + "key-properties": fips_properties(8), + }, + id="some-keys.kasp", + ), + pytest.param( + { + "zone": "unlimited.kasp", + "policy": "unlimited", + "config": kasp_config, + "key-properties": [ + f"csk 0 {os.environ['DEFAULT_ALGORITHM_NUMBER']} {os.environ['DEFAULT_BITS']} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + }, + id="unlimited.kasp", + ), + pytest.param( + { + "zone": "ed25519.kasp", + "policy": "ed25519", + "config": kasp_config, + "key-properties": fips_properties(15, bits=256), + }, + id="ed25519.kasp", + marks=isctest.mark.with_algorithm("ED25519"), + ), + pytest.param( + { + "zone": "ed448.kasp", + "policy": "ed448", + "config": kasp_config, + "key-properties": fips_properties(16, bits=456), + }, + id="ed448.kasp", + marks=isctest.mark.with_algorithm("ED448"), + ), + ], +) +def test_kasp_case(servers, params): + # Test many different configurations and expected keys and states after + # initial startup. + server = servers["ns3"] + keydir = server.identifier + + # Get test parameters. + zone = params["zone"] + policy = params["policy"] + + params["config"]["key-directory"] = params["config"]["key-directory"].replace( + "{keydir}", keydir + ) + if "key-directories" in params: + for i, val in enumerate(params["key-directories"]): + params["key-directories"][i] = val.replace("{keydir}", keydir) + + ttl = int(params["config"]["dnskey-ttl"].total_seconds()) + pregenerated = False + if params.get("pregenerated"): + pregenerated = params["pregenerated"] + zsk_missing = zone == "zsk-missing.autosign" + + # Test case. + isctest.log.info(f"check test case zone {zone} policy {policy}") + + # First make sure the zone is signed. + isctest.kasp.check_zone_is_signed(server, zone) + + # Key properties. + expected = isctest.kasp.policy_to_properties(ttl=ttl, keys=params["key-properties"]) + # Key files. + if "key-directories" in params: + kdir = params["key-directories"][0] + ksks = isctest.kasp.keydir_to_keylist(zone, kdir, in_use=pregenerated) + kdir = params["key-directories"][1] + zsks = isctest.kasp.keydir_to_keylist(zone, kdir, in_use=pregenerated) + keys = ksks + zsks + else: + keys = isctest.kasp.keydir_to_keylist( + zone, params["config"]["key-directory"], in_use=pregenerated + ) + ksks = [k for k in keys if k.is_ksk()] + zsks = [k for k in keys if not k.is_ksk()] + + isctest.kasp.check_keys(zone, keys, expected) + + offset = params["offset"] if "offset" in params else None + + for kp in expected: + kp.set_expected_keytimes( + params["config"], offset=offset, pregenerated=pregenerated + ) + + if "rumoured" not in params: + isctest.kasp.check_keytimes(keys, expected) + + check_all(server, zone, policy, ksks, zsks, zsk_missing=zsk_missing) + + if "additional-tests" in params: + params["servers"] = servers + for additional_test in params["additional-tests"]: + callback = additional_test["callback"] + arguments = additional_test["arguments"] + callback(*arguments, params=params, ksks=ksks, zsks=zsks) + + def test_kasp_default(servers): server = servers["ns3"] @@ -404,11 +986,6 @@ def test_kasp_dnssec_keygen(): return isctest.run.cmd(keygen_command, log_stdout=True).stdout.decode("utf-8") # check that 'dnssec-keygen -k' (configured policy) creates valid files. - lifetime = { - "P1Y": int(timedelta(days=365).total_seconds()), - "P30D": int(timedelta(days=30).total_seconds()), - "P6M": int(timedelta(days=31 * 6).total_seconds()), - } keyprops = [ f"csk {lifetime['P1Y']} 13 256", f"ksk {lifetime['P1Y']} 8 2048", diff --git a/bin/tests/system/ksr/tests_ksr.py b/bin/tests/system/ksr/tests_ksr.py index 5512f34fa2..ae020086f9 100644 --- a/bin/tests/system/ksr/tests_ksr.py +++ b/bin/tests/system/ksr/tests_ksr.py @@ -673,9 +673,9 @@ def test_ksr_common(servers): # - check keys check_keys(overlapping_zsks, lifetime, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, overlapping_zsks) + isctest.kasp.check_apex(ns1, zone, ksks, overlapping_zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, overlapping_zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, overlapping_zsks, offline_ksk=True) def test_ksr_lastbundle(servers): @@ -748,9 +748,9 @@ def test_ksr_lastbundle(servers): # - check keys check_keys(zsks, lifetime, offset=offset, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, zsks) + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) # check that last bundle warning is logged warning = "last bundle in skr, please import new skr file" @@ -828,9 +828,9 @@ def test_ksr_inthemiddle(servers): # - check keys check_keys(zsks, lifetime, offset=offset, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, zsks) + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) # check that no last bundle warning is logged warning = "last bundle in skr, please import new skr file" @@ -1023,9 +1023,9 @@ def test_ksr_unlimited(servers): # - check keys check_keys(zsks, lifetime, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, zsks) + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) def test_ksr_twotone(servers): @@ -1141,9 +1141,9 @@ def test_ksr_twotone(servers): lifetime = timedelta(days=31 * 5) check_keys(zsks_altalg, lifetime, alg, size, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, zsks) + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True) def test_ksr_kskroll(servers): @@ -1215,6 +1215,6 @@ def test_ksr_kskroll(servers): # - check keys check_keys(zsks, None, with_state=True) # - check apex - isctest.kasp.check_apex(ns1, zone, ksks, zsks) + isctest.kasp.check_apex(ns1, zone, ksks, zsks, offline_ksk=True) # - check subdomain - isctest.kasp.check_subdomain(ns1, zone, ksks, zsks) + isctest.kasp.check_subdomain(ns1, zone, ksks, zsks, offline_ksk=True)