2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +00:00

[9.20] chg: test: Rewrite kasp system test to pytest (3)

Write python-based tests for the many test cases from the kasp system test with the same pattern.

Backport of MR !10268

Merge branch 'backport-matthijs-pytest-rewrite-kasp-system-test-3-9.20' into 'bind-9.20'

See merge request isc-projects/bind9!10421
This commit is contained in:
Matthijs Mekking 2025-04-23 16:32:45 +00:00
commit e14173668e
6 changed files with 845 additions and 933 deletions

View File

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

View File

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

View File

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

View File

@ -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}.key1)
set_keytime "KEY1" "PUBLISHED" "${published}"
set_keytime "KEY1" "ACTIVE" "${published}"
published=$(key_get KEY1 PUBLISHED)
# The DS can be published if the zone is fully signed.
# This happens after max-zone-ttl (1d) plus
# zone-propagation-delay (300s) = 86400 + 300 = 86700.
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 86700
# Key lifetime is 6 months, 315360000 seconds.
set_addkeytime "KEY1" "RETIRED" "${published}" 16070400
# The key is removed after the retire time plus DS TTL (1d), parent
# propagation delay (1h), and retire safety (1h) = 86400 + 3600 + 3600 = 93600.
retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" 93600
# ZSK times.
created=$(key_get KEY2 CREATED)
keyfile=$(key_get KEY2 BASEFILE)
grep "; Publish:" "${keyfile}.key" >published.test${n}.key2
published=$(awk '{print $3}' <published.test${n}.key2)
set_keytime "KEY2" "PUBLISHED" "${published}"
set_keytime "KEY2" "ACTIVE" "${published}"
published=$(key_get KEY2 PUBLISHED)
# Key lifetime is 6 months, 315360000 seconds.
set_addkeytime "KEY2" "RETIRED" "${published}" 16070400
# The key is removed after the retire time plus max zone ttl (1d), zone
# propagation delay (300s), retire safety (1h), and sign delay (signature
# validity minus refresh, 9d) = 86400 + 300 + 3600 + 777600 = 867900.
retired=$(key_get KEY2 RETIRED)
set_addkeytime "KEY2" "REMOVED" "${retired}" 867900
check_keytimes
check_apex
check_subdomain
dnssec_verify
#
# Zone: keyfiles-missing.autosign.
#
set_zone "keyfiles-missing.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"
check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
set_keytimes_autosign_policy
check_keytimes
check_apex
check_subdomain
dnssec_verify
# All good, now remove key files and reload keys.
rm_keyfiles() {
_basefile=$(key_get "$1" BASEFILE)
echo_i "remove key files $_basefile"
_keyfile="${_basefile}.key"
_privatefile="${_basefile}.private"
_statefile="${_basefile}.state"
rm -f $_keyfile
rm -f $_privatefile
rm -f $_statefile
}
rm_keyfiles "KEY1"
rm_keyfiles "KEY2"
rndccmd 10.53.0.3 loadkeys "$ZONE" >/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.
#

View File

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

View File

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