2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 21:47:59 +00:00

Add checkds system test

Add a Pytest based system test for the 'checkds' feature. There is
one nameserver (ns9, because it should be started the latest) that
has configured several zones with dnssec-policy. The zones are set
in such a state that they are waiting for DS publication or DS
withdrawal.

Then several other name servers act as parent servers that either have
the DS for these published, or not. Also one server in the mix is
to test a badly configured parental-agent.

There are tests for DS publication, DS publication error handling,
DS withdrawal and DS withdrawal error handling.

The tests ensures that the zone is DNSSEC valid, and that the
DSPublish/DSRemoved key metadata is set (or not in case of the error
handling).

It does not test if the rollover continues, this is already tested in
the kasp system test (that uses 'rndc -dnssec checkds' to set the
DSPublish/DSRemoved key metadata).
This commit is contained in:
Matthijs Mekking 2021-05-11 14:40:04 +02:00
parent 1e763e582b
commit 56262db9cd
20 changed files with 1186 additions and 1 deletions

View File

@ -210,7 +210,7 @@ if HAVE_PYTHON
TESTS += kasp keymgr2kasp tcp pipelined
if HAVE_PYMOD_DNS
TESTS += qmin cookie timeouts
TESTS += checkds qmin cookie timeouts
if HAVE_PERLMOD_NET_DNS
TESTS += dnssec

View File

@ -0,0 +1,19 @@
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
See COPYRIGHT in the source root or https://isc.org/copyright.html for terms.
The test setup for the checkds tests.
These servers are parent servers:
- ns2 is a primary authoritative server that serves the parent zone for zones
configured in ns9.
- ns4 is the secondary server for ns2.
- ns5 is a primary authoritative server that serves the parent zone for zones
configured in ns9, but this one does not publish DS records (to test cases
where the DS is missing).
- ns6 is an authoritative server for a different zone, to test badly configured
parental agents.
- ns7 is the secondary server for ns5.
Finally, ns9 is the authoritative server for the various DNSSEC enabled test
domains.

View File

@ -0,0 +1,25 @@
#!/bin/sh
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
set -e
rm -f dig.out*
rm -f ns*/named.conf ns*/named.memstats ns*/named.run*
rm -f ns*/*.jnl ns*/*.jbk
rm -f ns*/K*.private ns*/K*.key ns*/K*.state
rm -f ns*/dsset-*
rm -f ns*/*.db ns*/*.jnl ns*/*.jbk ns*/*.db.signed ns*/*.db.infile
rm -f ns*/keygen.out.* ns*/settime.out.* ns*/signer.out.*
rm -f ns*/managed-keys.bind*
rm -f ns*/*.mkeys
rm -f ns*/zones
rm -f tests-checkds.py.status
rm -f *.checkds.out

View File

@ -0,0 +1,71 @@
############################################################################
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
############################################################################
import os
import pytest
def pytest_configure(config):
config.addinivalue_line(
"markers", "dnspython: mark tests that need dnspython to function"
)
config.addinivalue_line(
"markers", "dnspython2: mark tests that need dnspython >= 2.0.0"
)
def pytest_collection_modifyitems(config, items):
# pylint: disable=unused-argument,unused-import,too-many-branches
# pylint: disable=import-outside-toplevel
# Test for dnspython module
skip_dnspython = pytest.mark.skip(
reason="need dnspython module to run")
try:
import dns.query # noqa: F401
except ModuleNotFoundError:
for item in items:
if "dnspython" in item.keywords:
item.add_marker(skip_dnspython)
# Test for dnspython >= 2.0.0 module
skip_dnspython2 = pytest.mark.skip(
reason="need dnspython >= 2.0.0 module to run")
try:
from dns.query import udp_with_fallback # noqa: F401
except ImportError:
for item in items:
if "dnspython2" in item.keywords:
item.add_marker(skip_dnspython2)
@pytest.fixture
def named_port(request):
# pylint: disable=unused-argument
port = os.getenv("PORT")
if port is None:
port = 5301
else:
port = int(port)
return port
@pytest.fixture
def control_port(request):
# pylint: disable=unused-argument
port = os.getenv("CONTROLPORT")
if port is None:
port = 5301
else:
port = int(port)
return port

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
// 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;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "../../common/root.hint";
};
zone "checkds" {
type primary;
file "checkds.db";
};

View File

