]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
convert dnssec-policy tests to python
authorEvan Hunt <each@isc.org>
Sat, 28 Jun 2025 00:43:13 +0000 (17:43 -0700)
committerEvan Hunt <each@isc.org>
Thu, 31 Jul 2025 19:55:40 +0000 (12:55 -0700)
move the signatures-validity tests to tests_policy.py

bin/tests/system/dnssec/ns3/named.conf.j2
bin/tests/system/dnssec/ns3/siginterval1.conf [deleted file]
bin/tests/system/dnssec/ns3/siginterval2.conf [deleted file]
bin/tests/system/dnssec/setup.sh
bin/tests/system/dnssec/tests.sh
bin/tests/system/dnssec/tests_policy.py [new file with mode: 0644]

index a9a1b207bf3cd66ffb5d52f34af5c1c79175cec7..47d0422ad2cd872174751ed6e7b952dae1baa839 100644 (file)
@@ -13,6 +13,8 @@
 
 // NS3
 
+{% set long_sigs = long_sigs  | default(False) %}
+
 options {
        query-source address 10.53.0.3;
        notify-source 10.53.0.3;
@@ -464,28 +466,27 @@ zone "extended-ds-unknown-oid.example" {
         file "extended-ds-unknown-oid.example.db.signed";
 };
 
-dnssec-policy "siginterval1" {
+dnssec-policy "siginterval" {
        keys {
                ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
                zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
        };
 
-       signatures-validity 1d;
-       signatures-refresh 21h;
+       {% if long_sigs  %}
+               signatures-validity 35d;
+               signatures-refresh 28d;
+       {% else %}
+               signatures-validity 1d;
+               signatures-refresh 21h;
+       {% endif %}
        signatures-validity-dnskey 90d;
 };
 
-dnssec-policy "siginterval2" {
-       keys {
-               ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
-               zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
-       };
-
-       signatures-validity 35d;
-       signatures-refresh 28d;
-       signatures-validity-dnskey 90d;
+zone "siginterval.example" {
+       type primary;
+       allow-update { any; };
+       dnssec-policy siginterval;
+       file "siginterval.example.db";
 };
 
-include "siginterval.conf";
-
 include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns3/siginterval1.conf b/bin/tests/system/dnssec/ns3/siginterval1.conf
deleted file mode 100644 (file)
index 1d82f68..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.
- */
-
-zone "siginterval.example" {
-       type primary;
-       allow-update { any; };
-       dnssec-policy siginterval1;
-       file "siginterval.example.db";
-};
diff --git a/bin/tests/system/dnssec/ns3/siginterval2.conf b/bin/tests/system/dnssec/ns3/siginterval2.conf
deleted file mode 100644 (file)
index fa9c626..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.
- */
-
-zone "siginterval.example" {
-       type primary;
-       allow-update { any; };
-       dnssec-policy siginterval2;
-       file "siginterval.example.db";
-};
index c6234f686c3e9bd6ee1823322dd7f78565a033a7..14970719b945d1723d87a65b9eeceedac2078cc9 100644 (file)
@@ -28,11 +28,6 @@ copy_setports ns4/named1.conf.in ns4/named.conf
   } >>../ns3/bogus.example.db.signed
 )
 
-(
-  cd ns3
-  cp -f siginterval1.conf siginterval.conf
-)
-
 (
   cd ns5
   $SHELL sign.sh
index dc5f77bb742ed7b04d1607a6dd49b3a45c5a006c..b0033f61277e6ea0856fbe9bf97f896057079011 100644 (file)
@@ -25,10 +25,6 @@ dig_with_opts() {
   "$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
 }
 
-dig_with_additionalopts() {
-  "$DIG" +noall +additional +dnssec -p "$PORT" "$@"
-}
-
 dig_with_answeropts() {
   "$DIG" +noall +answer +dnssec -p "$PORT" "$@"
 }
@@ -79,11 +75,6 @@ checkprivate() {
   return 1
 }
 
-# strip NS and RRSIG NS from input
-stripns() {
-  awk '($4 == "NS") || ($4 == "RRSIG" && $5 == "NS") { next} { print }' "$1"
-}
-
 #
 # Ensure there is not multiple consecutive blank lines.
 # Ensure there is a blank line before "Start view" and
@@ -1616,26 +1607,6 @@ n=$((n + 1))
 test "$ret" -eq 0 || echo_i "failed"
 status=$((status + ret))
 
-echo_i "checking that the NSEC record is properly generated when DNSKEY are added by dnssec-policy ($n)"
-ret=0
-dig_with_opts +dnssec a auto-nsec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1
-grep "IN.NSEC[^3].* DNSKEY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that the NSEC3 record is properly generated when DNSKEY are added by dnssec-policy ($n)"
-ret=0
-dig_with_opts +dnssec a auto-nsec3.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1
-grep "IN.NSEC3 .* DNSKEY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
 echo_i "checking that signing records have been marked as complete ($n)"
 ret=0
 checkprivate dynamic.example 10.53.0.3 || ret=1
@@ -2060,53 +2031,6 @@ n=$((n + 1))
 test "$ret" -eq 0 || echo_i "failed"
 status=$((status + ret))
 
-echo_i "check that increasing the signatures-validity resigning triggers re-signing ($n)"
-ret=0
-before=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
-cp ns3/siginterval2.conf ns3/siginterval.conf
-rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
-i=10
-while [ "$i" -ge 0 ]; do
-  after=$($DIG axfr siginterval.example -p "$PORT" @10.53.0.3 | grep RRSIG.SOA)
-  test "$before" != "$after" && break
-  sleep 1
-  i=$((i - 1))
-done
-n=$((n + 1))
-if test "$before" = "$after"; then
-  echo_i "failed"
-  ret=1
-fi
-status=$((status + ret))
-
-if [ -x "$PYTHON" ]; then
-  echo_i "check signatures-validity-dnskey sets longer expiry for DNSKEY ($n)"
-  ret=0
-  rndccmd 10.53.0.3 sign siginterval.example 2>&1 | sed 's/^/ns3 /' | cat_i
-  # convert expiry date to a comma-separated list of integers python can
-  # use as input to date(). strip leading 0s in months and days so
-  # python3 will recognize them as integers.
-  $DIG +dnssec +short -p "$PORT" @10.53.0.3 soa siginterval.example >dig.out.soa.test$n || ret=1
-  soaexpire=$(awk '$1 ~ /SOA/ { print $5 }' dig.out.soa.test$n \
-    | sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' \
-    | sed 's/ 0/ /g')
-  $DIG +dnssec +short -p "$PORT" @10.53.0.3 dnskey siginterval.example >dig.out.dnskey.test$n || ret=1
-  dnskeyexpire=$(awk '$1 ~ /DNSKEY/ { print $5; exit 0 }' dig.out.dnskey.test$n \
-    | sed 's/\(....\)\(..\)\(..\).*/\1, \2, \3/' \
-    | sed 's/ 0/ /g')
-  $PYTHON >python.out.$n <<EOF
-from datetime import date;
-ke=date($dnskeyexpire)
-se=date($soaexpire)
-print((ke-se).days);
-EOF
-  diff=$(cat python.out.$n)
-  [ "$diff" -ge 55 ] || ret=1
-  n=$((n + 1))
-  test "$ret" -eq 0 || echo_i "failed"
-  status=$((status + ret))
-fi
-
 copy_setports ns4/named4.conf.in ns4/named.conf
 rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
 sleep 3
@@ -3009,17 +2933,6 @@ n=$((n + 1))
 test "$ret" -eq 0 || echo_i "failed"
 status=$((status + ret))
 
-echo_i "checking signatures-validity second field hours vs days ($n)"
-ret=0
-# zone configured with 'signatures-validity 500d; signatures-refresh 1d'
-# 499 days in the future w/ a 20 minute runtime to now allowance
-min=$(TZ=UTC $PERL -e '@lt=localtime(time() + 499*3600*24 - 20*60); printf "%.4d%0.2d%0.2d%0.2d%0.2d%0.2d\n",$lt[5]+1900,$lt[4]+1,$lt[3],$lt[2],$lt[1],$lt[0];')
-dig_with_opts @10.53.0.2 hours-vs-days AXFR >dig.out.ns2.test$n
-awk -v min=$min '$4 == "RRSIG" { if ($9 < min) { exit(1); } }' dig.out.ns2.test$n || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
 echo_i "checking validation succeeds during transition to signed ($n)"
 ret=0
 dig_with_opts @10.53.0.4 inprogress A >dig.out.ns4.test$n || ret=1
diff --git a/bin/tests/system/dnssec/tests_policy.py b/bin/tests/system/dnssec/tests_policy.py
new file mode 100644 (file)
index 0000000..bbeb818
--- /dev/null
@@ -0,0 +1,86 @@
+# 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.
+
+from datetime import timedelta
+import time
+
+from dns import rdatatype
+
+import isctest
+
+
+def is_rrsig_soa(rrset):
+    return rrset.rdtype == rdatatype.RRSIG and rrset.covers == rdatatype.SOA
+
+
+def test_signatures_validity(servers, templates):
+    # check that increasing signatures-validity triggers resigning
+    msg = isctest.query.create("siginterval.example.", "AXFR")
+    res = isctest.query.tcp(msg, "10.53.0.3")
+    before = next(filter(is_rrsig_soa, res.answer))
+
+    ns3 = servers["ns3"]
+    templates.render("ns3/named.conf", {"long_sigs": True})
+    with ns3.watch_log_from_here() as watcher:
+        ns3.reconfigure(log=False)
+        watcher.wait_for_line("siginterval.example/IN (signed): sending notifies")
+
+    res = isctest.query.tcp(msg, "10.53.0.3")
+    after = next(filter(is_rrsig_soa, res.answer))
+
+    assert after != before
+
+    ns3.rndc("sign siginterval.example", log=False)
+
+    msg = isctest.query.create("siginterval.example.", "SOA")
+    res = isctest.query.tcp(msg, "10.53.0.3")
+    sexp = res.answer[-1][0].expiration
+
+    msg = isctest.query.create("siginterval.example.", "DNSKEY")
+    res = isctest.query.tcp(msg, "10.53.0.3")
+    kexp = res.answer[-1][0].expiration
+
+    delta = timedelta(seconds=kexp - sexp)
+    assert delta > timedelta(days=54)
+
+
+def test_signatures_validity_hours_vs_days():
+    # zone configured with 'signatures-validity 500d; signatures-refresh 1d'
+    msg = isctest.query.create("hours-vs-days.", "AXFR")
+    res = isctest.query.tcp(msg, "10.53.0.2")
+
+    # 499 days in the future w/ a 20 minute runtime to now allowance
+    future = timedelta(days=499) - timedelta(minutes=20)
+    minimum = time.time() + future.total_seconds()
+    for rrset in res.answer:
+        if rrset.rdtype != rdatatype.RRSIG:
+            continue
+        assert rrset[0].expiration >= minimum
+
+
+def test_nsec_chain():
+    # check that NSEC records are properly generated when DNSKEYs
+    # are added by dnssec-policy
+    msg = isctest.query.create("auto-nsec.example", "A")
+    res = isctest.query.tcp(msg, "10.53.0.4")
+    isctest.check.noerror(res)
+    isctest.check.adflag(res)
+    assert [a for a in res.authority if a.rdtype == rdatatype.NSEC]
+
+
+def test_nsec3_chain():
+    # check that NSEC3 records are properly generated when DNSKEYs
+    # are added by dnssec-policy
+    msg = isctest.query.create("auto-nsec3.example", "A")
+    res = isctest.query.tcp(msg, "10.53.0.4")
+    isctest.check.noerror(res)
+    isctest.check.adflag(res)
+    assert [a for a in res.authority if a.rdtype == rdatatype.NSEC3]