]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Isolate rollover-ksk-3crowd test case
authorNicki Křížek <nicki@isc.org>
Tue, 10 Jun 2025 14:33:08 +0000 (16:33 +0200)
committerNicki Křížek <nicki@isc.org>
Fri, 18 Jul 2025 11:37:58 +0000 (13:37 +0200)
13 files changed:
bin/tests/system/rollover-ksk-3crowd/common.py [new symlink]
bin/tests/system/rollover-ksk-3crowd/ns3/kasp.conf.j2 [new symlink]
bin/tests/system/rollover-ksk-3crowd/ns3/named.common.conf.j2 [new symlink]
bin/tests/system/rollover-ksk-3crowd/ns3/named.conf.j2 [new file with mode: 0644]
bin/tests/system/rollover-ksk-3crowd/ns3/template.db.in [new symlink]
bin/tests/system/rollover-ksk-3crowd/setup.sh [new file with mode: 0644]
bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py [new file with mode: 0644]
bin/tests/system/rollover-ksk-doubleksk/tests_rollover_ksk_doubleksk.py
bin/tests/system/rollover/common.py
bin/tests/system/rollover/ns3/kasp.conf.j2
bin/tests/system/rollover/ns3/named.conf.j2
bin/tests/system/rollover/ns3/setup.sh
bin/tests/system/rollover/tests_rollover.py