@ -0,0 +1,42 @@
#!/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 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
echo_i "ns2/setup.sh"
for subdomain in dspublished reference missing-dspublished bad-dspublished \
multiple-dspublished incomplete-dspublished bad2-dspublished \
dswithdrawn missing-dswithdrawn bad-dswithdrawn \
multiple-dswithdrawn incomplete-dswithdrawn bad2-dswithdrawn
do
cp "../ns9/dsset-$subdomain.checkds$TP" .
done
private_type_record() {
_zone=$1
_algorithm=$2
_keyfile=$3
_id=$(keyfile_to_key_id "$_keyfile")
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
}
zone="checkds"
infile="checkds.db.infile"
zonefile="checkds.db"
CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone)
cat template.db.in "${CSK}.key" > "$infile"
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1

View File

@ -0,0 +1,36 @@
; 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.
$TTL 300
@ IN SOA secondary.example. hostmaster.example. (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
dspublished NS ns9.dspublished
reference NS ns9.reference
missing-dspublished NS ns9.missing-dspublished
bad-dspublished NS ns9.bad-dspublished
multiple-dspublished NS ns9.multiple-dspublished
incomplete-dspublished NS ns9.incomplete-dspublished
bad2-dspublished NS ns9.bad2-dspublished
dswithdrawn NS ns9.dswithdrawn
missing-dswithdrawn NS ns9.missing-dswithdrawn
bad-dswithdrawn NS ns9.bad-dswithdrawn
multiple-dswithdrawn NS ns9.multiple-dswithdrawn
incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn
bad2-dswithdrawn NS ns9.bad2-dswithdrawn

View File

@ -0,0 +1,39 @@
/*
* 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.
*/
// 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; };
allow-transfer { any; };
recursion no;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "checkds" {
type secondary;
file "checkds.db";
primaries { 10.53.0.2 port @PORT@; };
};

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
// NS5
options {
query-source address 10.53.0.5;
notify-source 10.53.0.5;
transfer-source 10.53.0.5;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "../../common/root.hint";
};
zone "checkds" {
type primary;
file "checkds.db";
};

View File

@ -0,0 +1,34 @@
#!/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 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
echo_i "ns5/setup.sh"
private_type_record() {
_zone=$1
_algorithm=$2
_keyfile=$3
_id=$(keyfile_to_key_id "$_keyfile")
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
}
zone="checkds"
infile="checkds.db.infile"
zonefile="checkds.db"
CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone)
cat template.db.in "${CSK}.key" > "$infile"
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1

View File

