// NS3
+{% set long_sigs = long_sigs | default(False) %}
+
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
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";
+++ /dev/null
-/*
- * 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";
-};
+++ /dev/null
-/*
- * 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";
-};
} >>../ns3/bogus.example.db.signed
)
-(
- cd ns3
- cp -f siginterval1.conf siginterval.conf
-)
-
(
cd ns5
$SHELL sign.sh
"$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" "$@"
}
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
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
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
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
--- /dev/null
+# 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]