diff --git a/bin/tests/system/statschannel/clean.sh b/bin/tests/system/statschannel/clean.sh index 224e14f76f..f38d6ac0b1 100644 --- a/bin/tests/system/statschannel/clean.sh +++ b/bin/tests/system/statschannel/clean.sh @@ -9,14 +9,18 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -rm -f traffic traffic.out.* +rm -f traffic traffic.out.* traffic.json.* traffic.xml.* +rm -f zones zones.out.* zones.json.* zones.xml.* zones.expect.* rm -f dig.out* rm -f */named.memstats rm -f */named.conf -rm -f */named.run +rm -f */named.run* rm -f ns*/named.lock rm -f ns*/named.stats rm -f xml.*stats json.*stats rm -f xml.*mem json.*mem rm -f compressed.headers regular.headers compressed.out regular.out rm -f ns*/managed-keys.bind* +rm -f ns2/Kdnssec* ns2/dnssec.*.id +rm -f ns2/dnssec.db.signed* ns2/dsset-dnssec. +rm -f ns2/core diff --git a/bin/tests/system/statschannel/ns2/dnssec.db.in b/bin/tests/system/statschannel/ns2/dnssec.db.in new file mode 100644 index 0000000000..47cb88e3dc --- /dev/null +++ b/bin/tests/system/statschannel/ns2/dnssec.db.in @@ -0,0 +1,26 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$ORIGIN . +$TTL 300 + +dnssec. IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) +dnssec. NS ns2.dnssec. +ns2.dnssec. A 10.53.0.2 + +$ORIGIN dnssec. +a A 10.0.0.1 + MX 10 mail.dnssec. +mail A 10.0.0.2 diff --git a/bin/tests/system/statschannel/ns2/named.conf.in b/bin/tests/system/statschannel/ns2/named.conf.in index 9030802f32..fc2952fa2a 100644 --- a/bin/tests/system/statschannel/ns2/named.conf.in +++ b/bin/tests/system/statschannel/ns2/named.conf.in @@ -39,3 +39,13 @@ zone "example" { file "example.db"; allow-transfer { any; }; }; + +zone "dnssec" { + type master; + file "dnssec.db.signed"; + auto-dnssec maintain; + allow-update { any; }; + zone-statistics full; + dnssec-dnskey-kskonly yes; + update-check-ksk yes; +}; diff --git a/bin/tests/system/statschannel/ns2/sign.sh b/bin/tests/system/statschannel/ns2/sign.sh new file mode 100644 index 0000000000..6c275989aa --- /dev/null +++ b/bin/tests/system/statschannel/ns2/sign.sh @@ -0,0 +1,28 @@ +#!/bin/sh -e +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. "$SYSTEMTESTTOP/conf.sh" + +set -e + +zone=dnssec. +infile=dnssec.db.in +zonefile=dnssec.db.signed + +ksk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone") +zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +# Sign deliberately with a very short expiration date. +"$SIGNER" -S -x -O full -e "now"+1s -o "$zone" -f "$zonefile" "$infile" > /dev/null 2>&1 + +echo "$ksk" | sed -e 's/.*[+]//' -e 's/^0*//' > dnssec.ksk.id +echo "$zsk" | sed -e 's/.*[+]//' -e 's/^0*//' > dnssec.zsk.id + diff --git a/bin/tests/system/statschannel/setup.sh b/bin/tests/system/statschannel/setup.sh index e7ad741204..bd9a25cb00 100644 --- a/bin/tests/system/statschannel/setup.sh +++ b/bin/tests/system/statschannel/setup.sh @@ -9,9 +9,14 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -SYSTEMTESTTOP=.. -. $SYSTEMTESTTOP/conf.sh +# shellcheck source=conf.sh +. "$SYSTEMTESTTOP/conf.sh" $SHELL clean.sh copy_setports ns2/named.conf.in ns2/named.conf + +( + cd ns2 + $SHELL sign.sh +) diff --git a/bin/tests/system/statschannel/tests.sh b/bin/tests/system/statschannel/tests.sh index 2883b2419a..2980337c55 100644 --- a/bin/tests/system/statschannel/tests.sh +++ b/bin/tests/system/statschannel/tests.sh @@ -9,8 +9,8 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. -SYSTEMTESTTOP=.. -. $SYSTEMTESTTOP/conf.sh +# shellcheck source=conf.sh +. "$SYSTEMTESTTOP/conf.sh" DIGCMD="$DIG @10.53.0.2 -p ${PORT}" RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" @@ -54,12 +54,48 @@ gettraffic() { *) return 1 ;; esac file=`$PERL fetch.pl -p ${EXTRAPORT1} $path` + cp $file $file.$1.$2 $PERL traffic-${1}.pl $file 2>/dev/null | sort > traffic.out.$2 result=$? - rm -f $file return $result } +getzones() { + sleep 1 + echo_i "... using $1" + case $1 in + xml) path='xml/v3/zones' ;; + json) path='json/v1/zones' ;; + *) return 1 ;; + esac + file=`$PERL fetch.pl -p ${EXTRAPORT1} $path` + cp $file $file.$1.$2 + $PERL zones-${1}.pl $file 2>/dev/null | sort > zones.out.$2 + result=$? + return $result +} + +# TODO: Move wait_for_log and loadkeys_on to conf.sh.common +wait_for_log() { + msg=$1 + file=$2 + + for i in 1 2 3 4 5 6 7 8 9 10; do + nextpart "$file" | grep "$msg" > /dev/null && return + sleep 1 + done + echo_i "exceeded time limit waiting for '$msg' in $file" + ret=1 +} + +loadkeys_on() { + nsidx=$1 + zone=$2 + nextpart ns${nsidx}/named.run > /dev/null + $RNDCCMD 10.53.0.${nsidx} loadkeys ${zone} | sed "s/^/ns${nsidx} /" | cat_i + wait_for_log "next key event" ns${nsidx}/named.run +} + status=0 n=1 ret=0 @@ -243,5 +279,93 @@ if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` n=`expr $n + 1` +# Test dnssec sign statistics. +zone="dnssec" +stat_prefix="dnskey sign operations" +ksk_id=`cat ns2/$zone.ksk.id` +zsk_id=`cat ns2/$zone.zsk.id` + +# 1. Test sign operations for scheduled resigning. +ret=0 +# The dnssec zone has 10 RRsets to sign (including NSEC) with the ZSK and one +# RRset (DNSKEY) with the KSK. So starting named with signatures that expire +# almost right away, this should trigger 10 zsk and 1 ksk sign operations. +# However, the DNSSEC maintenance assumes when we see the SOA record we have +# walked the whole zone, since the SOA record should always have the most +# recent signature. This however is not always the case, for example when +# the signature expiration is the same, `dns_db_getsigningtime could return +# the SOA RRset before a competing RRset. This happens here and so the +# SOA RRset is updated and resigned twice at startup, that explains the +# additional zsk sign operation (11 instead of 10). +echo "${stat_prefix} ${zsk_id}: 11" > zones.expect +echo "${stat_prefix} ${ksk_id}: 1" >> zones.expect +cat zones.expect | sort > zones.expect.$n +rm -f zones.expect +# Fetch and check the dnssec sign statistics. +echo_i "fetching zone stats data after zone maintenance at startup ($n)" +if [ $PERL_XML ]; then + getzones xml x$n || ret=1 + cmp zones.out.x$n zones.expect.$n || ret=1 +fi +if [ $PERL_JSON ]; then + getzones json j$n || ret=1 + cmp zones.out.j$n zones.expect.$n || ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` +n=`expr $n + 1` + +# 2. Test sign operations after dynamic update. +ret=0 +( +# Update dnssec zone to trigger signature creation. +echo zone $zone +echo server 10.53.0.2 "$PORT" +echo update add $zone. 300 in txt "nsupdate added me" +echo send +) | $NSUPDATE +# This should trigger the resign of SOA, TXT and NSEC (+3 zsk). +echo "${stat_prefix} ${zsk_id}: 14" > zones.expect +echo "${stat_prefix} ${ksk_id}: 1" >> zones.expect +cat zones.expect | sort > zones.expect.$n +rm -f zones.expect +# Fetch and check the dnssec sign statistics. +echo_i "fetching zone stats data after dynamic update ($n)" +if [ $PERL_XML ]; then + getzones xml x$n || ret=1 + cmp zones.out.x$n zones.expect.$n || ret=1 +fi +if [ $PERL_JSON ]; then + getzones json j$n || ret=1 + cmp zones.out.j$n zones.expect.$n || ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` +n=`expr $n + 1` + +# 3. Test sign operations of KSK. +ret=0 +# Add a standby DNSKEY, this triggers resigning the DNSKEY RRset. +zsk=$("$KEYGEN" -K ns2 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +$SETTIME -K ns2 -P now -A never $zsk.key > /dev/null +loadkeys_on 2 $zone || ret=1 +# This should trigger the resign of SOA (+1 zsk) and DNSKEY (+1 ksk). +echo "${stat_prefix} ${zsk_id}: 15" > zones.expect +echo "${stat_prefix} ${ksk_id}: 2" >> zones.expect +cat zones.expect | sort > zones.expect.$n +rm -f zones.expect +# Fetch and check the dnssec sign statistics. +if [ $PERL_XML ]; then + getzones xml x$n || ret=1 + cmp zones.out.x$n zones.expect.$n || ret=1 +fi +if [ $PERL_JSON ]; then + getzones json j$n || ret=1 + cmp zones.out.j$n zones.expect.$n || ret=1 +fi +if [ $ret != 0 ]; then echo_i "failed"; fi +status=`expr $status + $ret` +n=`expr $n + 1` + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/statschannel/zones-json.pl b/bin/tests/system/statschannel/zones-json.pl new file mode 100644 index 0000000000..f07e97e400 --- /dev/null +++ b/bin/tests/system/statschannel/zones-json.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# zones-json.pl: +# Parses the JSON version of the dnssec sign stats for the +# "dnssec" zone in the default view into a normalized format. + +use JSON; + +my $file = $ARGV[0]; +open(INPUT, "<$file"); +my $text = do{local$/;}; +close(INPUT); + +my $ref = decode_json($text); + + +my $dnssecsign = $ref->{views}->{_default}->{zones}[0]->{"dnssec"}; +my $type = "dnskey sign operations "; +foreach $key (keys %{$dnssecsign}) { + print $type . $key . ": ". $dnssecsign->{$key} ."\n"; +} diff --git a/bin/tests/system/statschannel/zones-xml.pl b/bin/tests/system/statschannel/zones-xml.pl new file mode 100644 index 0000000000..3ccd5e4b96 --- /dev/null +++ b/bin/tests/system/statschannel/zones-xml.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +# +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# 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 http://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# zones-xml.pl: +# Parses the XML version of the dnssec sign stats for the +# "dnssec" zone in the default view into a normalized format. + +use XML::Simple; + +my $file = $ARGV[0]; + +my $ref = XMLin($file); + +my $counters = $ref->{views}->{view}->{_default}->{zones}->{zone}->{dnssec}->{counters}; + +foreach $group (@$counters) { + + my $type = $group->{type}; + + if ($type eq "dnssec") { + my $prefix = "dnskey sign operations "; + if (exists $group->{counter}->{name}) { + print $prefix . $group->{counter}->{name} . ": " . $group->{counter}->{content} . "\n"; + } else { + foreach $key (keys %{$group->{counter}}) { + print $prefix . $key . ": ". $group->{counter}->{$key}->{content} ."\n"; + } + } + } +} diff --git a/util/copyrights b/util/copyrights index aa21d47ee8..0161d7c0e0 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1064,6 +1064,7 @@ ./bin/tests/system/statschannel/clean.sh SH 2015,2016,2017,2018,2019 ./bin/tests/system/statschannel/fetch.pl PERL 2015,2016,2018,2019 ./bin/tests/system/statschannel/mem-xml.pl PERL 2017,2018,2019 +./bin/tests/system/statschannel/ns2/sign.sh SH 2019 ./bin/tests/system/statschannel/prereq.sh SH 2015,2016,2018,2019 ./bin/tests/system/statschannel/server-json.pl PERL 2015,2016,2017,2018,2019 ./bin/tests/system/statschannel/server-xml.pl PERL 2015,2016,2017,2018,2019 @@ -1076,6 +1077,8 @@ ./bin/tests/system/statschannel/traffic.expect.4 X 2015,2018,2019 ./bin/tests/system/statschannel/traffic.expect.5 X 2015,2016,2018,2019 ./bin/tests/system/statschannel/traffic.expect.6 X 2015,2016,2018,2019 +./bin/tests/system/statschannel/zones-json.pl PERL 2019 +./bin/tests/system/statschannel/zones-xml.pl PERL 2019 ./bin/tests/system/stop.pl SH 2001,2004,2005,2006,2007,2012,2016,2017,2018,2019 ./bin/tests/system/stop.sh SH 2000,2001,2004,2007,2012,2016,2018,2019 ./bin/tests/system/stopall.sh SH 2018,2019