diff --git a/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py b/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py index 1966991e24..232be8f7f9 100644 --- a/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py +++ b/bin/tests/system/rollover-zsk-prepub/tests_rollover_zsk_prepublication.py @@ -13,8 +13,11 @@ 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, @@ -34,7 +37,7 @@ CONFIG = { "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) @@ -54,11 +57,22 @@ OFFSETS["step6-p"] = OFFSETS["step5-p"] - int(CONFIG["purge-keys"].total_seconds 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, @@ -71,14 +85,45 @@ def test_zsk_prepub_step1(alg, size, ns3): # 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 @@ -95,14 +140,59 @@ def test_zsk_prepub_step2(alg, size, ns3): # 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. @@ -124,14 +214,47 @@ def test_zsk_prepub_step3(alg, size, ns3): # 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. @@ -149,14 +272,24 @@ def test_zsk_prepub_step4(alg, size, ns3): # 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 @@ -172,14 +305,24 @@ def test_zsk_prepub_step5(alg, size, ns3): # 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, @@ -189,4 +332,4 @@ def test_zsk_prepub_step6(alg, size, ns3): ], "nextev": None, } - isctest.kasp.check_rollover_step(ns3, CONFIG, POLICY, step) + isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)