]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Rewrite nsec3 system test to pytest (3/4)
authorMatthijs Mekking <matthijs@isc.org>
Tue, 30 Sep 2025 13:06:45 +0000 (15:06 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Fri, 21 Nov 2025 12:50:13 +0000 (13:50 +0100)
This converts two test cases:

1. A zone that previously failed to load is now fixed. Make sure the
   zone is signed correctly with the right NSEC3 parameters.

2. Test case to ensure the salt is the same after a restart, i.e. no
   re-salting takes place. Previously we only tested with salt length
   0, this commit adds a test case for salt length 8 as well.

bin/tests/system/nsec3/tests.sh
bin/tests/system/nsec3/tests_nsec3_reconfig.py
bin/tests/system/nsec3/tests_nsec3_reload.py [new file with mode: 0644]
bin/tests/system/nsec3/tests_nsec3_restart.py [new file with mode: 0644]

index 9a4a2d22f7d095b664d283852a715837fd66aaf7..d22b3fd65f2613063f568d0814a4ac3901e7c0cd 100644 (file)
@@ -235,44 +235,6 @@ key_clear "KEY2"
 key_clear "KEY3"
 key_clear "KEY4"
 
-# Test NSEC3 and NSEC3PARAM is the same after restart
-set_zone_policy "nsec3.kasp" "nsec3" 1 3600
-set_nsec3param "0" "0"
-set_key_default_values "KEY1"
-echo_i "check zone ${ZONE} before restart"
-check_nsec3
-
-# Restart named, NSEC3 should stay the same.
-ret=0
-echo "stop ns3"
-stop_server --use-rndc --port ${CONTROLPORT} ${DIR} || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-ret=0
-echo "start ns3"
-start_server --noclean --restart --port ${PORT} ${DIR}
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-prevsalt="${SALT}"
-set_zone_policy "nsec3.kasp" "nsec3" 1 3600
-set_nsec3param "0" "0"
-set_key_default_values "KEY1"
-SALT="${prevsalt}"
-echo_i "check zone ${ZONE} after restart has salt ${SALT}"
-check_nsec3
-
-# Zone: nsec3-fails-to-load.kasp. (should be fixed after reload)
-cp ns3/template.db.in ns3/nsec3-fails-to-load.kasp.db
-rndc_reload ns3 10.53.0.3
-
-set_zone_policy "nsec3-fails-to-load.kasp" "nsec3" 1 3600
-set_nsec3param "0" "0"
-set_key_default_values "KEY1"
-echo_i "check zone ${ZONE} after reload"
-check_nsec3
-
 # Zone: nsec3-ent.kasp (regression test for #5108)
 n=$((n + 1))
 echo_i "check query for newly empty name does not crash ($n)"
index 7ce5846ed3b487869ddc7780ad2026a6496914c6..9178d9c716ebf7b27ad4356853d35170fbeb1e1a 100644 (file)
@@ -53,9 +53,10 @@ def after_servers_start(ns3, templates):
 
         return False
 
+    nsdir = ns3.identifier
+
     # Extra test for nsec3-change.kasp.
     zone = "nsec3-change.kasp"
-    nsdir = ns3.identifier
     fqdn = f"{zone}."
     isctest.kasp.wait_keymgr_done(ns3, zone)
     shutil.copyfile(f"{nsdir}/template2.db.in", f"{nsdir}/{zone}.db")
diff --git a/bin/tests/system/nsec3/tests_nsec3_reload.py b/bin/tests/system/nsec3/tests_nsec3_reload.py
new file mode 100644 (file)
index 0000000..0e5dd0c
--- /dev/null
@@ -0,0 +1,52 @@
+# 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
+
+import os
+import shutil
+import time
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import isctest
+from nsec3.common import (
+    ALGORITHM,
+    SIZE,
+    check_nsec3_case,
+)
+
+
+def test_nsec3_case(ns3):
+    # Get test parameters.
+    params = {
+        "zone": "nsec3-fails-to-load.kasp",
+        "policy": "nsec3",
+        "key-properties": [
+            f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
+        ],
+    }
+    zone = params["zone"]
+
+    # nsec3-fails-to-load.kasp. fails to load (should be fixed after reload).
+    zone = "nsec3-fails-to-load.kasp"
+    with ns3.watch_log_from_start() as watcher:
+        watcher.wait_for_line(f"zone {zone}/IN (unsigned): not loaded due to errors.")
+
+    shutil.copyfile(f"{ns3.identifier}/template.db.in", f"{ns3.identifier}/{zone}.db")
+    ns3.rndc(f"reload {zone}")
+
+    # First make sure the zone is properly signed.
+    isctest.kasp.wait_keymgr_done(ns3, zone)
+
+    # Test case.
+    check_nsec3_case(ns3, params)
diff --git a/bin/tests/system/nsec3/tests_nsec3_restart.py b/bin/tests/system/nsec3/tests_nsec3_restart.py
new file mode 100644 (file)
index 0000000..9415040
--- /dev/null
@@ -0,0 +1,119 @@
+# 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
+
+import os
+
+import dns.update
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import isctest
+import isctest.mark
+from nsec3.common import (
+    ALGORITHM,
+    SIZE,
+    default_config,
+    pytestmark,
+    check_auth_nsec3,
+    check_nsec3param,
+)
+
+
+def perform_nsec3_tests(server, params):
+    # Get test parameters.
+    zone = params["zone"]
+    fqdn = f"{zone}."
+    policy = params["policy"]
+    keydir = server.identifier
+    config = default_config
+    ttl = int(config.get("dnskey-ttl", 3600).total_seconds())
+    minimum = params.get("soa-minimum", 3600)
+    expected = isctest.kasp.policy_to_properties(ttl=ttl, keys=params["key-properties"])
+
+    iterations = 0
+    optout = 0
+    saltlen = 0
+    if "nsec3param" in params:
+        optout = params["nsec3param"].get("optout", 0)
+        saltlen = params["nsec3param"].get("salt-length", 0)
+
+    match = f"{fqdn} {minimum} IN NSEC3PARAM 1 0 {iterations}"
+
+    # Test case.
+    isctest.log.info(f"check nsec3 case zone {zone} policy {policy}")
+
+    # First make sure the zone is properly signed.
+    isctest.kasp.wait_keymgr_done(server, zone)
+
+    keys = isctest.kasp.keydir_to_keylist(zone, keydir)
+    isctest.kasp.check_keys(zone, keys, expected)
+    isctest.kasp.check_dnssec_verify(server, zone)
+    isctest.kasp.check_apex(server, zone, keys, [])
+
+    query = isctest.query.create(fqdn, dns.rdatatype.NSEC3PARAM)
+    response = isctest.query.tcp(query, server.ip)
+    assert response.rcode() == dns.rcode.NOERROR
+
+    salt = check_nsec3param(response, match, saltlen)
+
+    query = isctest.query.create(f"nosuchname.{fqdn}", dns.rdatatype.A)
+    response = isctest.query.tcp(query, server.ip)
+    assert response.rcode() == dns.rcode.NXDOMAIN
+    check_auth_nsec3(response, iterations, optout, salt)
+
+    return salt
+
+
+@pytest.mark.parametrize(
+    "params",
+    [
+        pytest.param(
+            {
+                "zone": "nsec3.kasp",
+                "policy": "nsec3",
+                "key-properties": [
+                    f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
+                ],
+            },
+            id="nsec3.kasp",
+        ),
+        pytest.param(
+            {
+                "zone": "nsec3-other.kasp",
+                "policy": "nsec3-other",
+                "nsec3param": {
+                    "optout": 1,
+                    "salt-length": 8,
+                },
+                "key-properties": [
+                    f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
+                ],
+            },
+            id="nsec3-other.kasp",
+        ),
+    ],
+)
+def test_nsec3_case(ns3, params):
+    zone = params["zone"]
+    salt = perform_nsec3_tests(ns3, params)
+
+    # Test NSEC3 and NSEC3PARAM is the same after restart
+    isctest.log.info(f"check zone {zone} after restart has salt {salt}")
+    prevsalt = salt
+
+    # Restart named, NSEC3 should stay the same.
+    ns3.stop()
+    ns3.start(["--noclean", "--restart", "--port", os.environ["PORT"]])
+
+    salt = perform_nsec3_tests(ns3, params)
+    assert prevsalt == salt