]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Isolate rollover-multisigner test case
authorNicki Křížek <nicki@isc.org>
Wed, 11 Jun 2025 14:33:53 +0000 (16:33 +0200)
committerNicki Křížek <nicki@isc.org>
Fri, 18 Jul 2025 11:43:51 +0000 (13:43 +0200)
bin/tests/system/rollover-multisigner/common.py [new symlink]
bin/tests/system/rollover-multisigner/ns3/kasp.conf.j2 [new file with mode: 0644]
bin/tests/system/rollover-multisigner/ns3/named.common.conf.j2 [new symlink]
bin/tests/system/rollover-multisigner/ns3/named.conf.j2 [new file with mode: 0644]
bin/tests/system/rollover-multisigner/ns3/template.db.in [new symlink]
bin/tests/system/rollover-multisigner/setup.sh [new file with mode: 0644]
bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py [new file with mode: 0644]
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-multisigner/common.py b/bin/tests/system/rollover-multisigner/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-multisigner/ns3/kasp.conf.j2 b/bin/tests/system/rollover-multisigner/ns3/kasp.conf.j2
new file mode 100644 (file)
index 0000000..22c8f5e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+dnssec-policy "multisigner-model2" {
+       dnskey-ttl 3600;
+       inline-signing no;
+
+       keys {
+               ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535;
+               zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535;
+       };
+};
diff --git a/bin/tests/system/rollover-multisigner/ns3/named.common.conf.j2 b/bin/tests/system/rollover-multisigner/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-multisigner/ns3/named.conf.j2 b/bin/tests/system/rollover-multisigner/ns3/named.conf.j2
new file mode 100644 (file)
index 0000000..bbc0850
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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";
+
+/* RFC 8901 Multi-signer Model 2. */
+zone "multisigner-model2.kasp" {
+        type primary;
+        file "multisigner-model2.kasp.db";
+        dnssec-policy "multisigner-model2";
+        allow-update { any; };
+};
+
+/*
+ * A zone that starts with keys that have tags that are
+ * outside of the desired multi-signer key tag range.
+ */
+zone "single-to-multisigner.kasp" {
+        type primary;
+        file "single-to-multisigner.kasp.db";
+        dnssec-policy "multisigner-model2";
+        allow-update { any; };
+};
diff --git a/bin/tests/system/rollover-multisigner/ns3/template.db.in b/bin/tests/system/rollover-multisigner/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-multisigner/setup.sh b/bin/tests/system/rollover-multisigner/setup.sh
new file mode 100644 (file)
index 0000000..d9937ad
--- /dev/null
@@ -0,0 +1,67 @@
+#!/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"
+
+# Multi-signer zones.
+setup "multisigner-model2.kasp"
+cp template.db.in "$zonefile"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.2)
+cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db"
+cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db"
+# Import a ZSK of another provider into the DNSKEY RRset.
+ZSK1=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 -M 0:32767 $zone 2>keygen.out.$zone.3)
+cat "../${ZSK1}.key" | grep -v ";.*" >>"${zone}.db"
+
+# We are changing an existing single-signed zone to multi-signed
+# zone where the key tags do not match the dnssec-policy key tag range
+setup single-to-multisigner.kasp
+T="now-7d"
+S="now-8635mi" # T - 1d5m
+keytimes="-P $T -A $T"
+cdstimes="-P sync $S"
+KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1)
+ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 $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"
+$SIGNER -PS -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}" $infile >signer.out.$zone.1 2>&1
+echo "Lifetime: 0" >>"${KSK}".state
+echo "Lifetime: 0" >>"${ZSK}".state
diff --git a/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py b/bin/tests/system/rollover-multisigner/tests_rollover_multisigner.py
new file mode 100644 (file)
index 0000000..9c2403c
--- /dev/null
@@ -0,0 +1,173 @@
+# 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 os
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import dns.update
+
+import isctest
+from isctest.kasp import Iret
+from common import (
+    pytestmark,
+    alg,
+    size,
+)
+
+
+def test_rollover_multisigner(servers, alg, size):
+    server = servers["ns3"]
+    policy = "multisigner-model2"
+    config = {
+        "dnskey-ttl": timedelta(hours=1),
+        "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=5),
+        "signatures-validity": timedelta(days=14),
+        "zone-propagation-delay": timedelta(minutes=5),
+    }
+    ttl = int(config["dnskey-ttl"].total_seconds())
+
+    offset = -timedelta(days=7)
+    offval = int(offset.total_seconds())
+
+    def keygen(zone):
+        keygen_command = [
+            os.environ.get("KEYGEN"),
+            "-a",
+            alg,
+            "-L",
+            "3600",
+            "-M",
+            "0:32767",
+            zone,
+        ]
+
+        return isctest.run.cmd(keygen_command).stdout.decode("utf-8")
+
+    zone = "multisigner-model2.kasp"
+
+    isctest.kasp.check_dnssec_verify(server, zone)
+
+    key_properties = [
+        f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535",
+        f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured tag-range:32768-65535",
+    ]
+    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
+
+    newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"]
+    expected2 = isctest.kasp.policy_to_properties(ttl, newprops)
+    expected2[0].properties["private"] = False
+    expected2[0].properties["legacy"] = True
+    expected = expected + expected2
+
+    ownkeys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
+    extkeys = isctest.kasp.keydir_to_keylist(zone)
+    keys = ownkeys + extkeys
+    ksks = [k for k in ownkeys if k.is_ksk()]
+    zsks = [k for k in ownkeys if not k.is_ksk()]
+    zsks = zsks + extkeys
+
+    isctest.kasp.check_keys(zone, keys, expected)
+    for kp in expected:
+        kp.set_expected_keytimes(config)
+    isctest.kasp.check_keytimes(keys, expected)
+    isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy)
+    isctest.kasp.check_apex(server, zone, ksks, zsks)
+    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
+
+    # Update zone with ZSK from another provider for zone.
+    out = keygen(zone)
+    newkeys = isctest.kasp.keystr_to_keylist(out)
+    newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"]
+    expected2 = isctest.kasp.policy_to_properties(ttl, newprops)
+    expected2[0].properties["private"] = False
+    expected2[0].properties["legacy"] = True
+    expected = expected + expected2
+
+    dnskey = newkeys[0].dnskey().split()
+    rdata = " ".join(dnskey[4:])
+
+    update_msg = dns.update.UpdateMessage(zone)
+    update_msg.add(f"{dnskey[0]}", 3600, "DNSKEY", rdata)
+    server.nsupdate(update_msg)
+
+    isctest.kasp.check_dnssec_verify(server, zone)
+
+    keys = keys + newkeys
+    zsks = zsks + newkeys
+    isctest.kasp.check_keys(zone, keys, expected)
+    isctest.kasp.check_apex(server, zone, ksks, zsks)
+    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
+
+    # Remove ZSKs from the other providers for zone.
+    dnskey2 = extkeys[0].dnskey().split()
+    rdata2 = " ".join(dnskey2[4:])
+    update_msg = dns.update.UpdateMessage(zone)
+    update_msg.delete(f"{dnskey[0]}", "DNSKEY", rdata)
+    update_msg.delete(f"{dnskey2[0]}", "DNSKEY", rdata2)
+    server.nsupdate(update_msg)
+
+    isctest.kasp.check_dnssec_verify(server, zone)
+
+    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
+    keys = ownkeys
+    ksks = [k for k in ownkeys if k.is_ksk()]
+    zsks = [k for k in ownkeys if not k.is_ksk()]
+    isctest.kasp.check_keys(zone, keys, expected)
+    isctest.kasp.check_apex(server, zone, ksks, zsks)
+    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
+
+    # A zone transitioning from single-signed to multi-signed. We should have
+    # the old omnipresent keys outside of the desired key range and the new
+    # keys in the desired key range.
+    zone = "single-to-multisigner.kasp"
+
+    isctest.kasp.check_dnssec_verify(server, zone)
+
+    key_properties = [
+        f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535",
+        f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden tag-range:32768-65535",
+        f"ksk unlimited {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent tag-range:0-32767 offset:{offval}",
+        f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent tag-range:0-32767 offset:{offval}",
+    ]
+    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
+    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
+    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)
+
+    for kp in expected:
+        kp.set_expected_keytimes(config)
+
+    start = expected[0].key.get_timing("Created")
+    expected[2].timing["Retired"] = start
+    expected[2].timing["Removed"] = expected[2].timing["Retired"] + Iret(
+        config, zsk=False, ksk=True
+    )
+    expected[3].timing["Retired"] = start
+    expected[3].timing["Removed"] = expected[3].timing["Retired"] + Iret(
+        config, zsk=True, ksk=False
+    )
+
+    isctest.kasp.check_keytimes(keys, expected)
+    isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy)
+    isctest.kasp.check_apex(server, zone, ksks, zsks)
+    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
index 2ab26877f0e6b5d7575403d98a886aebdaf7d679..bbecf098a8f2d48d6f450c0de363be7fd9d1cfe1 100644 (file)
@@ -19,13 +19,3 @@ dnssec-policy "manual-rollover" {
                zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
        };
 };
