]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add tests for DNSSEC sign statistics
authorMatthijs Mekking <matthijs@isc.org>
Thu, 20 Jun 2019 11:10:33 +0000 (13:10 +0200)
committerMatthijs Mekking <github@pletterpet.nl>
Tue, 25 Jun 2019 09:40:01 +0000 (11:40 +0200)
This adds tests to the statschannel system test for testing if
the dnskey sign operation counters are incremented correctly.

It tests three cases:

1. A zone maintenance event where all the signatures that are about
   to expire are resigned.
2. A dynamic update event where the new RR and other relevant records
   (SOA, NSEC) are resigned.
3. Adding a standby key, that means the DNSKEY and SOA RRset are
   resigned.

bin/tests/system/statschannel/clean.sh
bin/tests/system/statschannel/ns2/dnssec.db.in [new file with mode: 0644]
bin/tests/system/statschannel/ns2/named.conf.in
bin/tests/system/statschannel/ns2/sign.sh [new file with mode: 0644]
bin/tests/system/statschannel/setup.sh
bin/tests/system/statschannel/tests.sh
bin/tests/system/statschannel/zones-json.pl [new file with mode: 0644]
bin/tests/system/statschannel/zones-xml.pl [new file with mode: 0644]
util/copyrights

index 224e14f76f9e85761c021ba5efeae90fd179007d..f38d6ac0b194d31f672b9806790369bbe33fb965 100644 (file)
@@ -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 (file)
index 0000000..47cb88e
--- /dev/null
@@ -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
index 9030802f328046f1d418391a29b59d5dc7a34c91..fc2952fa2a8e5b73c13a7b8070fdf64db534dae7 100644 (file)
@@ -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 (file)
index 0000000..6c27598
--- /dev/null
@@ -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
+
index e7ad741204d7747a1469c7052e45d0ab92a59d34..bd9a25cb00fdb9e49d399610b646806766e6f0ea 100644 (file)
@@ -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
+)
index 2883b2419a93caacc9f5eca70bdd0d4ce0c17b27..2980337c5540f3d45fd428690540e8eff0bf0174 100644 (file)
@@ -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 (file)
index 0000000..f07e97e
--- /dev/null
@@ -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$/;<INPUT>};
+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 (file)
index 0000000..3ccd5e4
--- /dev/null
@@ -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";
+            }
+        }
+    }
+}
index aa21d47ee8068c6003f35b3df51c845c4abfa3a4..0161d7c0e03979cbcd78a7465778deddc16e0e72 100644 (file)
 ./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
 ./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