from datetime import timedelta
+import pytest
+
import isctest
from isctest.kasp import Ipub, Iret
+from isctest.util import param
from rollover.common import (
pytestmark,
alg,
"signatures-validity": TIMEDELTA["P14D"],
"zone-propagation-delay": TIMEDELTA["PT1H"],
}
-POLICY = "zsk-prepub-autosign"
+POLICY = "zsk-prepub"
ZSK_LIFETIME = TIMEDELTA["P30D"]
LIFETIME_POLICY = int(ZSK_LIFETIME.total_seconds())
IPUB = Ipub(CONFIG)
OFFSETS["step6-s"] = OFFSETS["step5-s"] - int(CONFIG["purge-keys"].total_seconds())
-def test_zsk_prepub_step1(alg, size, ns3):
- zone = "step1.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step1(tld, alg, size, ns3):
+ zone = f"step1.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ # manual-mode: Nothing changing in the zone, no 'dnssec -step' required.
+ # Note that the key was already generated during setup.
+
step = {
# Introduce the first key. This will immediately be active.
"zone": zone,
# already passed).
"nextev": ZSK_LIFETIME - IPUB - timedelta(days=7),
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
-def test_zsk_prepub_step2(alg, size, ns3):
- zone = "step2.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step2(tld, alg, size, ns3):
+ zone = f"step2.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ if tld == "manual":
+ # Same as step 1.
+ step = {
+ "zone": zone,
+ "keyprops": [
+ f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}",
+ f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}",
+ ],
+ "manual-mode": True,
+ "nextev": None,
+ }
+ keys = isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
+
+ # Check logs.
+ tag = keys[1].key.tag
+ msg = f"keymgr-manual-mode: block ZSK rollover for key {zone}/ECDSAP256SHA256/{tag} (policy {policy})"
+ ns3.log.expect(msg)
+
+ # Force step.
+ with ns3.watch_log_from_here() as watcher:
+ ns3.rndc(f"dnssec -step {zone}")
+ watcher.wait_for_line(f"keymgr: {zone} done")
+
step = {
# it is time to pre-publish the successor zsk.
# zsk1 goal: omnipresent -> hidden
# that is the dnskey ttl plus the zone propagation delay
"nextev": IPUB,
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
-def test_zsk_prepub_step3(alg, size, ns3):
- zone = "step3.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step3(tld, alg, size, ns3):
+ zone = f"step3.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ if tld == "manual":
+ # Same as step 2, but DNSKEY has become OMNIPRESENT.
+ step = {
+ "zone": zone,
+ "keyprops": [
+ f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step3-p']}",
+ f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}",
+ f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step3-s']}",
+ ],
+ "keyrelationships": [1, 2],
+ "manual-mode": True,
+ "nextev": None,
+ }
+ keys = isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
+
+ # Check logs.
+ tag = keys[2].key.tag
+ msg = f"keymgr-manual-mode: block transition ZSK {zone}/ECDSAP256SHA256/{tag} type ZRRSIG state HIDDEN to state RUMOURED"
+ ns3.log.expect(msg)
+
+ # Force step.
+ with ns3.watch_log_from_here() as watcher:
+ ns3.rndc(f"dnssec -step {zone}")
+ watcher.wait_for_line(f"keymgr: {zone} done")
+
+ # Check logs.
+ tag = keys[1].key.tag
+ msg = f"keymgr-manual-mode: block transition ZSK {zone}/ECDSAP256SHA256/{tag} type ZRRSIG state OMNIPRESENT to state UNRETENTIVE"
+ if msg in ns3.log:
+ # Force step.
+ isctest.log.debug(
+ f"keymgr-manual-mode blocking transition ZSK {zone}/ECDSAP256SHA256/{tag} type ZRRSIG state OMNIPRESENT to state UNRETENTIVE, step again"
+ )
+ with ns3.watch_log_from_here() as watcher:
+ ns3.rndc(f"dnssec -step {zone}")
+ watcher.wait_for_line(f"keymgr: {zone} done")
+
step = {
# predecessor zsk is no longer actively signing. successor zsk is
# now actively signing.
# from the predecessor zsk.
"smooth": True,
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
-def test_zsk_prepub_step4(alg, size, ns3):
- zone = "step4.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step4(tld, alg, size, ns3):
+ zone = f"step4.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ if tld == "manual":
+ # Same as step 3, but zone signatures have become HIDDEN/OMNIPRESENT.
+ step = {
+ "zone": zone,
+ "keyprops": [
+ f"ksk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-p']}",
+ f"zsk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:hidden offset:{OFFSETS['step4-p']}",
+ f"zsk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-s']}",
+ ],
+ "keyrelationships": [1, 2],
+ "manual-mode": True,
+ "nextev": None,
+ }
+ keys = isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
+
+ # Check logs.
+ tag = keys[1].key.tag
+ msg = f"keymgr-manual-mode: block transition ZSK {zone}/ECDSAP256SHA256/{tag} type DNSKEY state OMNIPRESENT to state UNRETENTIVE"
+ ns3.log.expect(msg)
+
+ # Force step.
+ with ns3.watch_log_from_here() as watcher:
+ ns3.rndc(f"dnssec -step {zone}")
+ watcher.wait_for_line(f"keymgr: {zone} done")
+
step = {
# predecessor zsk is no longer needed. all rrsets are signed with
# the successor zsk.
# this is the dnskey ttl plus zone propagation delay.
"nextev": KEYTTLPROP,
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
-def test_zsk_prepub_step5(alg, size, ns3):
- zone = "step5.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step5(tld, alg, size, ns3):
+ zone = f"step5.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ # manual-mode: Nothing changing in the zone, no 'dnssec -step' required.
+
step = {
# predecessor zsk is now removed.
# zsk1 dnskey: unretentive -> hidden
# elapsed.
"nextev": ZSK_LIFETIME - IRET - IPUB - KEYTTLPROP,
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
-def test_zsk_prepub_step6(alg, size, ns3):
- zone = "step6.zsk-prepub.autosign"
+@pytest.mark.parametrize(
+ "tld",
+ [
+ param("autosign"),
+ param("manual"),
+ ],
+)
+def test_zsk_prepub_step6(tld, alg, size, ns3):
+ zone = f"step6.zsk-prepub.{tld}"
+ policy = f"{POLICY}-{tld}"
isctest.kasp.wait_keymgr_done(ns3, zone)
+ # manual-mode: Nothing changing in the zone, no 'dnssec -step' required.
+
step = {
# predecessor zsk is now purged.
"zone": zone,
],
"nextev": None,
}
- isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step)
+ isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)