diff --git a/bin/tests/system/rollover-ksk-3crowd/common.py b/bin/tests/system/rollover-ksk-3crowd/common.py
new file mode 120000 (symlink)
index 0000000..64b8084
--- /dev/null
@@ -0,0 +1 @@
+../rollover/common.py
\ No newline at end of file
diff --git a/bin/tests/system/rollover-ksk-3crowd/ns3/kasp.conf.j2 b/bin/tests/system/rollover-ksk-3crowd/ns3/kasp.conf.j2
new file mode 120000 (symlink)
index 0000000..138fa68
--- /dev/null
@@ -0,0 +1 @@
+../../rollover-ksk-doubleksk/ns3/kasp.conf.j2
\ No newline at end of file
diff --git a/bin/tests/system/rollover-ksk-3crowd/ns3/named.common.conf.j2 b/bin/tests/system/rollover-ksk-3crowd/ns3/named.common.conf.j2
new file mode 120000 (symlink)
index 0000000..5dc2617
--- /dev/null
@@ -0,0 +1 @@
+../../rollover/ns3/named.common.conf.j2
\ No newline at end of file
diff --git a/bin/tests/system/rollover-ksk-3crowd/ns3/named.conf.j2 b/bin/tests/system/rollover-ksk-3crowd/ns3/named.conf.j2
new file mode 100644 (file)
index 0000000..ae01f2e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+include "kasp.conf";
+include "named.common.conf";
+
+zone "three-is-a-crowd.kasp" {
+        type primary;
+        file "three-is-a-crowd.kasp.db";
+        inline-signing yes;
+        /* Use same policy as KSK rollover test zones. */
+        dnssec-policy "ksk-doubleksk";
+};
diff --git a/bin/tests/system/rollover-ksk-3crowd/ns3/template.db.in b/bin/tests/system/rollover-ksk-3crowd/ns3/template.db.in
new file mode 120000 (symlink)
index 0000000..ce6d526
--- /dev/null
@@ -0,0 +1 @@
+../../rollover/ns3/template.db.in
\ No newline at end of file
diff --git a/bin/tests/system/rollover-ksk-3crowd/setup.sh b/bin/tests/system/rollover-ksk-3crowd/setup.sh
new file mode 100644 (file)
index 0000000..558c77b
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../conf.sh
+
+cd "ns3"
+
+setup() {
+  zone="$1"
+  echo_i "setting up zone: $zone"
+  zonefile="${zone}.db"
+  infile="${zone}.db.infile"
+  echo "$zone" >>zones
+}
+
+# Set in the key state files the Predecessor/Successor fields.
+# Key $1 is the predecessor of key $2.
+key_successor() {
+  id1=$(keyfile_to_key_id "$1")
+  id2=$(keyfile_to_key_id "$2")
+  echo "Predecessor: ${id1}" >>"${2}.state"
+  echo "Successor: ${id2}" >>"${1}.state"
+}
+
+# Make lines shorter by storing key states in environment variables.
+H="HIDDEN"
+R="RUMOURED"
+O="OMNIPRESENT"
+U="UNRETENTIVE"
+
+# Test #2375, the "three is a crowd" bug, where a new key is introduced but the
+# previous rollover has not finished yet. In other words, we have a key KEY2
+# that is the successor of key KEY1, and we introduce a new key KEY3 that is
+# the successor of key KEY2:
+#
+#     KEY1 < KEY2 < KEY3.
+#
+# The expected behavior is that all three keys remain in the zone, and not
+# the bug behavior where KEY2 is removed and immediately replaced with KEY3.
+#
+# Set up a zone that has a KSK (KEY1) and have the successor key (KEY2)
+# published as well.
+setup three-is-a-crowd.kasp
+# These times are the same as step3.ksk-doubleksk.autosign.
+TpubN="now-60d"
+TactN="now-1413h"
+TretN="now"
+TremN="now+50h"
+TpubN1="now-27h"
+TsbmN1="now"
+TactN1="${TretN}"
+TretN1="now+60d"
+TremN1="now+1490h"
+ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN} -D sync ${TactN1}"
+newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
+zsktimes="-P ${TpubN}  -A ${TpubN}"
+KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
+KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
+$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1
+$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1
+$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
+# Set key rollover relationship.
+key_successor $KSK1 $KSK2
+# Sign zone.
+cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
+private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
+cp $infile $zonefile
+$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
diff --git a/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py b/bin/tests/system/rollover-ksk-3crowd/tests_rollover_three_is_a_crowd.py
new file mode 100644 (file)
index 0000000..f30c206
--- /dev/null
@@ -0,0 +1,94 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# pylint: disable=redefined-outer-name,unused-import
+
+from datetime import timedelta
+
+import isctest
+from isctest.kasp import KeyTimingMetadata
+from common import (
+    pytestmark,
+    alg,
+    size,
+    KSK_CONFIG,
+    KSK_LIFETIME_POLICY,
+    KSK_IPUB,
+    KSK_IRET,
+)
+
+
+CDSS = ["CDS (SHA-256)"]
+POLICY = "ksk-doubleksk"
+OFFSET1 = -int(timedelta(days=60).total_seconds())
+OFFSET2 = -int(timedelta(hours=27).total_seconds())
+TTL = int(KSK_CONFIG["dnskey-ttl"].total_seconds())
+
+
+def test_rollover_ksk_three_is_a_crowd(alg, size, servers):
+    """Test #2375: Scheduled rollovers are happening faster than they can finish."""
+    server = servers["ns3"]
+    zone = "three-is-a-crowd.kasp"
+
+    step = {
+        "zone": zone,
+        "cdss": CDSS,
+        "keyprops": [
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}",
+            f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}",
+        ],
+        "keyrelationships": [0, 1],
+    }
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
+
+    # Rollover successor KSK (with DS in rumoured state).
+    expected = isctest.kasp.policy_to_properties(TTL, step["keyprops"])
+    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
+    isctest.kasp.check_keys(zone, keys, expected)
+    key = expected[1].key
+    now = KeyTimingMetadata.now()
+    with server.watch_log_from_here() as watcher:
+        server.rndc(f"dnssec -rollover -key {key.tag} -when {now} {zone}")
+        watcher.wait_for_line(f"keymgr: {zone} done")
+
+    # We now expect four keys (3x KSK, 1x ZSK).
+    step = {
+        "zone": zone,
+        "cdss": CDSS,
+        "keyprops": [
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSET1}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSET2}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:0",
+            f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSET1}",
+        ],
+        "check-keytimes": False,  # checked manually with modified values
+    }
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
+
+    expected = isctest.kasp.policy_to_properties(TTL, step["keyprops"])
+    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
+    isctest.kasp.check_keys(zone, keys, expected)
+
+    expected[0].metadata["Successor"] = expected[1].key.tag
+    expected[1].metadata["Predecessor"] = expected[0].key.tag
+    # Three is a crowd scenario.
+    expected[1].metadata["Successor"] = expected[2].key.tag
+    expected[2].metadata["Predecessor"] = expected[1].key.tag
+    isctest.kasp.check_keyrelationships(keys, expected)
+    for kp in expected:
+        kp.set_expected_keytimes(KSK_CONFIG)
+
+    # The first successor KSK is already being retired.
+    expected[1].timing["Retired"] = now + KSK_IPUB
+    expected[1].timing["Removed"] = now + KSK_IPUB + KSK_IRET
+
+    isctest.kasp.check_keytimes(keys, expected)
index 85e13f29cf8df07f3b2c3aee58221a118edd4510..4b0652c7f4ac96cda1e996101a2e7745ccc0efe7 100644 (file)
@@ -18,43 +18,31 @@ from common import (
     pytestmark,
     alg,
     size,
-    DEFAULT_CONFIG,
+    KSK_CONFIG,
+    KSK_LIFETIME,
+    KSK_LIFETIME_POLICY,
+    KSK_IPUB,
+    KSK_IPUBC,
+    KSK_IRET,
+    KSK_KEYTTLPROP,
     TIMEDELTA,
 )
 
 
 CDSS = ["CDS (SHA-256)"]
