From: Matthijs Mekking Date: Tue, 30 Sep 2025 13:11:22 +0000 (+0200) Subject: Rewrite nsec3 system test to pytest (4/4) X-Git-Tag: v9.21.16~38^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f5d295e2983c29415815b7c081191374a34befc;p=thirdparty%2Fbind9.git Rewrite nsec3 system test to pytest (4/4) Convert the final nsec3 system test case that deals with empty non-terminals. This is a regression test case for GL #5108. --- diff --git a/bin/tests/system/nsec3/ns3/nsec3-ent.kasp.db.j2 b/bin/tests/system/nsec3/ns3/nsec3-ent.kasp.db.j2 new file mode 100644 index 00000000000..5348dcfafaa --- /dev/null +++ b/bin/tests/system/nsec3/ns3/nsec3-ent.kasp.db.j2 @@ -0,0 +1,41 @@ +; 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. + +{% set serial = serial | default(1) %} + +$ORIGIN nsec3-ent.kasp. +$TTL 300 +nsec3-ent.kasp. IN SOA mname1. . ( + @serial@ ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns3 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 + +{% if serial == 1 %} +c A 10.0.0.3 +{% endif %} + +{% if serial == 2 %} +d A 10.0.0.3 +{% endif %} + +{% if serial == 3 %} +c A 10.0.0.3 +x.y.z A 10.0.0.4 +{% endif %} diff --git a/bin/tests/system/nsec3/ns3/setup.sh b/bin/tests/system/nsec3/ns3/setup.sh index 32ddf5e9c59..5b7053e08da 100644 --- a/bin/tests/system/nsec3/ns3/setup.sh +++ b/bin/tests/system/nsec3/ns3/setup.sh @@ -26,8 +26,7 @@ setup() { for zn in nsec-to-nsec3 nsec3 nsec3-other nsec3-change nsec3-to-nsec \ nsec3-to-optout nsec3-from-optout nsec3-dynamic \ nsec3-dynamic-change nsec3-dynamic-to-inline \ - nsec3-inline-to-dynamic nsec3-dynamic-update-inline \ - nsec3-ent; do + nsec3-inline-to-dynamic nsec3-dynamic-update-inline; do setup "${zn}.kasp" done diff --git a/bin/tests/system/nsec3/tests.sh b/bin/tests/system/nsec3/tests.sh index d22b3fd65f2..131daf052e8 100644 --- a/bin/tests/system/nsec3/tests.sh +++ b/bin/tests/system/nsec3/tests.sh @@ -235,40 +235,5 @@ key_clear "KEY2" key_clear "KEY3" key_clear "KEY4" -# Zone: nsec3-ent.kasp (regression test for #5108) -n=$((n + 1)) -echo_i "check query for newly empty name does not crash ($n)" -set_zone_policy "nsec3-ent.kasp" -set_server "ns3" "10.53.0.3" -# confirm the pre-existing name still exists -dig_with_opts +noquestion "@${SERVER}" c.$ZONE >"dig.out.$ZONE.test$n.1" || ret=1 -grep "c\.nsec3-ent\.kasp\..*IN.*A.*10\.0\.0\.3" "dig.out.$ZONE.test$n.1" >/dev/null || ret=1 -# remove a name, bump the SOA, and reload -sed -e 's/1 *; serial/2/' -e '/^c/d' ns3/template.db.in >ns3/nsec3-ent.kasp.db -rndc_reload ns3 10.53.0.3 -# try the query again -dig_with_opts +noquestion "@${SERVER}" c.$ZONE >"dig.out.$ZONE.test$n.2" || ret=1 -grep "status: NXDOMAIN" "dig.out.$ZONE.test$n.2" >/dev/null || ret=1 -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -n=$((n + 1)) -echo_i "check queries for new names below ENT do not crash ($n)" -set_zone_policy "nsec3-ent.kasp" -set_server "ns3" "10.53.0.3" -# confirm the ENT name does not exist yet -dig_with_opts +noquestion "@${SERVER}" x.y.z.$ZONE >"dig.out.$ZONE.test$n.1" || ret=1 -grep "status: NXDOMAIN" "dig.out.$ZONE.test$n.1" >/dev/null || ret=1 -# add a name with an ENT, bump the SOA, and reload ensuring the time stamp changes -sleep 1 -sed -e 's/1 *; serial/3/' ns3/template.db.in >ns3/nsec3-ent.kasp.db -echo "x.y.z A 10.0.0.4" >>ns3/nsec3-ent.kasp.db -rndc_reload ns3 10.53.0.3 -# try the query again -dig_with_opts +noquestion "@${SERVER}" x.y.z.$ZONE >"dig.out.$ZONE.test$n.2" || ret=1 -grep "x\.y\.z\.nsec3-ent\.kasp\..*IN.*A.*10\.0\.0\.4" "dig.out.$ZONE.test$n.2" >/dev/null || ret=1 -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/nsec3/tests_nsec3_reconfig.py b/bin/tests/system/nsec3/tests_nsec3_reconfig.py index 9178d9c716e..5dd27e281a7 100644 --- a/bin/tests/system/nsec3/tests_nsec3_reconfig.py +++ b/bin/tests/system/nsec3/tests_nsec3_reconfig.py @@ -354,3 +354,99 @@ def test_nsec3_case(ns3, params): ) response = ns3.rndc(f"signing -nsec3param 1 1 12 ffff {zone}") assert "zone uses dnssec-policy, use rndc dnssec command instead" in response + + +def test_nsec3_ent(ns3, templates): + # Zone: nsec3-ent.kasp (regression test for #5108) + zone = "nsec3-ent.kasp" + fqdn = f"{zone}." + policy = "nsec3" + keydir = ns3.identifier + config = default_config + ttl = int(config.get("dnskey-ttl", 3600).total_seconds()) + minimum = 3600 + keyprops = [ + f"csk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ] + expected = isctest.kasp.policy_to_properties(ttl=ttl, keys=keyprops) + + # 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(ns3, zone, reconfig=True) + + keys = isctest.kasp.keydir_to_keylist(zone, keydir) + isctest.kasp.check_keys(zone, keys, expected) + isctest.kasp.check_dnssec_verify(ns3, zone) + isctest.kasp.check_apex(ns3, zone, keys, []) + + query = isctest.query.create(fqdn, dns.rdatatype.NSEC3PARAM) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NOERROR + + match = f"{fqdn} {minimum} IN NSEC3PARAM 1 0 0" + salt = check_nsec3param(response, match, 0) + + query = isctest.query.create(f"nosuchname.{fqdn}", dns.rdatatype.A) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NXDOMAIN + check_auth_nsec3(response, 0, 0, salt) + + isctest.log.info("check query for newly empty name does not crash") + + # confirm the pre-existing name still exists + query = isctest.query.create(f"c.{fqdn}", dns.rdatatype.A) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NOERROR + + match = "10.0.0.3" + rrset = response.get_rrset( + response.answer, + dns.name.from_text(f"c.{fqdn}"), + dns.rdataclass.IN, + dns.rdatatype.A, + ) + assert rrset is not None, "no A records found in answer section" + assert match in str(rrset[0]) + + # remove a name, bump the SOA, and reload + templates.render(f"{ns3.identifier}/nsec3-ent.kasp.db", {"serial": 2}) + + with ns3.watch_log_from_here() as watcher: + ns3.rndc(f"reload {zone}") + watcher.wait_for_line(f"zone {zone}/IN (signed): sending notifies") + + # try the query again + query = isctest.query.create(f"c.{fqdn}", dns.rdatatype.A) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NXDOMAIN + + isctest.log.info("check queries for new names below ENT do not crash") + + # confirm the ENT name does not exist yet + query = isctest.query.create(f"x.y.z.{fqdn}", dns.rdatatype.A) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NXDOMAIN + + # add a name with an ENT, bump the SOA, and reload ensuring the time stamp changes + templates.render(f"{ns3.identifier}/nsec3-ent.kasp.db", {"serial": 3}) + + with ns3.watch_log_from_here() as watcher: + ns3.rndc(f"reload {zone}") + watcher.wait_for_line(f"zone {zone}/IN (signed): sending notifies") + + # try the query again + query = isctest.query.create(f"x.y.z.{fqdn}", dns.rdatatype.A) + response = isctest.query.tcp(query, ns3.ip, ns3.ports.dns, timeout=3) + assert response.rcode() == dns.rcode.NOERROR + + match = "10.0.0.4" + rrset = response.get_rrset( + response.answer, + dns.name.from_text(f"x.y.z.{fqdn}"), + dns.rdataclass.IN, + dns.rdatatype.A, + ) + assert rrset is not None, "no A records found in answer section" + assert match in str(rrset[0])