mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 22:15:20 +00:00
Convert kasp zsk retired test case
This test case does not easily fit in the standard test case framework, so it goes into its own suite.
This commit is contained in:
@@ -306,9 +306,8 @@ $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
|
||||
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)
|
||||
zsktimes="$keytimes -I now"
|
||||
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
|
||||
|
@@ -437,96 +437,6 @@ set_keytimes_autosign_policy() {
|
||||
set_addkeytime "KEY2" "REMOVED" "${retired}" 695100
|
||||
}
|
||||
|
||||
#
|
||||
# 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"
|
||||
set_keyalgorithm "KEY3" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS"
|
||||
set_keysigning "KEY3" "no"
|
||||
set_zonesigning "KEY3" "no"
|
||||
# The ZSK goal is set to HIDDEN but records stay OMNIPRESENT until the new ZSK
|
||||
# is active.
|
||||
set_keystate "KEY2" "GOAL" "hidden"
|
||||
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
|
||||
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
|
||||
# A new ZSK should be introduced, so expect a key with goal OMNIPRESENT,
|
||||
# the DNSKEY introduced (RUMOURED) and the signatures HIDDEN.
|
||||
set_keystate "KEY3" "GOAL" "omnipresent"
|
||||
set_keystate "KEY3" "STATE_DNSKEY" "rumoured"
|
||||
set_keystate "KEY3" "STATE_ZRRSIG" "hidden"
|
||||
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_autosign_policy
|
||||
|
||||
# The old ZSK is retired.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_keytime "KEY2" "RETIRED" "${created}"
|
||||
set_addkeytime "KEY2" "REMOVED" "${created}" 695100
|
||||
# The new ZSK is immediately published.
|
||||
created=$(key_get KEY3 CREATED)
|
||||
set_keytime "KEY3" "PUBLISHED" "${created}"
|
||||
# And becomes active after Ipub:
|
||||
# DNSKEY TTL: 300 seconds
|
||||
# zone-propagation-delay 5 minutes (300 seconds)
|
||||
# publish-safety: 1 hour (3600 seconds)
|
||||
# Ipub: 4200 seconds
|
||||
published=$(key_get KEY3 PUBLISHED)
|
||||
set_addkeytime "KEY3" "ACTIVE" "${published}" 4200
|
||||
# Lzsk: 1 year (31536000 seconds)
|
||||
active=$(key_get KEY3 ACTIVE)
|
||||
set_addkeytime "KEY3" "RETIRED" "${active}" 31536000
|
||||
# Iret: 695100 seconds.
|
||||
retired=$(key_get KEY3 RETIRED)
|
||||
set_addkeytime "KEY3" "REMOVED" "${retired}" 695100
|
||||
|
||||
check_keytimes
|
||||
check_apex
|
||||
check_subdomain
|
||||
dnssec_verify
|
||||
#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)"
|
||||
ret=0
|
||||
rndccmd 10.53.0.3 loadkeys "$ZONE" >/dev/null || log_error "rndc loadkeys zone ${ZONE} failed"
|
||||
wait_for_log 3 "keymgr: $ZONE done" $DIR/named.run || ret=1
|
||||
grep "zone $ZONE/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing" $DIR/named.run && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
#
|
||||
# Test dnssec-policy inheritance.
|
||||
#
|
||||
|
@@ -1151,3 +1151,138 @@ def test_kasp_dnssec_keygen():
|
||||
out = isctest.run.cmd(settime, log_stdout=True).stdout.decode("utf-8")
|
||||
isctest.kasp.check_keys("kasp", keys, expected)
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
|
||||
|
||||
def test_kasp_zsk_retired(servers):
|
||||
server = servers["ns3"]
|
||||
|
||||
config = {
|
||||
"dnskey-ttl": timedelta(seconds=300),
|
||||
"ds-ttl": timedelta(days=1),
|
||||
"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),
|
||||
}
|
||||
|
||||
zone = "zsk-retired.autosign"
|
||||
policy = "autosign"
|
||||
alg = os.environ["DEFAULT_ALGORITHM_NUMBER"]
|
||||
size = os.environ["DEFAULT_BITS"]
|
||||
key_properties = [
|
||||
f"ksk 63072000 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
|
||||
# zsk predecessor
|
||||
f"zsk 31536000 {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent",
|
||||
# zsk successor
|
||||
f"zsk 31536000 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden",
|
||||
]
|
||||
expected = isctest.kasp.policy_to_properties(300, key_properties)
|
||||
keys = isctest.kasp.keydir_to_keylist(zone, "ns3")
|
||||
ksks = [k for k in keys if k.is_ksk()]
|
||||
zsks = [k for k in keys if not k.is_ksk()]
|
||||
isctest.kasp.check_zone_is_signed(server, zone)
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
|
||||
offset = -timedelta(days=30 * 6)
|
||||
sign_delay = config["signatures-validity"] - config["signatures-refresh"]
|
||||
|
||||
def sumvars(variables):
|
||||
result = timedelta(0)
|
||||
for var in variables:
|
||||
result = result + config[var]
|
||||
return result
|
||||
|
||||
# KSK Key Timings:
|
||||
# IpubC = DprpC + TTLkey
|
||||
# Note: Also need to wait until the signatures are omnipresent.
|
||||
# That's why we use max-zone-ttl instead of dnskey-ttl here.
|
||||
Ipub_KSK = sumvars(["zone-propagation-delay", "max-zone-ttl"])
|
||||
# Iret = DprpP + TTLds
|
||||
Iret_KSK = sumvars(["parent-propagation-delay", "retire-safety", "ds-ttl"])
|
||||
|
||||
# ZSK Key Timings:
|
||||
# Ipub = Dprp + TTLkey
|
||||
Ipub_ZSK = sumvars(["zone-propagation-delay", "publish-safety", "dnskey-ttl"])
|
||||
# Iret = Dsgn + Dprp + TTLsig
|
||||
Iret_ZSK = sumvars(["zone-propagation-delay", "retire-safety", "max-zone-ttl"])
|
||||
Iret_ZSK = Iret_ZSK + sign_delay
|
||||
|
||||
# KSK
|
||||
expected[0].timing["Generated"] = expected[0].key.get_timing("Created")
|
||||
expected[0].timing["Published"] = expected[0].timing["Generated"]
|
||||
expected[0].timing["Published"] = expected[0].timing["Published"] + offset
|
||||
expected[0].timing["Active"] = expected[0].timing["Published"]
|
||||
expected[0].timing["Retired"] = expected[0].timing["Published"] + int(
|
||||
expected[0].metadata["Lifetime"]
|
||||
)
|
||||
# Trdy(N) = Tpub(N) + IpubC
|
||||
expected[0].timing["PublishCDS"] = expected[0].timing["Published"] + Ipub_KSK
|
||||
# Tdea(N) = Tret(N) + Iret
|
||||
expected[0].timing["Removed"] = expected[0].timing["Retired"] + Iret_KSK
|
||||
expected[0].timing["DNSKEYChange"] = None
|
||||
expected[0].timing["DSChange"] = None
|
||||
expected[0].timing["KRRSIGChange"] = None
|
||||
|
||||
# ZSK (predecessor)
|
||||
expected[1].timing["Generated"] = expected[1].key.get_timing("Created")
|
||||
expected[1].timing["Published"] = expected[1].timing["Generated"] + offset
|
||||
expected[1].timing["Active"] = expected[1].timing["Published"]
|
||||
expected[1].timing["Retired"] = expected[1].timing["Generated"]
|
||||
# Tdea(N) = Tret(N) + Iret
|
||||
expected[1].timing["Removed"] = expected[1].timing["Retired"] + Iret_ZSK
|
||||
expected[1].timing["DNSKEYChange"] = None
|
||||
expected[1].timing["ZRRSIGChange"] = None
|
||||
|
||||
# ZSK (successor)
|
||||
expected[2].timing["Generated"] = expected[2].key.get_timing("Created")
|
||||
expected[2].timing["Published"] = expected[2].timing["Generated"]
|
||||
# Trdy(N) = Tpub(N) + Ipub
|
||||
expected[2].timing["Active"] = expected[2].timing["Published"] + Ipub_ZSK
|
||||
# Tret(N) = Tact(N) + Lzsk
|
||||
expected[2].timing["Retired"] = expected[2].timing["Active"] + int(
|
||||
expected[2].metadata["Lifetime"]
|
||||
)
|
||||
# Tdea(N) = Tret(N) + Iret
|
||||
expected[2].timing["Removed"] = expected[2].timing["Retired"] + Iret_ZSK
|
||||
expected[2].timing["DNSKEYChange"] = None
|
||||
expected[2].timing["ZRRSIGChange"] = None
|
||||
|
||||
isctest.kasp.check_keytimes(keys, expected)
|
||||
check_all(server, zone, policy, 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",
|
||||
]
|
||||
|
||||
def rrsig_is_refreshed():
|
||||
parts = query.split()
|
||||
qname = parts[0]
|
||||
qtype = dns.rdatatype.from_text(parts[1])
|
||||
return isctest.kasp.verify_rrsig_is_refreshed(
|
||||
server, zone, f"ns3/{zone}.db.signed", qname, qtype, ksks, zsks
|
||||
)
|
||||
|
||||
for query in queries:
|
||||
isctest.run.retry_with_timeout(rrsig_is_refreshed, timeout=5)
|
||||
|
||||
# Load again, make sure the purged key is not an issue when verifying keys.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
msg = f"zone {zone}/IN (signed): zone_rekey:zone_verifykeys failed: some key files are missing"
|
||||
server.log.prohibit(msg)
|
||||
|
Reference in New Issue
Block a user