-CONFIG = {
-    "dnskey-ttl": TIMEDELTA["PT2H"],
-    "ds-ttl": TIMEDELTA["PT1H"],
-    "max-zone-ttl": TIMEDELTA["P1D"],
-    "parent-propagation-delay": TIMEDELTA["PT1H"],
-    "publish-safety": TIMEDELTA["P1D"],
-    "purge-keys": TIMEDELTA["PT1H"],
-    "retire-safety": TIMEDELTA["P2D"],
-    "signatures-refresh": TIMEDELTA["P7D"],
-    "signatures-validity": TIMEDELTA["P14D"],
-    "zone-propagation-delay": TIMEDELTA["PT1H"],
-}
 POLICY = "ksk-doubleksk"
-KSK_LIFETIME = TIMEDELTA["P60D"]
-LIFETIME_POLICY = int(KSK_LIFETIME.total_seconds())
-IPUB = Ipub(CONFIG)
-IPUBC = IpubC(CONFIG)
-IRET = Iret(CONFIG, zsk=False, ksk=True)
-KEYTTLPROP = CONFIG["dnskey-ttl"] + CONFIG["zone-propagation-delay"]
 OFFSETS = {}
 OFFSETS["step1-p"] = -int(TIMEDELTA["P7D"].total_seconds())
-OFFSETS["step2-p"] = -int(KSK_LIFETIME.total_seconds() - IPUBC.total_seconds())
+OFFSETS["step2-p"] = -int(KSK_LIFETIME.total_seconds() - KSK_IPUBC.total_seconds())
 OFFSETS["step2-s"] = 0
 OFFSETS["step3-p"] = -int(KSK_LIFETIME.total_seconds())
-OFFSETS["step3-s"] = -int(IPUBC.total_seconds())
-OFFSETS["step4-p"] = OFFSETS["step3-p"] - int(IRET.total_seconds())
-OFFSETS["step4-s"] = OFFSETS["step3-s"] - int(IRET.total_seconds())
-OFFSETS["step5-p"] = OFFSETS["step4-p"] - int(KEYTTLPROP.total_seconds())
-OFFSETS["step5-s"] = OFFSETS["step4-s"] - int(KEYTTLPROP.total_seconds())
-OFFSETS["step6-p"] = OFFSETS["step5-p"] - int(CONFIG["purge-keys"].total_seconds())
-OFFSETS["step6-s"] = OFFSETS["step5-s"] - int(CONFIG["purge-keys"].total_seconds())
+OFFSETS["step3-s"] = -int(KSK_IPUBC.total_seconds())
+OFFSETS["step4-p"] = OFFSETS["step3-p"] - int(KSK_IRET.total_seconds())
+OFFSETS["step4-s"] = OFFSETS["step3-s"] - int(KSK_IRET.total_seconds())
+OFFSETS["step5-p"] = OFFSETS["step4-p"] - int(KSK_KEYTTLPROP.total_seconds())
+OFFSETS["step5-s"] = OFFSETS["step4-s"] - int(KSK_KEYTTLPROP.total_seconds())
+OFFSETS["step6-p"] = OFFSETS["step5-p"] - int(KSK_CONFIG["purge-keys"].total_seconds())
+OFFSETS["step6-s"] = OFFSETS["step5-s"] - int(KSK_CONFIG["purge-keys"].total_seconds())
 
 
 def test_ksk_doubleksk_step1(alg, size, servers):