@ -0,0 +1,36 @@
; 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.
$TTL 300
@ IN SOA secondary.example. hostmaster.example. (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns5
ns5 A 10.53.0.5
dspublished NS ns9.dspublished
reference NS ns9.reference
missing-dspublished NS ns9.missing-dspublished
bad-dspublished NS ns9.bad-dspublished
multiple-dspublished NS ns9.multiple-dspublished
incomplete-dspublished NS ns9.incomplete-dspublished
bad2-dspublished NS ns9.bad2-dspublished
dswithdrawn NS ns9.dswithdrawn
missing-dswithdrawn NS ns9.missing-dswithdrawn
bad-dswithdrawn NS ns9.bad-dswithdrawn
multiple-dswithdrawn NS ns9.multiple-dswithdrawn
incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn
bad2-dswithdrawn NS ns9.bad2-dswithdrawn

View File

@ -0,0 +1,43 @@
/*
* 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.
*/
// NS2
options {
query-source address 10.53.0.6;
notify-source 10.53.0.6;
transfer-source 10.53.0.6;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.6; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "../../common/root.hint";
};
zone "foo" {
type primary;
file "foo.db";
};

View File

@ -0,0 +1,44 @@
/*
* 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.
*/
// NS7
options {
query-source address 10.53.0.7;
notify-source 10.53.0.7;
transfer-source 10.53.0.7;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.7; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "." {
type hint;
file "../../common/root.hint";
};
zone "checkds" {
type secondary;
file "checkds.db";
primaries { 10.53.0.5 port @PORT@; };
};

View File

@ -0,0 +1,193 @@
// 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; };
allow-transfer { any; };
recursion no;
};
key rndc_key {
secret "1234abcd8765";
algorithm hmac-sha256;
};
controls {
inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
parental-agents "ns2" port @PORT@ {
10.53.0.2;
};
zone "." {
type hint;
file "../../common/root.hint";
};
/*
* Zone with parental agent configured, due for DS checking.
*/
zone "dspublished.checkds" {
type primary;
file "dspublished.checkds.db";
dnssec-policy "default";
parental-agents { 10.53.0.2 port @PORT@; };
};
/*
* Zone with parental agent configured, due for DS checking.
* Same as above, but now with a reference to parental-agents.
*/
zone "reference.checkds" {
type primary;
file "reference.checkds.db";
dnssec-policy "default";
parental-agents { "ns2"; };
};
/*
* Zone with parental agent configured, due for DS checking.
* The parental agent does not have the DS yet.
*/
zone "missing-dspublished.checkds" {
type primary;
file "missing-dspublished.checkds.db";
dnssec-policy "default";
parental-agents {
10.53.0.5 port @PORT@; // missing
};
};
/*
* Zone with parental agent configured, due for DS checking.
* This case, the server is badly configured.
*/
zone "bad-dspublished.checkds" {
type primary;
file "bad-dspublished.checkds.db";
dnssec-policy "default";
parental-agents {
10.53.0.6 port @PORT@; // bad
};
};
/*
* Zone with multiple parental agents configured, due for DS checking.
* All need to have the DS before the rollover may continue.
*/
zone "multiple-dspublished.checkds" {
type primary;
file "multiple-dspublished.checkds.db";
dnssec-policy "default";
parental-agents {
10.53.0.2 port @PORT@;
10.53.0.4 port @PORT@;
};
};
/*
* Zone with multiple parental agents configured, due for DS checking.
* All need to have the DS before the rollover may continue.
* This case, one server is still missing the DS.
*/
zone "incomplete-dspublished.checkds" {
type primary;
file "incomplete-dspublished.checkds.db";
dnssec-policy "default";
parental-agents {
10.53.0.2 port @PORT@;
10.53.0.4 port @PORT@;
10.53.0.5 port @PORT@; // missing
};
};
/*
* Zone with multiple parental agents configured, due for DS checking.
* All need to have the DS before the rollover may continue.
* This case, one server is badly configured.
*/
zone "bad2-dspublished.checkds" {
type primary;
file "bad2-dspublished.checkds.db";
dnssec-policy "default";
parental-agents {
10.53.0.2 port @PORT@;
10.53.0.4 port @PORT@;
10.53.0.6 port @PORT@; // bad
};
};
// TODO: Other test cases:
// - Test with bogus response
// - check with TSIG
// - check with TLS
/*
* Zones that are going insecure (test DS withdrawn polling).
*/
zone "dswithdrawn.checkds" {
type primary;
file "dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents { 10.53.0.5 port @PORT@; };
};
zone "missing-dswithdrawn.checkds" {
type primary;
file "missing-dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents {
10.53.0.2 port @PORT@; // still published
};
};
zone "bad-dswithdrawn.checkds" {
type primary;
file "bad-dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents {
10.53.0.6 port @PORT@; // bad
};
};
zone "multiple-dswithdrawn.checkds" {
type primary;
file "multiple-dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents {
10.53.0.5 port @PORT@;
10.53.0.7 port @PORT@;
};
};
zone "incomplete-dswithdrawn.checkds" {
type primary;
file "incomplete-dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents {
10.53.0.2 port @PORT@; // still published
10.53.0.5 port @PORT@;
10.53.0.7 port @PORT@;
};
};
zone "bad2-dswithdrawn.checkds" {
type primary;
file "bad2-dswithdrawn.checkds.db";
dnssec-policy "insecure";
parental-agents {
10.53.0.5 port @PORT@;
10.53.0.7 port @PORT@;
10.53.0.6 port @PORT@; // bad
};
};

View File

@ -0,0 +1,69 @@
#!/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 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
echo_i "ns9/setup.sh"
setup() {
zone="$1"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
infile="${zone}.db.infile"
echo "$zone" >> zones
}
private_type_record() {
_zone=$1
_algorithm=$2
_keyfile=$3
_id=$(keyfile_to_key_id "$_keyfile")
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
}
# Short environment variable names for key states and times.
H="HIDDEN"
R="RUMOURED"
O="OMNIPRESENT"
U="UNRETENTIVE"
T="now-30d"
Y="now-1y"
# DS Publication.
for zn in dspublished reference missing-dspublished bad-dspublished \
multiple-dspublished incomplete-dspublished bad2-dspublished
do
setup "${zn}.checkds"
cp template.db.in "$zonefile"
keytimes="-P $T -P sync $T -A $T"
CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone)
$SETTIME -s -g $O -k $O $T -r $O $T -z $O $T -d $R $T "$CSK" > settime.out.$zone 2>&1
cat template.db.in "${CSK}.key" > "$infile"
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
done
# DS Withdrawal.
for zn in dswithdrawn missing-dswithdrawn bad-dswithdrawn multiple-dswithdrawn \
incomplete-dswithdrawn bad2-dswithdrawn
do
setup "${zn}.checkds"
cp template.db.in "$zonefile"
keytimes="-P $Y -P sync $Y -A $Y"
CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone)
$SETTIME -s -g $H -k $O $T -r $O $T -z $O $T -d $U $T "$CSK" > settime.out.$zone 2>&1
cat template.db.in "${CSK}.key" > "$infile"
private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile"
$SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone.1 2>&1
done