-
-dnssec-policy "multisigner-model2" {
-       dnskey-ttl 3600;
-       inline-signing no;
-
-       keys {
-               ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535;
-               zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@ tag-range 32768 65535;
-       };
-};
index 63a6909144a50a8d411e4ca159790dabed252896..f44a96afd0aa3aa9a20885c445b92512941abcc8 100644 (file)
  * information regarding copyright ownership.
  */
 
-// NS3
-
 include "kasp.conf";
-
 include "named.common.conf";
 
-/* Manual rollover. */
 zone "manual-rollover.kasp" {
         type primary;
         file "manual-rollover.kasp.db";
         dnssec-policy "manual-rollover";
 };
-
-/* RFC 8901 Multi-signer Model 2. */
-zone "multisigner-model2.kasp" {
-        type primary;
-        file "multisigner-model2.kasp.db";
-        dnssec-policy "multisigner-model2";
-        allow-update { any; };
-};
-
-/*
- * A zone that starts with keys that have tags that are
- * outside of the desired multi-signer key tag range.
- */
-zone "single-to-multisigner.kasp" {
-        type primary;
-        file "single-to-multisigner.kasp.db";
-        dnssec-policy "multisigner-model2";
-        allow-update { any; };
-};
index 969b6a7e6c126d02466afc176d0a63917ab19cb9..59fd259aed4abf2f6de126ba53be1291279ce977 100644 (file)
@@ -52,30 +52,3 @@ private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile"
 private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile"
 cp $infile $zonefile
 $SIGNER -PS -x -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1