@@ -64,14 +52,14 @@ def test_ksk_doubleksk_step1(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step1-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step1-p']}",
         ],
         # Next key event is when the successor KSK needs to be published.
         # That is the KSK lifetime - prepublication time (minus time
         # already passed).
-        "nextev": KSK_LIFETIME - IPUB - timedelta(days=7),
+        "nextev": KSK_LIFETIME - KSK_IPUB - timedelta(days=7),
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
 
 
 def test_ksk_doubleksk_step2(alg, size, servers):
@@ -85,14 +73,14 @@ def test_ksk_doubleksk_step2(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step2-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{OFFSETS['step2-s']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step2-p']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:{OFFSETS['step2-s']}",
         ],
         "keyrelationships": [1, 2],
         # Next key event is when the successor KSK becomes OMNIPRESENT.
-        "nextev": IPUB,
+        "nextev": KSK_IPUB,
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
 
 
 def test_ksk_doubleksk_step3(alg, size, servers):
@@ -108,17 +96,17 @@ def test_ksk_doubleksk_step3(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step3-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSETS['step3-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSETS['step3-s']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{OFFSETS['step3-p']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{OFFSETS['step3-s']}",
         ],
         "keyrelationships": [1, 2],
         # Next key event is when the predecessor DS has been replaced with
         # the successor DS and enough time has passed such that the all
         # validators that have this DS RRset cached only know about the
         # successor DS.  This is the the retire interval.
-        "nextev": IRET,
+        "nextev": KSK_IRET,
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
 
 
 def test_ksk_doubleksk_step4(alg, size, servers):
@@ -133,15 +121,15 @@ def test_ksk_doubleksk_step4(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step4-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{OFFSETS['step4-p']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4-s']}",
         ],
         "keyrelationships": [1, 2],
         # Next key event is when the DNSKEY enters the HIDDEN state.
         # This is the DNSKEY TTL plus zone propagation delay.
-        "nextev": KEYTTLPROP,
+        "nextev": KSK_KEYTTLPROP,
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
 
 
 def test_ksk_doubleksk_step5(alg, size, servers):
@@ -154,15 +142,15 @@ def test_ksk_doubleksk_step5(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step5-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{OFFSETS['step5-p']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step5-s']}",
         ],
         "keyrelationships": [1, 2],
         # Next key event is when the new successor needs to be published.
         # This is the KSK lifetime minus Ipub minus Iret minus time elapsed.
-        "nextev": KSK_LIFETIME - IPUB - IRET - KEYTTLPROP,
+        "nextev": KSK_LIFETIME - KSK_IPUB - KSK_IRET - KSK_KEYTTLPROP,
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
 
 
 def test_ksk_doubleksk_step6(alg, size, servers):
@@ -172,8 +160,8 @@ def test_ksk_doubleksk_step6(alg, size, servers):
         "cdss": CDSS,
         "keyprops": [
             f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{OFFSETS['step6-p']}",
-            f"ksk {LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}",
+            f"ksk {KSK_LIFETIME_POLICY} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{OFFSETS['step6-s']}",
         ],
         "nextev": None,
     }
-    isctest.kasp.check_rollover_step(servers["ns3"], CONFIG, POLICY, step)
+    isctest.kasp.check_rollover_step(servers["ns3"], KSK_CONFIG, POLICY, step)
index a5429e195c41e5ea6f41f4aecf7f5989e2a89b90..1e3ab1585a8a576c9b72864c4998c962a8c9f366 100644 (file)
@@ -108,6 +108,24 @@ ALGOROLL_OFFSETS["step6"] = ALGOROLL_OFFSETS["step5"] - int(
     ALGOROLL_IRET.total_seconds()
 )
 ALGOROLL_OFFVAL = -DURATION["P7D"]
+KSK_CONFIG = {
+    "dnskey-ttl": TIMEDELTA["PT2H"],
+    "ds-ttl": TIMEDELTA["PT1H"],
+    "max-zone-ttl": TIMEDELTA["P1D"],
+    "parent-propagation-delay": TIMEDELTA["PT1H"],
+    "publish-safety": TIMEDELTA["P1D"],
+    "purge-keys": TIMEDELTA["PT1H"],
+    "retire-safety": TIMEDELTA["P2D"],
+    "signatures-refresh": TIMEDELTA["P7D"],
+    "signatures-validity": TIMEDELTA["P14D"],
+    "zone-propagation-delay": TIMEDELTA["PT1H"],
+}
+KSK_LIFETIME = TIMEDELTA["P60D"]
+KSK_LIFETIME_POLICY = int(KSK_LIFETIME.total_seconds())
+KSK_IPUB = Ipub(KSK_CONFIG)
+KSK_IPUBC = IpubC(KSK_CONFIG)
+KSK_IRET = Iret(KSK_CONFIG, zsk=False, ksk=True)
+KSK_KEYTTLPROP = KSK_CONFIG["dnskey-ttl"] + KSK_CONFIG["zone-propagation-delay"]
 
 
 @pytest.fixture
index 80e76fae87a2fe46015b5ab21377fab75a249927..209d72cb09e4067cdd6dbeb78a45086fd255af18 100644 (file)
@@ -67,26 +67,3 @@ dnssec-policy "zsk-prepub" {
        zone-propagation-delay PT1H;
        max-zone-ttl 1d;
 };
-
-dnssec-policy "ksk-doubleksk" {
-       signatures-refresh P1W;
-       signatures-validity P2W;
-       signatures-validity-dnskey P2W;
-
-       dnskey-ttl 2h;
-       publish-safety P1D;
-       retire-safety P2D;
-       purge-keys PT1H;
-
-       cdnskey no;
-       keys {
-               ksk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
-               zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
-       };
-
-       zone-propagation-delay PT1H;
-       max-zone-ttl 1d;
-
-       parent-ds-ttl 3600;
-       parent-propagation-delay PT1H;
-};
index 20e597d7ac52cc56ce2cddcd459fc8f16c13cc35..25e7e9b6ee980c58b7a3dfd55e7ad992a8804087 100644 (file)
@@ -100,14 +100,3 @@ zone "step6.zsk-prepub.autosign" {
        file "step6.zsk-prepub.autosign.db";
        dnssec-policy "zsk-prepub";
 };
-
-/*
- * Zone for testing GL #2375: Three is a crowd.
- */
-zone "three-is-a-crowd.kasp" {
-        type primary;
-        file "three-is-a-crowd.kasp.db";
-        inline-signing yes;
-        /* Use same policy as KSK rollover test zones. */
-        dnssec-policy "ksk-doubleksk";
-};
index 9fa044b09f143f6e6ab65a91de674030b0e2222c..82271ff007ee4ba4821b29cf22194b26a74e0477 100644 (file)
@@ -315,45 +315,3 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK1" >>"$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile"
 cp $infile $zonefile
 $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Test #2375, the "three is a crowd" bug, where a new key is introduced but the
-# previous rollover has not finished yet. In other words, we have a key KEY2
-# that is the successor of key KEY1, and we introduce a new key KEY3 that is
-# the successor of key KEY2:
-#
-#     KEY1 < KEY2 < KEY3.
-#
-# The expected behavior is that all three keys remain in the zone, and not
-# the bug behavior where KEY2 is removed and immediately replaced with KEY3.
-#
-# Set up a zone that has a KSK (KEY1) and have the successor key (KEY2)
-# published as well.
-setup three-is-a-crowd.kasp
-# These times are the same as step3.ksk-doubleksk.autosign.
-TpubN="now-60d"
-TactN="now-1413h"
-TretN="now"
-TremN="now+50h"
-TpubN1="now-27h"
-TsbmN1="now"
-TactN1="${TretN}"
-TretN1="now+60d"
-TremN1="now+1490h"
-ksktimes="-P ${TpubN}  -A ${TpubN}  -P sync ${TactN}  -I ${TretN}  -D ${TremN} -D sync ${TactN1}"
-newtimes="-P ${TpubN1} -A ${TactN1} -P sync ${TsbmN1} -I ${TretN1} -D ${TremN1}"
-zsktimes="-P ${TpubN}  -A ${TpubN}"
-KSK1=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1)
-KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $newtimes $zone 2>keygen.out.$zone.2)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.3)
-$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1
-$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.2 2>&1
-$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.3 2>&1
-# Set key rollover relationship.
-key_successor $KSK1 $KSK2
-# Sign zone.
-cat template.db.in "${KSK1}.key" "${KSK2}.key" "${ZSK}.key" >"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK1" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile"
-private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
-cp $infile $zonefile
-$SIGNER -S -x -G "cds:sha-256" -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
index 02f07969b2de57abd7c3ad53cec273b0089ec975..5b176aae676f9f7ecc6e064c67de4e52abac458e 100644 (file)
@@ -536,91 +536,3 @@ def test_rollover_zsk_prepublication(servers):
 
     for step in steps:
         isctest.kasp.check_rollover_step(server, config, policy, step)