View File

@ -0,0 +1,25 @@
; 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.
$TTL 300
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns9
ns9 A 10.53.0.9
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View File

@ -0,0 +1,38 @@
#!/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 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
$SHELL clean.sh
copy_setports ns2/named.conf.in ns2/named.conf
copy_setports ns4/named.conf.in ns4/named.conf
copy_setports ns5/named.conf.in ns5/named.conf
copy_setports ns6/named.conf.in ns6/named.conf
copy_setports ns7/named.conf.in ns7/named.conf
copy_setports ns9/named.conf.in ns9/named.conf
# Setup zones
(
cd ns9
$SHELL setup.sh
)
(
cd ns5
$SHELL setup.sh
)
(
cd ns2
$SHELL setup.sh
)

View File

@ -0,0 +1,376 @@
#!/usr/bin/python3
############################################################################
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
############################################################################
import mmap
import os
import subprocess
import sys
import time
import dns.resolver
import pytest
def has_signed_apex_nsec(zone, response):
has_nsec = False
has_rrsig = False
ttl = 300
nextname = "a."
types = "NS SOA RRSIG NSEC DNSKEY CDS CDNSKEY"
match = "{0} {1} IN NSEC {2}{0} {3}".format(zone, ttl, nextname, types)
sig = "{0} {1} IN RRSIG NSEC 13 2 300".format(zone, ttl)
for rr in response.answer:
if match in rr.to_text():
has_nsec = True
if sig in rr.to_text():
has_rrsig = True
if not has_nsec:
print("error: missing apex NSEC record in response")
if not has_rrsig:
print("error: missing NSEC signature in response")
return has_nsec and has_rrsig
def do_query(server, qname, qtype, tcp=False):
query = dns.message.make_query(qname, qtype, use_edns=True,
want_dnssec=True)
try:
if tcp:
response = dns.query.tcp(query, server.nameservers[0], timeout=3,
port=server.port)
else:
response = dns.query.udp(query, server.nameservers[0], timeout=3,
port=server.port)
except dns.exception.Timeout:
print("error: query timeout for query {} {} to {}".format(
qname, qtype, server.nameservers[0]))
return None
return response
def verify_zone(zone, transfer):
verify = os.getenv("VERIFY")
assert verify is not None
filename = "{}out".format(zone)
with open(filename, 'w') as file:
for rr in transfer.answer:
file.write(rr.to_text())
file.write('\n')
# dnssec-verify command with default arguments.
verify_cmd = [verify, "-z", "-o", zone, filename]
verifier = subprocess.run(verify_cmd, capture_output=True, check=True)
if verifier.returncode != 0:
print("error: dnssec-verify {} failed".format(zone))
sys.stderr.buffer.write(verifier.stderr)
return verifier.returncode == 0
def read_statefile(server, zone):
addr = server.nameservers[0]
count = 0
keyid = 0
state = {}
response = do_query(server, zone, "DS", tcp=True)
if not isinstance(response, dns.message.Message):
print("error: no response for {} DS from {}".format(zone, addr))
return {}
if response.rcode() == dns.rcode.NOERROR:
# fetch key id from response.
for rr in response.answer:
if rr.match(dns.name.from_text(zone), dns.rdataclass.IN,
dns.rdatatype.DS, dns.rdatatype.NONE):
if count == 0:
keyid = list(dict(rr.items).items())[0][0].key_tag
count += 1
if count != 1:
print("error: expected a single DS in response for {} from {},"
"got {}".format(zone, addr, count))
return {}
else:
print("error: {} response for {} DNSKEY from {}".format(
dns.rcode.to_text(response.rcode()), zone, addr))
return {}
filename = "ns9/K{}+013+{:05d}.state".format(zone, keyid)
print("read state file {}".format(filename))
try:
with open(filename, 'r') as file:
for line in file:
if line.startswith(';'):
continue
key, val = line.strip().split(':', 1)
state[key.strip()] = val.strip()
except FileNotFoundError:
# file may not be written just yet.
return {}
return state
def zone_check(server, zone):
addr = server.nameservers[0]
# wait until zone is fully signed.
signed = False
for _ in range(10):
response = do_query(server, zone, 'NSEC')
if not isinstance(response, dns.message.Message):
print("error: no response for {} NSEC from {}".format(zone, addr))
elif response.rcode() == dns.rcode.NOERROR:
signed = has_signed_apex_nsec(zone, response)
else:
print("error: {} response for {} NSEC from {}".format(
dns.rcode.to_text(response.rcode()), zone, addr))
if signed:
break
time.sleep(1)
assert signed
# check if zone if DNSSEC valid.
verified = False
transfer = do_query(server, zone, 'AXFR', tcp=True)
if not isinstance(transfer, dns.message.Message):
print("error: no response for {} AXFR from {}".format(zone, addr))
elif transfer.rcode() == dns.rcode.NOERROR:
verified = verify_zone(zone, transfer)
else:
print("error: {} response for {} AXFR from {}".format(
dns.rcode.to_text(transfer.rcode()), zone, addr))
assert verified
def keystate_check(server, zone, key):
val = 0
deny = False
search = key
if key.startswith('!'):
deny = True
search = key[1:]
for _ in range(10):
state = read_statefile(server, zone)
try:
val = state[search]
except KeyError:
pass
if not deny and val != 0:
break
if deny and val == 0:
break
time.sleep(1)
if deny:
assert val == 0
else:
assert val != 0
def wait_for_log(filename, log):
found = False
for _ in range(10):
print("read log file {}".format(filename))
try:
with open(filename, 'r') as file:
s = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
if s.find(bytes(log, "ascii")) != -1:
found = True
except FileNotFoundError:
print("file not found {}".format(filename))
if found:
break
print("sleep")
time.sleep(1)
assert found
@pytest.mark.dnspython
@pytest.mark.dnspython2
def test_checkds_dspublished(named_port):
# We create resolver instances that will be used to send queries.
server = dns.resolver.Resolver()
server.nameservers = ["10.53.0.9"]
server.port = named_port
parent = dns.resolver.Resolver()
parent.nameservers = ["10.53.0.2"]
parent.port = named_port
# DS correctly published in parent.
zone_check(server, "dspublished.checkds.")
wait_for_log("ns9/named.run",
"zone dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
keystate_check(parent, "dspublished.checkds.", "DSPublish")
# DS correctly published in parent (reference to parental-agent).
zone_check(server, "reference.checkds.")
wait_for_log("ns9/named.run",
"zone reference.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
keystate_check(parent, "reference.checkds.", "DSPublish")
# DS not published in parent.
zone_check(server, "missing-dspublished.checkds.")
wait_for_log("ns9/named.run",
"zone missing-dspublished.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
keystate_check(parent, "missing-dspublished.checkds.", "!DSPublish")
# Badly configured parent.
zone_check(server, "bad-dspublished.checkds.")
wait_for_log("ns9/named.run",
"zone bad-dspublished.checkds/IN (signed): checkds: "
"bad DS response from 10.53.0.6")
keystate_check(parent, "bad-dspublished.checkds.", "!DSPublish")
# TBD: DS published in parent, but bogus signature.
# DS correctly published in all parents.
zone_check(server, "multiple-dspublished.checkds.")
wait_for_log("ns9/named.run",
"zone multiple-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
wait_for_log("ns9/named.run",
"zone multiple-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.4")
keystate_check(parent, "multiple-dspublished.checkds.", "DSPublish")
# DS published in only one of multiple parents.
zone_check(server, "incomplete-dspublished.checkds.")
wait_for_log("ns9/named.run",
"zone incomplete-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
wait_for_log("ns9/named.run",
"zone incomplete-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.4")
wait_for_log("ns9/named.run",
"zone incomplete-dspublished.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
keystate_check(parent, "incomplete-dspublished.checkds.", "!DSPublish")
# One of the parents is badly configured.
wait_for_log("ns9/named.run",
"zone bad2-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
wait_for_log("ns9/named.run",
"zone bad2-dspublished.checkds/IN (signed): checkds: "
"DS response from 10.53.0.4")
wait_for_log("ns9/named.run",
"zone bad2-dspublished.checkds/IN (signed): checkds: "
"bad DS response from 10.53.0.6")
keystate_check(parent, "bad2-dspublished.checkds.", "!DSPublish")
# TBD: DS published in all parents, but one has bogus signature.
# TBD: Check with TSIG
# TBD: Check with TLS
@pytest.mark.dnspython
@pytest.mark.dnspython2
def test_checkds_dswithdrawn(named_port):
# We create resolver instances that will be used to send queries.
server = dns.resolver.Resolver()
server.nameservers = ["10.53.0.9"]
server.port = named_port
parent = dns.resolver.Resolver()
parent.nameservers = ["10.53.0.2"]
parent.port = named_port
# DS correctly published in single parent.
zone_check(server, "dswithdrawn.checkds.")
wait_for_log("ns9/named.run",
"zone dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
keystate_check(parent, "dswithdrawn.checkds.", "DSRemoved")
# DS not withdrawn from parent.
zone_check(server, "missing-dswithdrawn.checkds.")
wait_for_log("ns9/named.run",
"zone missing-dswithdrawn.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
keystate_check(parent, "missing-dswithdrawn.checkds.", "!DSRemoved")
# Badly configured parent.
zone_check(server, "bad-dswithdrawn.checkds.")
wait_for_log("ns9/named.run",
"zone bad-dswithdrawn.checkds/IN (signed): checkds: "
"bad DS response from 10.53.0.6")
keystate_check(parent, "bad-dswithdrawn.checkds.", "!DSRemoved")
# TBD: DS published in parent, but bogus signature.
# DS correctly withdrawn from all parents.
zone_check(server, "multiple-dswithdrawn.checkds.")
wait_for_log("ns9/named.run",
"zone multiple-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
wait_for_log("ns9/named.run",
"zone multiple-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.7")
keystate_check(parent, "multiple-dswithdrawn.checkds.", "DSRemoved")
# DS withdrawn from only one of multiple parents.
zone_check(server, "incomplete-dswithdrawn.checkds.")
wait_for_log("ns9/named.run",
"zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
"DS response from 10.53.0.2")
wait_for_log("ns9/named.run",
"zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
wait_for_log("ns9/named.run",
"zone incomplete-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.7")
keystate_check(parent, "incomplete-dswithdrawn.checkds.", "!DSRemoved")
# One of the parents is badly configured.
wait_for_log("ns9/named.run",
"zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.5")
wait_for_log("ns9/named.run",
"zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
"empty DS response from 10.53.0.7")
wait_for_log("ns9/named.run",
"zone bad2-dswithdrawn.checkds/IN (signed): checkds: "
"bad DS response from 10.53.0.6")
keystate_check(parent, "bad2-dswithdrawn.checkds.", "!DSRemoved")
# TBD: DS withdrawn from all parents, but one has bogus signature.

View File

@ -82,6 +82,7 @@ SEQUENTIALDIRS="$SEQUENTIAL_COMMON $SEQUENTIAL_UNIX"
PARALLEL_UNIX="@DNSTAP@
chain
checkds
cookie
dlzexternal
dnssec

View File

@ -188,6 +188,14 @@
./bin/tests/system/checkconf/dnssec.2 X 2011,2016,2018,2019,2020,2021
./bin/tests/system/checkconf/good.zonelist X 2016,2017,2018,2019,2020,2021
./bin/tests/system/checkconf/tests.sh SH 2005,2007,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021
./bin/tests/system/checkds/README TXT.BRIEF 2021
./bin/tests/system/checkds/clean.sh SH 2021
./bin/tests/system/checkds/conftest.py PYTHON 2021
./bin/tests/system/checkds/ns2/setup.sh SH 2021
./bin/tests/system/checkds/ns5/setup.sh SH 2021
./bin/tests/system/checkds/ns9/setup.sh SH 2021
./bin/tests/system/checkds/setup.sh SH 2021
./bin/tests/system/checkds/tests-checkds.py PYTHON-BIN 2021
./bin/tests/system/checknames/clean.sh SH 2004,2007,2012,2014,2015,2016,2018,2019,2020,2021
./bin/tests/system/checknames/setup.sh SH 2004,2007,2012,2014,2016,2018,2019,2020,2021
./bin/tests/system/checknames/tests.sh SH 2004,2007,2012,2013,2014,2015,2016,2018,2019,2020,2021