-
-# Multi-signer zones.
-setup "multisigner-model2.kasp"
-cp template.db.in "$zonefile"
-KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.2)
-cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db"
-cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db"
-# Import a ZSK of another provider into the DNSKEY RRset.
-ZSK1=$($KEYGEN -K ../ -a $DEFAULT_ALGORITHM -L 3600 -M 0:32767 $zone 2>keygen.out.$zone.3)
-cat "../${ZSK1}.key" | grep -v ";.*" >>"${zone}.db"
-
-# We are changing an existing single-signed zone to multi-signed
-# zone where the key tags do not match the dnssec-policy key tag range
-setup single-to-multisigner.kasp
-T="now-7d"
-S="now-8635mi" # T - 1d5m
-keytimes="-P $T -A $T"
-cdstimes="-P sync $S"
-KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1)
-ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -M 0:32767 -L 3600 $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"
-$SIGNER -PS -z -x -s now-2w -e now-1mi -o $zone -f "${zonefile}" $infile >signer.out.$zone.1 2>&1
-echo "Lifetime: 0" >>"${KSK}".state
-echo "Lifetime: 0" >>"${ZSK}".state
index 025bbb0d7c4b9bdf4b95cf1f4889aa59584d5419..b7804812309167f17a2e0132dd81d0c505728f0d 100644 (file)
@@ -9,17 +9,13 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
-import os
-
 from datetime import timedelta
+import os
 
 import pytest
 
-pytest.importorskip("dns", minversion="2.0.0")
-import dns.update
-
 import isctest
-from isctest.kasp import KeyTimingMetadata, Ipub, IpubC, Iret
+from isctest.kasp import KeyTimingMetadata, Ipub,  Iret
 
 from common import pytestmark
 
@@ -161,150 +157,3 @@ def test_rollover_manual(servers):
     zsk = expected[3].key
     response = server.rndc(f"dnssec -rollover -key {zsk.tag} {zone}")
     assert "key is not actively signing" in response
