mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 08:49:58 -04:00
Add NSEC3 answer correctness test to dnssec_py
Rewrite nsec3_answer/tests_nsec3.py as dnssec_py/tests_nsec3_answer.py using the isctest.zone helpers for zone setup. ns1 (auth) and ns2 (resolver) were renumbered to ns2 and ns9 respectively to fit the existing dnssec_py server infrastructure. Assisted-by: Claude:claude-opus-4-8
This commit is contained in:
parent
b8c1b645ea
commit
ca890789cd
7 changed files with 88 additions and 156 deletions
47
bin/tests/system/dnssec_py/ns2/zones/nsec3-answer.db
Normal file
47
bin/tests/system/dnssec_py/ns2/zones/nsec3-answer.db
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
; This zone file intentionally isn't a jinja2 template.
|
||||
;
|
||||
; It needs to be read before the templates are rended, to generate hypothesis
|
||||
; test cases.
|
||||
$ORIGIN nsec3-answer.
|
||||
$TTL 300
|
||||
nsec3-answer. IN SOA . . (
|
||||
1 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
|
||||
nsec3-answer. NS ns2
|
||||
ns2 A 10.53.0.2
|
||||
|
||||
02hc3em7bdd011a0gms3hkkjt2if5vp8 A 10.0.0.0
|
||||
a A 10.0.0.1
|
||||
*.a.a A 10.0.0.6
|
||||
a.a.a.a A 10.0.0.3
|
||||
b A 10.0.0.2
|
||||
b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b A 10.0.0.2
|
||||
cname CNAME does-not-exist
|
||||
cname.cname CNAME cname
|
||||
cname.ent.cname CNAME cname.cname
|
||||
d A 10.0.0.4
|
||||
dname-to-nowhere DNAME does-not-exist
|
||||
; DNAME owner longer than target to avoid YXDOMAIN dependent on QNAME
|
||||
insecure NS a.root-servers.nil
|
||||
ns.insecure A 10.53.0.3
|
||||
a.root-servers.nil A 10.53.0.1
|
||||
secure NS a.root-servers.nil
|
||||
secure DS 11111 13 255 00
|
||||
occluded.secure A 0.0.0.0
|
||||
*.wild A 10.0.0.6
|
||||
explicit.wild A 192.0.2.66
|
||||
z A 10.0.0.26
|
||||
|
||||
; randomly generated subtree to excercise unknown corner cases
|
||||
; intentionally small, to not blow up algorithms with quadratic complexity in ZoneAnalyzer and name generator
|
||||
a.a.a.b.a.a.a.b.a.a.b.b.a.random TXT "r"
|
||||
b.b.a.a.b.b.a.a.a.b.b.a.b.a.a.a.a.a.b.a.a.b.a.b.a.b.b.b.b.b.a.a.a.a.b.a.a.a.b.a.a.b.b.a.random TXT "r"
|
||||
a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random TXT "r"
|
||||
b.b.a.b.a.b.a.a.a.b.a.a.b.a.a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random TXT "r"
|
||||
a.b.a.a.b.a.b.a.b.a.a.b.a.b.a.a.a.b.b.a.b.b.a.a.b.b.a.a.b.a.b.a.b.b.b.b.a.a.a.a.a.a.a.a.b.a.b.a.b.b.a.b.a.b.a.a.a.b.a.a.b.a.a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random TXT "r"
|
||||
a.a.a.a.a.b.b.a.a.b.a.a.b.a.a.b.b.a.a.a.b.a.a.a.b.b.b.b.b.a.a.a.b.b.b.b.b.b.a.b.b.b.a.a.b.b.b.b.a.a.a.a.b.a.b.b.a.b.a.a.b.b.b.b.b.b.b.a.b.b.a.b.a.b.a.a.a.b.b.a.a.b.b.a.b.a.b.b.a.b.b.b.a.b.b.b.b.b.a.a.b.a.a.a.b.b.a.a.a.b.b.b.b.b.a.random TXT "r"
|
||||
57
bin/tests/system/nsec3_answer/tests_nsec3.py → bin/tests/system/dnssec_py/tests_nsec3_answer.py
Executable file → Normal file
57
bin/tests/system/nsec3_answer/tests_nsec3.py → bin/tests/system/dnssec_py/tests_nsec3_answer.py
Executable file → Normal file
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
|
|
@ -11,7 +9,7 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
# Silence incorrect warnings cause by hypothesis.assume()
|
||||
# Silence incorrect warnings caused by hypothesis.assume()
|
||||
# https://github.com/pylint-dev/pylint/issues/10785#issuecomment-3677224217
|
||||
# pylint: disable=unreachable
|
||||
|
||||
|
|
@ -20,6 +18,7 @@ from dataclasses import dataclass
|
|||
from pathlib import Path
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from hypothesis import assume, given
|
||||
|
||||
|
|
@ -34,17 +33,43 @@ import dns.rdtypes.ANY.RRSIG
|
|||
import dns.rrset
|
||||
import pytest
|
||||
|
||||
from dnssec_py.common import DNSSEC_PY_MARK
|
||||
from isctest.hypothesis.strategies import dns_names, sampled_from
|
||||
from isctest.template import NS2, zones
|
||||
from isctest.zone import Zone, configure_root
|
||||
|
||||
import isctest
|
||||
import isctest.name
|
||||
|
||||
SUFFIX = dns.name.from_text(".")
|
||||
AUTH = "10.53.0.1"
|
||||
RESOLVER = "10.53.0.2"
|
||||
pytestmark = DNSSEC_PY_MARK
|
||||
|
||||
|
||||
def bootstrap():
|
||||
zone = Zone(
|
||||
"nsec3-answer",
|
||||
NS2,
|
||||
signed=True,
|
||||
)
|
||||
zone.add_keys()
|
||||
salt = int(time.time()) // 3600 % 65536
|
||||
salt_hex = f"{salt:04X}"
|
||||
isctest.log.info(f"NSEC3 salt for this hour: {salt_hex}")
|
||||
zone.sign(f"-3 {salt_hex}")
|
||||
|
||||
root = configure_root([zone])
|
||||
return {
|
||||
"trust_anchors": root.trust_anchors(),
|
||||
"zones": zones([root, zone]),
|
||||
}
|
||||
|
||||
|
||||
SUFFIX = dns.name.from_text("nsec3-answer.")
|
||||
AUTH = "10.53.0.2"
|
||||
RESOLVER = "10.53.0.9"
|
||||
TIMEOUT = 5
|
||||
ZONE = isctest.name.ZoneAnalyzer.read_path(
|
||||
Path(os.environ["srcdir"]) / "nsec3_answer/ns1/root.db.in", origin=SUFFIX
|
||||
Path(os.environ["srcdir"]) / "dnssec_py/ns2/zones/nsec3-answer.db",
|
||||
origin=SUFFIX,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -71,7 +96,7 @@ def do_test_query(
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(
|
||||
qname=sampled_from(
|
||||
|
|
@ -84,7 +109,7 @@ def test_nodata(server: str, qname: dns.name.Name, named_port: int) -> None:
|
|||
check_nodata(qname, nsec3check)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("server", [pytest.param(AUTH, id="ns1")])
|
||||
@pytest.mark.parametrize("server", [pytest.param(AUTH, id="ns2")])
|
||||
@given(
|
||||
qname=dns_names(
|
||||
suffix=(ZONE.delegations - ZONE.get_names_with_type(dns.rdatatype.DS))
|
||||
|
|
@ -116,7 +141,7 @@ def assume_nx_and_no_delegation(qname: dns.name.Name) -> None:
|
|||
assume(qname not in ZONE.all_existing_names)
|
||||
|
||||
# name must not be under a delegation or DNAME:
|
||||
# it would not work with resolver ns2
|
||||
# it would not work with resolver ns9
|
||||
assume(
|
||||
not is_related_to_any(
|
||||
qname,
|
||||
|
|
@ -127,7 +152,7 @@ def assume_nx_and_no_delegation(qname: dns.name.Name) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=dns_names(suffix=SUFFIX))
|
||||
def test_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -141,7 +166,7 @@ def test_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=sampled_from(sorted(ZONE.get_names_with_type(dns.rdatatype.CNAME))))
|
||||
def test_cname_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -157,7 +182,7 @@ def test_cname_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> N
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=dns_names(suffix=ZONE.get_names_with_type(dns.rdatatype.DNAME)))
|
||||
def test_dname_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -175,7 +200,7 @@ def test_dname_nxdomain(server: str, qname: dns.name.Name, named_port: int) -> N
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=dns_names(suffix=ZONE.ents))
|
||||
def test_ents(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -193,7 +218,7 @@ def test_ents(server: str, qname: dns.name.Name, named_port: int) -> None:
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=dns_names(suffix=ZONE.reachable_wildcard_parents))
|
||||
def test_wildcard_synthesis(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -207,7 +232,7 @@ def test_wildcard_synthesis(server: str, qname: dns.name.Name, named_port: int)
|
|||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"server", [pytest.param(AUTH, id="ns1"), pytest.param(RESOLVER, id="ns2")]
|
||||
"server", [pytest.param(AUTH, id="ns2"), pytest.param(RESOLVER, id="ns9")]
|
||||
)
|
||||
@given(qname=dns_names(suffix=ZONE.reachable_wildcard_parents))
|
||||
def test_wildcard_nodata(server: str, qname: dns.name.Name, named_port: int) -> None:
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// NS1
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type primary;
|
||||
file "root.db.signed";
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
$TTL 300
|
||||
. IN SOA . . (
|
||||
2025063000 ; serial
|
||||
600 ; refresh
|
||||
600 ; retry
|
||||
1200 ; expire
|
||||
600 ; minimum
|
||||
)
|
||||
. NS a.root-servers.nil.
|
||||
|
||||
02hc3em7bdd011a0gms3hkkjt2if5vp8. A 10.0.0.0
|
||||
a. A 10.0.0.1
|
||||
*.a.a. A 10.0.0.6
|
||||
a.a.a.a. A 10.0.0.3
|
||||
b. A 10.0.0.2
|
||||
b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b. A 10.0.0.2
|
||||
cname. CNAME does-not-exist.
|
||||
cname.cname. CNAME cname.
|
||||
cname.ent.cname. CNAME cname.cname.
|
||||
d. A 10.0.0.4
|
||||
dname-to-nowhere. DNAME does-not-exist.
|
||||
; DNAME owner longer than target to avoid YXDOMAIN dependent on QNAME
|
||||
insecure. NS a.root-servers.nil.
|
||||
ns.insecure. A 10.53.0.3
|
||||
a.root-servers.nil. A 10.53.0.1
|
||||
secure. NS a.root-servers.nil.
|
||||
secure. DS 11111 13 255 00
|
||||
occluded.secure. A 0.0.0.0
|
||||
*.wild. A 10.0.0.6
|
||||
explicit.wild. A 192.0.2.66
|
||||
z. A 10.0.0.26
|
||||
|
||||
; randomly generated subtree to excercise unknown corner cases
|
||||
; intentionally small, to not blow up algorithms with quadratic complexity in ZoneAnalyzer and name generator
|
||||
a.a.a.b.a.a.a.b.a.a.b.b.a.random. TXT "r"
|
||||
b.b.a.a.b.b.a.a.a.b.b.a.b.a.a.a.a.a.b.a.a.b.a.b.a.b.b.b.b.b.a.a.a.a.b.a.a.a.b.a.a.b.b.a.random. TXT "r"
|
||||
a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random. TXT "r"
|
||||
b.b.a.b.a.b.a.a.a.b.a.a.b.a.a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random. TXT "r"
|
||||
a.b.a.a.b.a.b.a.b.a.a.b.a.b.a.a.a.b.b.a.b.b.a.a.b.b.a.a.b.a.b.a.b.b.b.b.a.a.a.a.a.a.a.a.b.a.b.a.b.b.a.b.a.b.a.a.a.b.a.a.b.a.a.a.a.b.b.a.b.b.a.b.a.b.a.b.a.b.b.b.a.random. TXT "r"
|
||||
a.a.a.a.a.b.b.a.a.a.a.a.b.b.a.a.b.a.a.b.a.a.b.b.a.a.a.b.a.a.a.b.b.b.b.b.a.a.a.b.b.b.b.b.b.a.b.b.b.a.a.b.b.b.b.a.a.a.a.b.a.b.b.a.b.a.a.b.b.b.b.b.b.b.a.b.b.a.b.a.b.a.a.a.b.b.a.a.b.b.a.b.a.b.b.a.b.b.b.a.b.b.b.b.b.a.a.b.a.a.a.b.b.a.a.a.b.b.b.b.b.a.random. TXT "r"
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/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
|
||||
|
||||
set -e
|
||||
|
||||
zone=.
|
||||
infile=root.db.in
|
||||
zonefile=root.db
|
||||
|
||||
echo_i "ns1/sign.sh"
|
||||
|
||||
ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
|
||||
|
||||
cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile"
|
||||
|
||||
SALT="$(printf "%04x" "$(($(date +%s) / 3600 % 65536))")"
|
||||
echo_ic "NSEC3 salt for this hour: $SALT"
|
||||
"$SIGNER" -3 "$SALT" -o "$zone" "$zonefile" 2>&1 >"$zonefile.sign.log"
|
||||
|
||||
keyfile_to_initial_ds "$ksk" >managed-keys.conf
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// validating resolver
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.2;
|
||||
notify-source 10.53.0.2;
|
||||
transfer-source 10.53.0.2;
|
||||
port @PORT@;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.2; };
|
||||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
dnssec-validation yes;
|
||||
};
|
||||
|
||||
controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
include "../../_common/rndc.key";
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../_common/root.hint";
|
||||
};
|
||||
|
||||
include "../ns1/managed-keys.conf";
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#!/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
|
||||
|
||||
set -e
|
||||
|
||||
(
|
||||
cd ns1
|
||||
$SHELL sign.sh
|
||||
)
|
||||
Loading…
Reference in a new issue