From: Evan Hunt Date: Thu, 26 Jun 2025 20:05:40 +0000 (-0700) Subject: move NTA test cases to a separate python test X-Git-Tag: v9.21.11~13^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3bfa916b38a0974c620833638351676e3e625de;p=thirdparty%2Fbind9.git move NTA test cases to a separate python test the tests of "rndc nta" behavior have been moved out of the dnssec shell test, into bin/tests/system/nta, and converted to python. features of the dnssec test framework that were needed for NTA testing have been moved to the nta test, and dnssec has been correspondingly simplified. --- diff --git a/bin/tests/system/dnssec/ns2/named.conf.j2 b/bin/tests/system/dnssec/ns2/named.conf.j2 index 3b31574579a..da6df5d5fbd 100644 --- a/bin/tests/system/dnssec/ns2/named.conf.j2 +++ b/bin/tests/system/dnssec/ns2/named.conf.j2 @@ -190,11 +190,6 @@ zone "updatecheck-kskonly.secure" { allow-update { any; }; }; -zone "corp" { - type primary; - file "corp.db"; -}; - zone "hours-vs-days" { type primary; file "hours-vs-days.db.signed"; diff --git a/bin/tests/system/dnssec/ns4/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in index a2413cef79a..66975a352af 100644 --- a/bin/tests/system/dnssec/ns4/named1.conf.in +++ b/bin/tests/system/dnssec/ns4/named1.conf.in @@ -24,10 +24,6 @@ options { recursion yes; minimal-responses no; - nta-lifetime 12s; - nta-recheck 9s; - validate-except { corp; }; - # Note: We only reference the bind.keys file here to confirm that it # is *not* being used. It contains the real root key, and we're # using a local toy root zone for the tests, so it wouldn't work. @@ -52,8 +48,3 @@ zone "." { type hint; file "../../_common/root.hint"; }; - -zone "corp" { - type static-stub; - server-addresses { 10.53.0.2; }; -}; diff --git a/bin/tests/system/dnssec/ns4/named2.conf.in b/bin/tests/system/dnssec/ns4/named2.conf.in index 04d98b89add..c8699834f33 100644 --- a/bin/tests/system/dnssec/ns4/named2.conf.in +++ b/bin/tests/system/dnssec/ns4/named2.conf.in @@ -24,10 +24,6 @@ options { recursion yes; minimal-responses no; - nta-lifetime 12s; - nta-recheck 9s; - validate-except { corp; }; - dnssec-validation auto; bindkeys-file "managed.conf"; }; @@ -45,8 +41,3 @@ zone "." { type hint; file "../../_common/root.hint"; }; - -zone "corp" { - type static-stub; - server-addresses { 10.53.0.2; }; -}; diff --git a/bin/tests/system/dnssec/ns4/named3.conf.in b/bin/tests/system/dnssec/ns4/named3.conf.in index 28a9abe8040..24012b38e72 100644 --- a/bin/tests/system/dnssec/ns4/named3.conf.in +++ b/bin/tests/system/dnssec/ns4/named3.conf.in @@ -24,10 +24,6 @@ options { recursion yes; minimal-responses no; - nta-lifetime 12s; - nta-recheck 9s; - validate-except { corp; }; - dnssec-accept-expired yes; servfail-ttl 0; @@ -48,8 +44,3 @@ zone "." { type hint; file "../../_common/root.hint"; }; - -zone "corp" { - type static-stub; - server-addresses { 10.53.0.2; }; -}; diff --git a/bin/tests/system/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in index 4655d5959eb..f5b387d0bdc 100644 --- a/bin/tests/system/dnssec/ns4/named4.conf.in +++ b/bin/tests/system/dnssec/ns4/named4.conf.in @@ -23,9 +23,6 @@ options { listen-on-v6 { none; }; minimal-responses no; - nta-lifetime 12s; - nta-recheck 9s; - disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; diff --git a/bin/tests/system/dnssec/ns5/named.conf.j2 b/bin/tests/system/dnssec/ns5/named.conf.j2 index c47306f3716..bdbd1f3b30f 100644 --- a/bin/tests/system/dnssec/ns5/named.conf.j2 +++ b/bin/tests/system/dnssec/ns5/named.conf.j2 @@ -61,11 +61,6 @@ controls { file "../../_common/root.hint"; }; - zone "corp" { - type static-stub; - server-addresses { 10.53.0.2; }; - }; - include "broken.conf"; {% else %} zone "." { diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index a5f879b5896..d61dbcc7369 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -2156,7 +2156,7 @@ check_secroots_layout named.secroots.test$n || ret=1 linecount=$(grep -c "./$DEFAULT_ALGORITHM/$keyid ; static" named.secroots.test$n || true) [ "$linecount" -eq 1 ] || ret=1 linecount=$(wc 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 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive and negative validation with negative trust anchors ($n)" -ret=0 - -# -# check correct initial behavior -# -dig_with_opts a.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null || ret=1 -dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1 -dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1 - -if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi -status=$((status + ret)) -ret=0 - -# -# add negative trust anchors -# -rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i -# reconfig should maintain NTAs -rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 -lines=$(wc -l &1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i -# reload should maintain NTAs -rndc_reload ns4 10.53.0.4 -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2 -lines=$(wc -l dig.out.ns4.test$n.4 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1 -dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 >/dev/null && ret=1 -dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.6 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.6 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 >/dev/null && ret=1 -dig_with_opts a.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.7 || ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 >/dev/null && ret=1 -echo_i "dumping secroots" -rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i -cp ns4/named.secroots named.secroots.test$n -check_secroots_layout named.secroots.test$n || ret=1 -grep "bogus.example: expiry" named.secroots.test$n >/dev/null || ret=1 -grep "badds.example: expiry" named.secroots.test$n >/dev/null || ret=1 -grep "secure.example: expiry" named.secroots.test$n >/dev/null || ret=1 -grep "fakenode.secure.example: expiry" named.secroots.test$n >/dev/null || ret=1 - -if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi -status=$((status + ret)) -ret=0 - -echo_i "waiting for NTA rechecks/expirations" - -# -# secure.example and badds.example used default nta-duration -# (configured as 12s in ns4/named1.conf), but nta recheck interval -# is configured to 9s, so at t=10 the NTAs for secure.example and -# fakenode.secure.example should both be lifted, but badds.example -# should still be going. -# -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -dig_with_opts b.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.8 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.8 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 >/dev/null || ret=1 -dig_with_opts b.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.9 || ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 >/dev/null || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n.9 >/dev/null || ret=1 -dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.10 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.10 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 >/dev/null && ret=1 - -if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi -status=$((status + ret)) -ret=0 - -# -# bogus.example was set to expire in 20s, so at t=13 -# it should still be NTA'd, but badds.example used the default -# lifetime of 12s, so it should revert to SERVFAIL now. -# -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -# check nta table -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n._11 -lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true) -[ "$lines" -le 2 ] || ret=1 -grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null || ret=1 -grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null && ret=1 -dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.11 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.11 >/dev/null && ret=1 -dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.12 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.12 >/dev/null || ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 >/dev/null && ret=1 -dig_with_opts c.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.13 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.13 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 >/dev/null || ret=1 - -if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi -status=$((status + ret)) -ret=0 - -# -# at t=21, all the NTAs should have expired. -# -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' -# check correct behavior after bogus.example expiry -dig_with_opts d.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.14 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.14 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 >/dev/null || ret=1 -dig_with_opts c.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.15 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.15 >/dev/null || ret=1 -# check nta table has been cleaned up now -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 -lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true) -[ "$lines" -eq 0 ] || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi -status=$((status + ret)) -ret=0 - -echo_i "testing NTA removals ($n)" -rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 -grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 >/dev/null || ret=1 -dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null && ret=1 -grep "^a.badds.example." dig.out.ns4.test$n.1 >/dev/null || ret=1 -rndccmd 10.53.0.4 nta -remove badds.example >rndc.out.ns4.test$n.2 -grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 >/dev/null || ret=1 -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 -grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 >/dev/null && ret=1 -dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -ret=0 - -echo_i "remove non-existent NTA three times" -rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.4 2>&1 -rndccmd 10.53.0.4 nta -remove foo >rndc.out.ns4.test$n.5 2>&1 -rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.6 2>&1 -grep "not found" rndc.out.ns4.test$n.6 >/dev/null || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -ret=0 - -n=$((n + 1)) -echo_i "testing NTA with bogus lifetimes ($n)" -echo_i "check with no nta lifetime specified" -rndccmd 10.53.0.4 nta -l "" foo >rndc.out.ns4.test$n.1 2>&1 || true -grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 >/dev/null || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -ret=0 - -echo_i "check with bad nta lifetime" -rndccmd 10.53.0.4 nta -l garbage foo >rndc.out.ns4.test$n.2 2>&1 || true -grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 >/dev/null || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -ret=0 - -echo_i "check with too long nta lifetime" -rndccmd 10.53.0.4 nta -l 7d1h foo >rndc.out.ns4.test$n.3 2>&1 || true -grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 >/dev/null || ret=1 -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -ret=0 - -# -# check NTA persistence across restarts -# -n=$((n + 1)) -echo_i "testing NTA persistence across restarts ($n)" -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 -lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true) -[ "$lines" -eq 0 ] || ret=1 -rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2 -lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true) -[ "$lines" -eq 2 ] || ret=1 -# shellcheck disable=SC2016 -start=$($PERL -e 'print time()."\n";') - -if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi -status=$((status + ret)) -ret=0 - -echo_i "killing ns4 with SIGTERM" -kill -TERM "$(cat ns4/named.pid)" -rm -f ns4/named.pid - -# -# ns4 has now shutdown. wait until t=14 when badds.example's NTA -# (lifetime=10s) would have expired, and then restart ns4. -# -echo_i "waiting till 14s have passed since NTAs were added before restarting ns4" -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' - -if - start_server --noclean --restart --port "$PORT" ns4 -then - echo_i "restarted server ns4" -else - echo_i "could not restart server ns4" - exit 1 -fi - -echo_i "sleeping for an additional 4 seconds for ns4 to fully startup" -sleep 4 - -# -# ns4 should be back up now. The NTA for bogus.example should still be -# valid, whereas badds.example should not have been added during named -# startup (as it had already expired), the fact that it's ignored should -# be logged. -# -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3 -lines=$(wc -l /dev/null || ret=1 -dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.4 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1 -dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null || ret=1 -grep "ignoring expired NTA at badds.example" ns4/named.run >/dev/null || ret=1 - -# cleanup -rndccmd 10.53.0.4 nta -remove bogus.example >rndc.out.ns4.test$n.6 - -if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi -status=$((status + ret)) -ret=0 - -# -# check "regular" attribute in NTA file works as expected at named -# startup. -# -n=$((n + 1)) -echo_i "testing loading regular attribute from NTA file ($n)" -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null -lines=$(wc -l dig.out.ns4.test$n.2 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1 - -echo_i "killing ns4 with SIGTERM" -kill -TERM "$(cat ns4/named.pid)" -rm -f ns4/named.pid - -echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" -sleep 4 - -# -# ns4 has now shutdown. add NTA for secure.example. directly into the -# _default.nta file with the regular attribute and some future timestamp. -# -future="$(($(date +%Y) + 20))0101010000" -echo "secure.example. regular $future" >ns4/_default.nta -# shellcheck disable=SC2016 -start=$($PERL -e 'print time()."\n";') - -if - start_server --noclean --restart --port "$PORT" ns4 -then - echo_i "restarted server ns4" -else - echo_i "could not restart server ns4" - exit 1 -fi - -# nta-recheck is configured as 9s, so at t=12 the NTAs for -# secure.example. should be lifted as it is not a forced NTA. -echo_i "waiting till 12s have passed after ns4 was restarted" -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' - -# secure.example. should now return an AD=1 answer (still validates) as -# the NTA has been lifted. -dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1 - -# cleanup -rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null - -if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi -status=$((status + ret)) -ret=0 - -# -# check "forced" attribute in NTA file works as expected at named -# startup. -# -n=$((n + 1)) -echo_i "testing loading forced attribute from NTA file ($n)" -rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null -lines=$(wc -l dig.out.ns4.test$n.2 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1 - -echo_i "killing ns4 with SIGTERM" -kill -TERM "$(cat ns4/named.pid)" -rm -f named.pid - -echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" -sleep 4 - -# -# ns4 has now shutdown. add NTA for secure.example. directly into the -# _default.nta file with the forced attribute and some future timestamp. -# -echo "secure.example. forced $future" >ns4/_default.nta -start=$($PERL -e 'print time()."\n";') - -if - start_server --noclean --restart --port "$PORT" ns4 -then - echo_i "restarted server ns4" -else - echo_i "could not restart server ns4" - exit 1 -fi - -# nta-recheck is configured as 9s, but even at t=12 the NTAs for -# secure.example. should not be lifted as it is a forced NTA. -echo_i "waiting till 12s have passed after ns4 was restarted" -# shellcheck disable=SC2016 -$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);' - -# secure.example. should now return an AD=0 answer (non-authenticated) -# as the NTA is still there. -dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null && ret=1 - -# cleanup -rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null - -if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi -status=$((status + ret)) -ret=0 - -# -# check that NTA lifetime read from file is clamped to 1 week. -# -n=$((n + 1)) -echo_i "testing loading out of bounds lifetime from NTA file ($n)" - -echo_i "killing ns4 with SIGTERM" -kill -TERM "$(cat ns4/named.pid)" -rm -f ns4/named.pid - -echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown" -sleep 4 - -# -# ns4 has now shutdown. add NTA for secure.example. directly into the -# _default.nta file with a lifetime well into the future. -# -echo "secure.example. forced $future" >ns4/_default.nta -added=$($PERL -e 'print time()."\n";') - -if - start_server --noclean --restart --port "$PORT" ns4 -then - echo_i "restarted server ns4" -else - echo_i "could not restart server ns4" - exit 1 -fi - -echo_i "sleeping for an additional 4 seconds for ns4 to fully startup" -sleep 4 - -# dump the NTA to a file (omit validate-except entries) -echo_i "testing 'rndc nta -d' with NTA" -rndccmd 10.53.0.4 nta -d | grep -v ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null -# "corp" is configured as a validate-except domain and thus should be -# removed by the grep -v above. only "secure.example" should appear in -# the dump. -lines=$(wc -l /dev/null || ret=1 -ts=$(awk '{print $3" "$4}' rndc.out.ns4.test$n.2 -echo "ts_with_zone=$ts_with_zone" >>rndc.out.ns4.test$n.2 -echo "added=$added" >>rndc.out.ns4.test$n.2 -if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null; then - # ntadiff.pl computes $ts_with_zone - ($added + 1week) - d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added") - echo "d=$d" >>rndc.out.ns4.test$n.2 - # diff from $added(now) + 1week to the clamped NTA lifetime should be - # less than a few seconds (handle daylight saving changes by adding 3600). - [ "$d" -lt 3610 ] || ret=1 -else - echo_i "skipped ntadiff test; install PERL module Time::Piece" -fi - -echo_i "testing 'rndc nta' lifetime clamping" -rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null -# "corp" is configured as a validate-except domain and thus should be -# the only entry in the dump. -lines=$(wc -l /dev/null || ret=1 - -# cleanup -rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.3 2>/dev/null - -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "testing 'rndc nta -d' displays validate-except entries" -rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null -lines=$(wc -l /dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)" -ret=0 -# Sanity check behavior without an NTA in place. -dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.1 || ret=1 -grep "SERVFAIL" dig.out.ns9.test$n.1 >/dev/null || ret=1 -grep "ANSWER: 0" dig.out.ns9.test$n.1 >/dev/null || ret=1 -grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 >/dev/null && ret=1 -# Add an NTA, expecting that to cause resolution to succeed. -rndccmd 10.53.0.9 nta badds.example >rndc.out.ns9.test$n.1 2>&1 || ret=1 -dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.2 || ret=1 -grep "NOERROR" dig.out.ns9.test$n.2 >/dev/null || ret=1 -grep "ANSWER: 2" dig.out.ns9.test$n.2 >/dev/null || ret=1 -grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 >/dev/null && ret=1 -# Remove the NTA, expecting that to cause resolution to fail again. -rndccmd 10.53.0.9 nta -remove badds.example >rndc.out.ns9.test$n.2 2>&1 || ret=1 -dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.3 || ret=1 -grep "SERVFAIL" dig.out.ns9.test$n.3 >/dev/null || ret=1 -grep "ANSWER: 0" dig.out.ns9.test$n.3 >/dev/null || ret=1 -grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 >/dev/null && ret=1 -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "completed NTA tests" - # Run a minimal update test if possible. This is really just # a regression test for RT #2399; more tests should be added. diff --git a/bin/tests/system/nta/ns1/named.conf.j2 b/bin/tests/system/nta/ns1/named.conf.j2 new file mode 100644 index 00000000000..bd1ccc40810 --- /dev/null +++ b/bin/tests/system/nta/ns1/named.conf.j2 @@ -0,0 +1,36 @@ +/* + * 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. + */ + +// 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; + notify yes; + dnssec-validation yes; + /* test that we can turn off trust-anchor-telemetry */ + trust-anchor-telemetry no; +}; + +zone "." { + type primary; + file "root.db.signed"; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/nta/ns1/root.db.in b/bin/tests/system/nta/ns1/root.db.in new file mode 100644 index 00000000000..34f777330de --- /dev/null +++ b/bin/tests/system/nta/ns1/root.db.in @@ -0,0 +1,24 @@ +; 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. + +$TTL 300 +. IN SOA gson.nominum.com. a.root.servers.nil. ( + 2000042100 ; serial + 600 ; refresh + 600 ; retry + 1200 ; expire + 600 ; minimum + ) +. NS a.root-servers.nil. +a.root-servers.nil. A 10.53.0.1 + +example. NS ns2.example. +ns2.example. A 10.53.0.2 diff --git a/bin/tests/system/nta/ns1/sign.sh b/bin/tests/system/nta/ns1/sign.sh new file mode 100644 index 00000000000..243503d85da --- /dev/null +++ b/bin/tests/system/nta/ns1/sign.sh @@ -0,0 +1,37 @@ +#!/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 + +(cd ../ns2 && $SHELL sign.sh) + +cp "../ns2/dsset-example." . + +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" + +"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1 + +# Configure the resolving server with a static key. +keyfile_to_static_ds "$ksk" >trusted.conf +cp trusted.conf ../ns4/trusted.conf +cp trusted.conf ../ns9/trusted.conf diff --git a/bin/tests/system/dnssec/ns2/corp.db b/bin/tests/system/nta/ns2/corp.db similarity index 100% rename from bin/tests/system/dnssec/ns2/corp.db rename to bin/tests/system/nta/ns2/corp.db diff --git a/bin/tests/system/nta/ns2/example.db.in b/bin/tests/system/nta/ns2/example.db.in new file mode 100644 index 00000000000..f72258f63c0 --- /dev/null +++ b/bin/tests/system/nta/ns2/example.db.in @@ -0,0 +1,35 @@ +; 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. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns2 + NS ns3 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +; A secure subdomain +secure NS ns3.secure +ns3.secure A 10.53.0.3 + +; A secure subdomain we're going to inject bogus data into +bogus NS ns.bogus +ns.bogus A 10.53.0.3 + +; A subdomain with a corrupt DS +badds NS ns.badds +ns.badds A 10.53.0.3 diff --git a/bin/tests/system/nta/ns2/named.conf.j2 b/bin/tests/system/nta/ns2/named.conf.j2 new file mode 100644 index 00000000000..9bfbcde9d2a --- /dev/null +++ b/bin/tests/system/nta/ns2/named.conf.j2 @@ -0,0 +1,50 @@ +/* + * 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. + */ + +// NS2 + +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; }; + allow-transfer { any; }; + recursion no; + notify yes; + notify-delay 1; + dnssec-validation no; + minimal-responses no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "example" { + type primary; + file "example.db.signed"; + allow-update { any; }; +}; + +zone "corp" { + type primary; + file "corp.db"; +}; diff --git a/bin/tests/system/nta/ns2/sign.sh b/bin/tests/system/nta/ns2/sign.sh new file mode 100644 index 00000000000..5eb698e8420 --- /dev/null +++ b/bin/tests/system/nta/ns2/sign.sh @@ -0,0 +1,38 @@ +#!/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 + +# Sign child zones (served by ns3). +(cd ../ns3 && $SHELL sign.sh) + +# The "example." zone. +zone=example. +infile=example.db.in +zonefile=example.db + +# Get the DS records for the "example." zone. +for subdomain in bogus badds secure; do + cp "../ns3/dsset-$subdomain.example." . +done + +# Sign the "example." zone. +keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -f KSK "$zone") +keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" "$zone") + +cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile" + +"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1 diff --git a/bin/tests/system/nta/ns3/bogus.example.db.in b/bin/tests/system/nta/ns3/bogus.example.db.in new file mode 100644 index 00000000000..0feb441cdd8 --- /dev/null +++ b/bin/tests/system/nta/ns3/bogus.example.db.in @@ -0,0 +1,27 @@ +; 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. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 +d A 10.0.0.4 +z A 10.0.0.26 diff --git a/bin/tests/system/nta/ns3/named.conf.j2 b/bin/tests/system/nta/ns3/named.conf.j2 new file mode 100644 index 00000000000..3c3f256ca46 --- /dev/null +++ b/bin/tests/system/nta/ns3/named.conf.j2 @@ -0,0 +1,62 @@ +/* + * 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. + */ + +// NS3 + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + notify yes; + dnssec-validation no; + minimal-responses no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "example" { + type secondary; + primaries { 10.53.0.2; }; + file "example.bk"; +}; + +zone "secure.example" { + type primary; + file "secure.example.db.signed"; + allow-update { any; }; +}; + +zone "bogus.example" { + type primary; + file "bogus.example.db.signed"; + allow-update { any; }; +}; + +zone "badds.example" { + type primary; + file "badds.example.db.signed"; + allow-update { any; }; +}; diff --git a/bin/tests/system/nta/ns3/secure.example.db.in b/bin/tests/system/nta/ns3/secure.example.db.in new file mode 100644 index 00000000000..182329bf421 --- /dev/null +++ b/bin/tests/system/nta/ns3/secure.example.db.in @@ -0,0 +1,30 @@ +; 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. + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; 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 +c A 10.0.0.3 +d A 10.0.0.4 +e A 10.0.0.5 +f A 10.0.0.6 +g A 10.0.0.7 +z A 10.0.0.26 diff --git a/bin/tests/system/nta/ns3/sign.sh b/bin/tests/system/nta/ns3/sign.sh new file mode 100644 index 00000000000..5e5405abed5 --- /dev/null +++ b/bin/tests/system/nta/ns3/sign.sh @@ -0,0 +1,62 @@ +#!/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 + +# a validly signed zone +zone=secure.example. +infile=secure.example.db.in +zonefile=secure.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null +cat "$zonefile" "$zonefile".signed >"$zonefile".tmp +mv "$zonefile".tmp "$zonefile".signed + +# a zone that we'll add bogus data to +zone=bogus.example. +infile=bogus.example.db.in +zonefile=bogus.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null + +{ + echo "a.bogus.example. A 10.0.0.22" + echo "b.bogus.example. A 10.0.0.23" + echo "c.bogus.example. A 10.0.0.23" +} >>bogus.example.db.signed + +# +# A zone with a bad DS in the parent +# (sourced from bogus.example.db.in) +# +zone=badds.example. +infile=bogus.example.db.in +zonefile=badds.example.db + +keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") + +cat "$infile" "$keyname.key" >"$zonefile" + +"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null +sed -e 's/bogus/badds/g' dsset-badds.example. diff --git a/bin/tests/system/nta/ns4/named.conf.j2 b/bin/tests/system/nta/ns4/named.conf.j2 new file mode 100644 index 00000000000..87f70e2f216 --- /dev/null +++ b/bin/tests/system/nta/ns4/named.conf.j2 @@ -0,0 +1,53 @@ +/* + * 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. + */ + +// NS4 + +options { + query-source address 10.53.0.4; + notify-source 10.53.0.4; + transfer-source 10.53.0.4; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.4; }; + listen-on-v6 { none; }; + recursion yes; + minimal-responses no; + + nta-lifetime 12s; + nta-recheck 9s; + validate-except { corp; }; + + dnssec-validation yes; +}; + +include "trusted.conf"; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint"; +}; + +zone "corp" { + type static-stub; + server-addresses { 10.53.0.2; }; +}; diff --git a/bin/tests/system/nta/ns9/named.conf.j2 b/bin/tests/system/nta/ns9/named.conf.j2 new file mode 100644 index 00000000000..cdbe7ec8eac --- /dev/null +++ b/bin/tests/system/nta/ns9/named.conf.j2 @@ -0,0 +1,40 @@ +/* + * 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. + */ + +// NS9 + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + recursion yes; + dnssec-validation yes; + forward only; + forwarders { 10.53.0.4; }; + servfail-ttl 0; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ntadiff.pl b/bin/tests/system/nta/setup.sh old mode 100755 new mode 100644 similarity index 58% rename from bin/tests/system/dnssec/ntadiff.pl rename to bin/tests/system/nta/setup.sh index ca80eac9b89..4a4db2dd0d1 --- a/bin/tests/system/dnssec/ntadiff.pl +++ b/bin/tests/system/nta/setup.sh @@ -1,4 +1,4 @@ -#!/usr/bin/perl -w +#!/bin/sh -e # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # @@ -11,14 +11,12 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -use strict; -use Time::Piece; -use Time::Seconds; +# shellcheck source=conf.sh +. ../conf.sh -exit 1 if (scalar(@ARGV) != 2); +set -e -my $actual = Time::Piece->strptime($ARGV[0], '%d-%b-%Y %H:%M:%S.000 %z'); -my $expected = Time::Piece->strptime($ARGV[1], '%s') + ONE_WEEK; -my $diff = abs($actual - $expected); - -print($diff . "\n"); +( + cd ns1 + $SHELL sign.sh +) diff --git a/bin/tests/system/nta/tests_nta.py b/bin/tests/system/nta/tests_nta.py new file mode 100644 index 00000000000..088a3c5a1d5 --- /dev/null +++ b/bin/tests/system/nta/tests_nta.py @@ -0,0 +1,430 @@ +# 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. + +import os +import re +import time + +import pytest + +import isctest + + +# helper functions +def hasmatch(regex, blob): + return re.search(regex, blob, flags=re.MULTILINE) + + +def active(blob): + return len([x for x in blob.splitlines() if " expiry" in x]) + + +# global start-time variable +# pylint: disable=global-statement +# pylint: disable=global-variable-not-assigned +start = 0 + + +def test_initial(): + m = isctest.query.create("a.bogus.example.", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + + m = isctest.query.create("badds.example.", "SOA") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + + m = isctest.query.create("a.secure.example.", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + +def test_nta_validate_except(servers): + ns4 = servers["ns4"] + response = ns4.rndc("secroots -", log=False) + assert hasmatch("^corp: permanent", response) + + # check insecure local domain works with validate-except + m = isctest.query.create("www.corp", "NS") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + +def test_nta_bogus_lifetimes(servers): + ns4 = servers["ns4"] + + # no nta lifetime specified: + response = ns4.rndc("nta -l '' foo", ignore_errors=True, log=False) + assert "'nta' failed: bad ttl" in response + + # bad nta lifetime: + response = ns4.rndc("nta -l garbage foo", ignore_errors=True, log=False) + assert "'nta' failed: bad ttl" in response + + # excessive nta lifetime: + response = ns4.rndc("nta -l 7d1h foo", ignore_errors=True, log=False) + assert "'nta' failed: out of range" in response + + +def test_nta_install(servers): + global start + + ns4 = servers["ns4"] + ns4.rndc("nta -f -l 20s bogus.example", log=False) + ns4.rndc("nta badds.example", log=False) + + # NTAs should persist after reconfig + with ns4.watch_log_from_here() as watcher: + ns4.reconfigure(log=False) + watcher.wait_for_line("any newly configured zones are now loaded") + + response = ns4.rndc("nta -d", log=False) + assert len(response.splitlines()) == 3 + + ns4.rndc("nta secure.example", log=False) + ns4.rndc("nta fakenode.secure.example", log=False) + with ns4.watch_log_from_here() as watcher: + ns4.rndc("reload", log=False) + watcher.wait_for_line("all zones loaded") + + response = ns4.rndc("nta -d", log=False) + assert len(response.splitlines()) == 5 + + start = time.time() + + +def test_nta_behavior(servers): + global start + assert start, "test_nta_behavior must be run as part of the full NTA test" + + m = isctest.query.create("a.bogus.example.", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + m = isctest.query.create("badds.example.", "SOA") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + m = isctest.query.create("a.secure.example.", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + m = isctest.query.create("a.fakenode.secure.example.", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noadflag(res) + + ns4 = servers["ns4"] + response = ns4.rndc("secroots -", log=False) + assert hasmatch("^bogus.example: expiry", response) + assert hasmatch("^badds.example: expiry", response) + assert hasmatch("^secure.example: expiry", response) + assert hasmatch("^fakenode.secure.example: expiry", response) + + # secure.example and badds.example used the default nta-duration + # (configured as 12s in ns4/named1.conf), but the nta recheck interval + # is configured to 9s, so at t=10 the NTAs for secure.example and + # fakenode.secure.example should both be lifted, while badds.example + # should still be going. + delay = start + 10 - time.time() + if delay > 0: + time.sleep(delay) + + m = isctest.query.create("b.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + m = isctest.query.create("b.fakenode.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.nxdomain(res) + isctest.check.adflag(res) + + m = isctest.query.create("badds.example.", "SOA") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + # bogus.example was set to expire in 20s, so at t=13 + # it should still be NTA'd, but badds.example used the default + # lifetime of 12s, so it should revert to SERVFAIL now. + delay = start + 13 - time.time() + if delay > 0: + time.sleep(delay) + + response = ns4.rndc("nta -d", log=False) + assert active(response) <= 2 + + response = ns4.rndc("secroots -", log=False) + assert hasmatch("bogus.example: expiry", response) + assert not hasmatch("badds.example: expiry", response) + + m = isctest.query.create("b.bogus.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + + m = isctest.query.create("a.badds.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + isctest.check.noadflag(res) + + m = isctest.query.create("c.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # at t=21, all the NTAs should have expired. + delay = start + 21 - time.time() + if delay > 0: + time.sleep(delay) + + response = ns4.rndc("nta -d", log=False) + assert active(response) == 0 + + m = isctest.query.create("d.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + m = isctest.query.create("c.bogus.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + isctest.check.noadflag(res) + + +def test_nta_removals(servers): + ns4 = servers["ns4"] + ns4.rndc("nta badds.example", log=False) + + response = ns4.rndc("nta -d", log=False) + assert hasmatch("^badds.example/_default: expiry", response) + + m = isctest.query.create("a.badds.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + response = ns4.rndc("nta -remove badds.example", log=False) + assert "Negative trust anchor removed: badds.example" in response + + response = ns4.rndc("nta -d", log=False) + assert not hasmatch("^badds.example/_default: expiry", response) + + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + isctest.check.noadflag(res) + + # remove non-existent NTA three times + ns4.rndc("nta -r foo", log=False) + ns4.rndc("nta -remove foo", log=False) + response = ns4.rndc("nta -r foo", log=False) + assert "not found" in response + + +def test_nta_restarts(servers): + global start + assert start, "test_nta_restarts must be run as part of the full NTA test" + + # test NTA persistence across restarts + ns4 = servers["ns4"] + response = ns4.rndc("nta -d", log=False) + assert active(response) == 0 + + start = time.time() + ns4.rndc("nta -f -l 30s bogus.example", log=False) + ns4.rndc("nta -f -l 10s badds.example", log=False) + response = ns4.rndc("nta -d", log=False) + assert active(response) == 2 + + # stop the server + ns4.stop() + + # wait 14s before restarting. badds.example's NTA (lifetime=10s) should + # have expired, and bogus.example should still be running. + delay = start + 14 - time.time() + if delay > 0: + time.sleep(delay) + ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + + response = ns4.rndc("nta -d", log=False) + assert active(response) == 1 + assert hasmatch("^bogus.example/_default: expiry", response) + + m = isctest.query.create("a.badds.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.servfail(res) + + m = isctest.query.create("a.bogus.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + ns4.rndc("nta -r bogus.example", log=False) + + +def test_nta_regular(servers): + global start + assert start, "test_nta_regular must be run as part of the full NTA test" + + # check "regular" attribute in NTA file + ns4 = servers["ns4"] + + response = ns4.rndc("nta -d", log=False) + assert active(response) == 0 + + # secure.example validates with AD=1 + m = isctest.query.create("a.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # stop the server, update _default.nta, restart + ns4.stop() + now = time.localtime() + future = str(now.tm_year + 20) + "0101010000" + with open("ns4/_default.nta", "w", encoding="utf-8") as f: + f.write(f"secure.example. regular {future}") + + ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + + # NTA active; secure.example. should now return an AD=0 answer. + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + # nta-recheck is configured as 9s, so at t=12 the NTA for + # secure.example. should be lifted as it is not a "forced" NTA. + start = time.mktime(now) + delay = start + 12 - time.time() + if delay > 0: + time.sleep(delay) + + response = ns4.rndc("nta -d", log=False) + assert active(response) == 0 + + # NTA lifted; secure.example. flush the cache to trigger a new query, + # and it should now return an AD=1 answer. + ns4.rndc("flushtree secure.example", log=False) + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + +def test_nta_forced(servers): + global start + assert start, "test_nta_regular must be run as part of the full NTA test" + + # check "forced" attribute in NTA file + ns4 = servers["ns4"] + + # just to be certain, clean up any existing NTA first + ns4.rndc("nta -r secure.example", log=False) + + response = ns4.rndc("nta -d", log=False) + assert active(response) == 0 + + # secure.example validates with AD=1 + m = isctest.query.create("a.secure.example", "A") + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # stop the server, update _default.nta, restart + ns4.stop() + now = time.localtime() + future = str(now.tm_year + 20) + "0101010000" + with open("ns4/_default.nta", "w", encoding="utf-8") as f: + f.write(f"secure.example. forced {future}") + + ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + + # NTA active; secure.example. should now return an AD=0 answer + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + # nta-recheck is configured as 9s. at t=12 the NTA for + # secure.example. should NOT be lifted as it is "forced". + start = time.mktime(now) + delay = start + 12 - time.time() + if delay > 0: + time.sleep(delay) + + # NTA lifted; secure.example. should still return an AD=0 answer + ns4.rndc("flushtree secure.example", log=False) + res = isctest.query.tcp(m, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + + +def test_nta_clamping(servers): + ns4 = servers["ns4"] + + # clean up any existing NTA + ns4.rndc("nta -r secure.example", log=False) + + # stop the server, update _default.nta, restart + ns4.stop() + now = time.localtime() + future = str(now.tm_year + 20) + "0101010000" + with open("ns4/_default.nta", "w", encoding="utf-8") as f: + f.write(f"secure.example. forced {future}") + + ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]]) + + # check that NTA lifetime read from file is clamped to 1 week. + response = ns4.rndc("nta -d", log=False) + assert active(response) == 1 + + nta = next((s for s in response.splitlines() if " expiry" in s), None) + assert nta is not None + + nta = nta.split(" ") + expiry = f"{nta[2]} {nta[3]}" + then = time.mktime(time.strptime(expiry, "%d-%b-%Y %H:%M:%S.000")) + nextweek = time.mktime(now) + (86400 * 7) + + # normally there's no more than a few seconds difference between the + # clamped expiration date and the calculated date for next week, + # but add a 3600 second fudge factor to allow for daylight savings + # changes. + assert abs(nextweek - then < 3610) + + # remove the NTA + ns4.rndc("nta -r secure.example", log=False) + + +def test_nta_forward(servers): + ns9 = servers["ns9"] + + m = isctest.query.create("badds.example", "SOA") + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.servfail(res) + isctest.check.empty_answer(res) + isctest.check.noadflag(res) + + # add NTA and expect resolution to succeed + ns9.rndc("nta badds.example", log=False) + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 2) + isctest.check.noadflag(res) + + # remove NTA and expect resolution to fail again + ns9.rndc("nta -remove badds.example", log=False) + res = isctest.query.tcp(m, "10.53.0.9") + isctest.check.servfail(res) + isctest.check.empty_answer(res) + isctest.check.noadflag(res)