-
-
-def test_rollover_multisigner(servers):
-    server = servers["ns3"]
-    policy = "multisigner-model2"
-    config = {
-        "dnskey-ttl": timedelta(hours=1),
-        "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=5),
-        "signatures-validity": timedelta(days=14),
-        "zone-propagation-delay": timedelta(minutes=5),
-    }
-    ttl = int(config["dnskey-ttl"].total_seconds())
-    alg = os.environ["DEFAULT_ALGORITHM_NUMBER"]
-    size = os.environ["DEFAULT_BITS"]
-
-    offset = -timedelta(days=7)
-    offval = int(offset.total_seconds())
-
-    def keygen(zone):
-        keygen_command = [
-            os.environ.get("KEYGEN"),
-            "-a",
-            alg,
-            "-L",
-            "3600",
-            "-M",
-            "0:32767",
-            zone,
-        ]
-
-        return isctest.run.cmd(keygen_command).stdout.decode("utf-8")
-
-    zone = "multisigner-model2.kasp"
-
-    isctest.kasp.check_dnssec_verify(server, zone)
-
-    key_properties = [
-        f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535",
-        f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured tag-range:32768-65535",
-    ]
-    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
-
-    newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"]
-    expected2 = isctest.kasp.policy_to_properties(ttl, newprops)
-    expected2[0].properties["private"] = False
-    expected2[0].properties["legacy"] = True
-    expected = expected + expected2
-
-    ownkeys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
-    extkeys = isctest.kasp.keydir_to_keylist(zone)
-    keys = ownkeys + extkeys
-    ksks = [k for k in ownkeys if k.is_ksk()]
-    zsks = [k for k in ownkeys if not k.is_ksk()]
-    zsks = zsks + extkeys
-
-    isctest.kasp.check_keys(zone, keys, expected)
-    for kp in expected:
-        kp.set_expected_keytimes(config)
-    isctest.kasp.check_keytimes(keys, expected)
-    isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy)
-    isctest.kasp.check_apex(server, zone, ksks, zsks)
-    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
-
-    # Update zone with ZSK from another provider for zone.
-    out = keygen(zone)
-    newkeys = isctest.kasp.keystr_to_keylist(out)
-    newprops = [f"zsk unlimited {alg} {size} tag-range:0-32767"]
-    expected2 = isctest.kasp.policy_to_properties(ttl, newprops)
-    expected2[0].properties["private"] = False
-    expected2[0].properties["legacy"] = True
-    expected = expected + expected2
-
-    dnskey = newkeys[0].dnskey().split()
-    rdata = " ".join(dnskey[4:])
-
-    update_msg = dns.update.UpdateMessage(zone)
-    update_msg.add(f"{dnskey[0]}", 3600, "DNSKEY", rdata)
-    server.nsupdate(update_msg)
-
-    isctest.kasp.check_dnssec_verify(server, zone)
-
-    keys = keys + newkeys
-    zsks = zsks + newkeys
-    isctest.kasp.check_keys(zone, keys, expected)
-    isctest.kasp.check_apex(server, zone, ksks, zsks)
-    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
-
-    # Remove ZSKs from the other providers for zone.
-    dnskey2 = extkeys[0].dnskey().split()
-    rdata2 = " ".join(dnskey2[4:])
-    update_msg = dns.update.UpdateMessage(zone)
-    update_msg.delete(f"{dnskey[0]}", "DNSKEY", rdata)
-    update_msg.delete(f"{dnskey2[0]}", "DNSKEY", rdata2)
-    server.nsupdate(update_msg)
-
-    isctest.kasp.check_dnssec_verify(server, zone)
-
-    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
-    keys = ownkeys
-    ksks = [k for k in ownkeys if k.is_ksk()]
-    zsks = [k for k in ownkeys if not k.is_ksk()]
-    isctest.kasp.check_keys(zone, keys, expected)
-    isctest.kasp.check_apex(server, zone, ksks, zsks)
-    isctest.kasp.check_subdomain(server, zone, ksks, zsks)
-
-    # A zone transitioning from single-signed to multi-signed. We should have
-    # the old omnipresent keys outside of the desired key range and the new
-    # keys in the desired key range.
-    zone = "single-to-multisigner.kasp"
-
-    isctest.kasp.check_dnssec_verify(server, zone)
-
-    key_properties = [
-        f"ksk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden tag-range:32768-65535",
-        f"zsk unlimited {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:hidden tag-range:32768-65535",
-        f"ksk unlimited {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent tag-range:0-32767 offset:{offval}",
-        f"zsk unlimited {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent tag-range:0-32767 offset:{offval}",
-    ]
-    expected = isctest.kasp.policy_to_properties(ttl, key_properties)
-    keys = isctest.kasp.keydir_to_keylist(zone, server.identifier)
-    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)
-
-    for kp in expected:
-        kp.set_expected_keytimes(config)
-
-    start = expected[0].key.get_timing("Created")
-    expected[2].timing["Retired"] = start
-    expected[2].timing["Removed"] = expected[2].timing["Retired"] + Iret(
-        config, zsk=False, ksk=True
-    )
-    expected[3].timing["Retired"] = start
-    expected[3].timing["Removed"] = expected[3].timing["Retired"] + Iret(
-        config, zsk=True, ksk=False
-    )
-
-    isctest.kasp.check_keytimes(keys, expected)
-    isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy)
-    isctest.kasp.check_apex(server, zone, ksks, zsks)
-    isctest.kasp.check_subdomain(server, zone, ksks, zsks)