-
-
-def test_rollover_ksk_doubleksk(servers):
-    server = servers["ns3"]
-    policy = "ksk-doubleksk"
-    cdss = ["CDS (SHA-256)"]
-    config = {
-        "dnskey-ttl": timedelta(hours=2),
-        "ds-ttl": timedelta(seconds=3600),
-        "max-zone-ttl": timedelta(days=1),
-        "parent-propagation-delay": timedelta(hours=1),
-        "publish-safety": timedelta(days=1),
-        "purge-keys": timedelta(hours=1),
-        "retire-safety": timedelta(days=2),
-        "signatures-refresh": timedelta(days=7),
-        "signatures-validity": timedelta(days=14),
-        "zone-propagation-delay": timedelta(hours=1),
-    }
-    ttl = int(config["dnskey-ttl"].total_seconds())
-    alg = os.environ["DEFAULT_ALGORITHM_NUMBER"]
-    size = os.environ["DEFAULT_BITS"]
-    ksk_lifetime = timedelta(days=60)
-    lifetime_policy = int(ksk_lifetime.total_seconds())
-
-    ipub = Ipub(config)
-    iret = Iret(config, zsk=False, ksk=True)
-
-    # Test #2375: Scheduled rollovers are happening faster than they can finish.
-    isctest.log.info(
-        "check that fast rollovers do not remove dependent keys from zone (#2375)"
-    )
-    offset1 = -int(timedelta(days=60).total_seconds())
-    offset2 = -int(timedelta(hours=27).total_seconds())
-    zone = "three-is-a-crowd.kasp"
-    step = {
-        "zone": zone,
-        "cdss": cdss,
-        "keyprops": [
-            f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offset1}",
-            f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{offset2}",
-            f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offset1}",
-        ],
-        "keyrelationships": [0, 1],
-    }
-    isctest.kasp.check_rollover_step(servers["ns3"], config, policy, step)
-
-    # Rollover successor KSK (with DS in rumoured state).
-    expected = isctest.kasp.policy_to_properties(ttl, step["keyprops"])
-    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
-    isctest.kasp.check_keys(zone, keys, expected)
-    key = expected[1].key
-    now = KeyTimingMetadata.now()
-    with server.watch_log_from_here() as watcher:
-        server.rndc(f"dnssec -rollover -key {key.tag} -when {now} {zone}")
-        watcher.wait_for_line(f"keymgr: {zone} done")
-
-    # We now expect four keys (3x KSK, 1x ZSK).
-    step = {
-        "zone": zone,
-        "cdss": cdss,
-        "keyprops": [
-            f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offset1}",
-            f"ksk {lifetime_policy} {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{offset2}",
-            f"ksk {lifetime_policy} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden offset:0",
-            f"zsk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offset1}",
-        ],
-        "check-keytimes": False,  # checked manually with modified values
-    }
-    isctest.kasp.check_rollover_step(servers["ns3"], config, policy, step)
-
-    expected = isctest.kasp.policy_to_properties(ttl, step["keyprops"])
-    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
-    isctest.kasp.check_keys(zone, keys, expected)
-
-    expected[0].metadata["Successor"] = expected[1].key.tag
-    expected[1].metadata["Predecessor"] = expected[0].key.tag
-    # Three is a crowd scenario.
-    expected[1].metadata["Successor"] = expected[2].key.tag
-    expected[2].metadata["Predecessor"] = expected[1].key.tag
-    isctest.kasp.check_keyrelationships(keys, expected)
-    for kp in expected:
-        kp.set_expected_keytimes(config, offset=None)
-
-    # The first successor KSK is already being retired.
-    expected[1].timing["Retired"] = now + ipub
-    expected[1].timing["Removed"] = now + ipub + iret
-
-    isctest.kasp.check_keytimes(keys, expected)