mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-27 20:25:55 -04:00
[9.20] chg: test: Rewrite multisigner system test to pytest
Backport of MR !11082 Merge branch 'backport-matthijs-pytestify-multisigner-system-test-9.20' into 'bind-9.20' See merge request isc-projects/bind9!11307
This commit is contained in:
commit
d42bfbba7e
7 changed files with 651 additions and 2115 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -28,8 +28,6 @@ KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.
|
|||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
|
||||
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
|
||||
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
|
||||
# ZSK will be added to the other provider with nsupdate.
|
||||
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"
|
||||
|
||||
zone="model2.secondary"
|
||||
echo_i "setting up zone: $zone"
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.
|
|||
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
|
||||
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
|
||||
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
|
||||
# ZSK will be added to the other provider with nsupdate.
|
||||
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"
|
||||
|
||||
zone="model2.secondary"
|
||||
echo_i "setting up zone: $zone"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ options {
|
|||
recursion no;
|
||||
key-directory ".";
|
||||
dnssec-validation no;
|
||||
notify-delay 0;
|
||||
};
|
||||
|
||||
key rndc_key {
|
||||
|
|
|
|||
|
|
@ -1,771 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../conf.sh
|
||||
# shellcheck source=kasp.sh
|
||||
. ../kasp.sh
|
||||
|
||||
dig_with_opts() {
|
||||
$DIG +tcp +noadd +nosea +nostat +nocmd +dnssec -p $PORT "$@"
|
||||
}
|
||||
|
||||
start_time="$(TZ=UTC date +%s)"
|
||||
status=0
|
||||
n=0
|
||||
|
||||
set_zone "model2.multisigner"
|
||||
set_policy "model2" "2" "3600"
|
||||
|
||||
# Key properties and states.
|
||||
key_clear "KEY1"
|
||||
set_keyrole "KEY1" "ksk"
|
||||
set_keylifetime "KEY1" "0"
|
||||
set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256"
|
||||
set_keysigning "KEY1" "yes"
|
||||
set_zonesigning "KEY1" "no"
|
||||
set_keystate "KEY1" "GOAL" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DNSKEY" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_KRRSIG" "omnipresent"
|
||||
set_keystate "KEY1" "STATE_DS" "omnipresent"
|
||||
|
||||
key_clear "KEY2"
|
||||
set_keyrole "KEY2" "zsk"
|
||||
set_keylifetime "KEY2" "0"
|
||||
set_keyalgorithm "KEY2" "13" "ECDSAP256SHA256" "256"
|
||||
set_keysigning "KEY2" "no"
|
||||
set_zonesigning "KEY2" "yes"
|
||||
set_keystate "KEY2" "GOAL" "omnipresent"
|
||||
set_keystate "KEY2" "STATE_DNSKEY" "omnipresent"
|
||||
set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent"
|
||||
|
||||
key_clear "KEY3"
|
||||
key_clear "KEY4"
|
||||
|
||||
set_keytimes_model2() {
|
||||
# The first KSK is immediately published and activated.
|
||||
created=$(key_get KEY1 CREATED)
|
||||
set_keytime "KEY1" "PUBLISHED" "${created}"
|
||||
set_keytime "KEY1" "ACTIVE" "${created}"
|
||||
set_keytime "KEY1" "SYNCPUBLISH" "${created}"
|
||||
|
||||
# The first ZSKs are immediately published and activated.
|
||||
created=$(key_get KEY2 CREATED)
|
||||
set_keytime "KEY2" "PUBLISHED" "${created}"
|
||||
set_keytime "KEY2" "ACTIVE" "${created}"
|
||||
}
|
||||
|
||||
set_server "ns3" "10.53.0.3"
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_model2
|
||||
check_keytimes
|
||||
check_apex
|
||||
dnssec_verify
|
||||
|
||||
set_server "ns4" "10.53.0.4"
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_model2
|
||||
check_keytimes
|
||||
check_apex
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# Update DNSKEY RRset.
|
||||
#
|
||||
|
||||
# Check that the ZSKs from the other provider are published.
|
||||
zsks_are_published() {
|
||||
dig_with_opts "$ZONE" "@${SERVER}" DNSKEY >"dig.out.$DIR.test$n" || return 1
|
||||
cat dig.out.$DIR.test$n | tr [:blank:] ' ' >dig.out.$DIR.test$n.tr || return 1
|
||||
# We should have two ZSKs.
|
||||
lines=$(grep "256 3 13" dig.out.$DIR.test$n.tr | wc -l)
|
||||
test "$lines" -eq 2 || return 1
|
||||
# Both ZSKs are published.
|
||||
grep "$(cat ns3/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr >/dev/null || return 1
|
||||
grep "$(cat ns4/${ZONE}.zsk | tr [:blank:] ' ')" dig.out.$DIR.test$n.tr >/dev/null || return 1
|
||||
# And one KSK.
|
||||
lines=$(grep "257 3 13" dig.out.$DIR.test$n.tr | wc -l)
|
||||
test "$lines" -eq 1 || return 1
|
||||
}
|
||||
|
||||
# Test to make sure no DNSSEC records end up in the raw journal.
|
||||
no_dnssec_in_journal() {
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "check zone ${ZONE} raw journal has no DNSSEC ($n)"
|
||||
$JOURNALPRINT "${DIR}/${ZONE}.db.jnl" >"${DIR}/${ZONE}.journal.out.test$n"
|
||||
rrset_exists NSEC "${DIR}/${ZONE}.journal.out.test$n" && ret=1
|
||||
rrset_exists NSEC3 "${DIR}/${ZONE}.journal.out.test$n" && ret=1
|
||||
rrset_exists NSEC3PARAM "${DIR}/${ZONE}.journal.out.test$n" && ret=1
|
||||
rrset_exists RRSIG "${DIR}/${ZONE}.journal.out.test$n" && ret= 1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
}
|
||||
|
||||
# Check if a certain RRtype is present in the journal file.
|
||||
rrset_exists() (
|
||||
rrtype=$1
|
||||
file=$2
|
||||
lines=$(awk -v rt="${rrtype}" '$5 == rt {print}' ${file} | wc -l)
|
||||
test "$lines" -gt 0
|
||||
)
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add dnskey record: update zone ${ZONE} at ns3 with ZSK from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "ns4/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Check the new DNSKEY RRset.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Check the logs for find zone keys errors.
|
||||
n=$((n + 1))
|
||||
echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Verify again.
|
||||
dnssec_verify
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add dnskey record: - update zone ${ZONE} at ns4 with ZSK from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "ns3/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Check the new DNSKEY RRset.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Check the logs for find zone keys errors.
|
||||
n=$((n + 1))
|
||||
echo_i "make sure we did not try to sign with the keys added with nsupdate for zone ${ZONE} ($n)"
|
||||
ret=0
|
||||
grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Verify again.
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove dnskey record: - try to remove ns3 ZSK from provider ns3 (should fail) ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "ns3/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Both ZSKs should still be published.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after failed update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove dnskey record: remove ns4 ZSK from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "ns4/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# We should have only the KSK and ZSK from provider ns3.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
check_keys
|
||||
check_apex
|
||||
dnssec_verify
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove dnskey record: try to remove ns4 ZSK from provider ns4 (should fail) ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "ns4/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Both ZSKs should still be published.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after failed update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove dnskey record: remove ns3 ZSK from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "ns3/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# We should have only the KSK and ZSK from provider ns4.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
check_keys
|
||||
check_apex
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
#
|
||||
# Update CDNSKEY RRset.
|
||||
#
|
||||
|
||||
# Check that the CDNSKEY from both providers are published.
|
||||
records_published() {
|
||||
_rrtype=$1
|
||||
_expect=$2
|
||||
|
||||
dig_with_opts "$ZONE" "@${SERVER}" "${_rrtype}" >"dig.out.$DIR.test$n" || return 1
|
||||
lines=$(awk -v rt="${_rrtype}" '$4 == rt {print}' dig.out.$DIR.test$n | wc -l)
|
||||
test "$lines" -eq "$_expect" || return 1
|
||||
}
|
||||
|
||||
# Retrieve CDNSKEY records from the other provider.
|
||||
dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY >dig.out.ns3.cdnskey
|
||||
awk '$4 == "CDNSKEY" {print}' dig.out.ns3.cdnskey >cdnskey.ns3
|
||||
dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY >dig.out.ns4.cdnskey
|
||||
awk '$4 == "CDNSKEY" {print}' dig.out.ns4.cdnskey >cdnskey.ns4
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cdnskey record: update zone ${ZONE} at ns3 with CDNSKEY from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Initially there should be one CDNSKEY.
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "cdnskey.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDNSKEY records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cdnskey record: update zone ${ZONE} at ns4 with CDNSKEY from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
# Initially there should be one CDNSKEY.
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "cdnskey.ns3")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDNSKEY records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# No DNSSEC in raw journal.
|
||||
no_dnssec_in_journal
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cdnskey record: remove ns4 CDNSKEY from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "cdnskey.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDNSKEY record again.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cdnskey record: remove ns3 CDNSKEY from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "cdnskey.ns3")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDNSKEY record again.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDNSKEY RRset after update ($n)"ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# No DNSSEC in raw journal.
|
||||
no_dnssec_in_journal
|
||||
|
||||
#
|
||||
# Update CDS RRset.
|
||||
#
|
||||
|
||||
# Retrieve CDS records from the other provider.
|
||||
dig_with_opts ${ZONE} @10.53.0.3 CDS >dig.out.ns3.cds
|
||||
awk '$4 == "CDS" {print}' dig.out.ns3.cds >cds.ns3
|
||||
dig_with_opts ${ZONE} @10.53.0.4 CDS >dig.out.ns4.cds
|
||||
awk '$4 == "CDS" {print}' dig.out.ns4.cds >cds.ns4
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cds record: update zone ${ZONE} at ns3 with CDS from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
# Initially there should be one CDS.
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "cds.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDS records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cds record: update zone ${ZONE} at ns4 with CDS from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
# Initially there should be one CDS.
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "cds.ns3")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDS records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# No DNSSEC in raw journal.
|
||||
no_dnssec_in_journal
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cds record: remove ns4 CDS from provider ns3 ($n)"
|
||||
ret=0
|
||||
set_server "ns3" "10.53.0.3"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "cds.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDS record again.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cds record: remove ns3 CDS from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns4" "10.53.0.4"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "cds.ns3")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDS record again.
|
||||
n=$((n + 1))
|
||||
echo_i "check zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# No DNSSEC in raw journal.
|
||||
no_dnssec_in_journal
|
||||
|
||||
#
|
||||
# Check secondary server behaviour.
|
||||
#
|
||||
set_zone "model2.secondary"
|
||||
set_policy "model2" "2" "3600"
|
||||
|
||||
set_server "ns3" "10.53.0.3"
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_model2
|
||||
check_keytimes
|
||||
check_apex
|
||||
dnssec_verify
|
||||
|
||||
set_server "ns4" "10.53.0.4"
|
||||
check_keys
|
||||
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
|
||||
set_keytimes_model2
|
||||
check_keytimes
|
||||
check_apex
|
||||
dnssec_verify
|
||||
|
||||
#
|
||||
# Update DNSKEY RRset.
|
||||
#
|
||||
n=$((n + 1))
|
||||
echo_i "add dnskey record: update zone ${ZONE} at ns5 with ZSKs from providers ns3 and ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "ns3/${ZONE}.zsk")
|
||||
echo update add $(cat "ns4/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 zsks_are_published || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
grep "dns_zone_findkeys: error reading ./K${ZONE}.*\.private: file not found" "${DIR}/named.run" && ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove dnskey record: remove ns3 and ns4 DNSKEY records from primary ns5 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "ns3/${ZONE}.zsk")
|
||||
echo update del $(cat "ns4/${ZONE}.zsk")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one DNSKEY record again.
|
||||
# While we did remove both DNSKEY records, the bump in the wire signer, i.e
|
||||
# the secondary inline-signing zone, should add back the DNSKEY belonging to
|
||||
# its own KSK when re-signing the zone.
|
||||
#
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
check_keys
|
||||
check_apex
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} DNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
check_keys
|
||||
check_apex
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
#
|
||||
# Update CDNSKEY RRset.
|
||||
#
|
||||
|
||||
# Retrieve CDNSKEY records from the providers.
|
||||
n=$((n + 1))
|
||||
echo_i "check initial CDSNKEY response for zone ${ZONE} at ns3 and ns4 ($n)"
|
||||
ret=0
|
||||
dig_with_opts ${ZONE} @10.53.0.3 CDNSKEY >dig.out.ns3.secondary.cdnskey
|
||||
awk '$4 == "CDNSKEY" {print}' dig.out.ns3.secondary.cdnskey >secondary.cdnskey.ns3
|
||||
dig_with_opts ${ZONE} @10.53.0.4 CDNSKEY >dig.out.ns4.secondary.cdnskey
|
||||
awk '$4 == "CDNSKEY" {print}' dig.out.ns4.secondary.cdnskey >secondary.cdnskey.ns4
|
||||
# Initially there should be one CDNSKEY.
|
||||
set_server "ns3" "10.53.0.3"
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
set_server "ns4" "10.53.0.4"
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cdnskey record: update zone ${ZONE} at ns5 with CDNSKEY records from providers ns3 and ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "secondary.cdnskey.ns3")
|
||||
echo update add $(cat "secondary.cdnskey.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDNSKEY records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
#
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cdnskey record: remove ns3 and ns4 CDNSKEY records from primary ns5 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "secondary.cdnskey.ns3")
|
||||
echo update del $(cat "secondary.cdnskey.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDNSKEY record again.
|
||||
# While we did remove both CDNSKEY records, the bump in the wire signer, i.e
|
||||
# the secondary inline-signing zone, should add back the CDNSKEY belonging to
|
||||
# its own KSK when re-signing the zone.
|
||||
#
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDNSKEY RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDNSKEY 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
#
|
||||
# Update CDS RRset.
|
||||
#
|
||||
|
||||
# Retrieve CDS records from the other provider.
|
||||
n=$((n + 1))
|
||||
echo_i "check initial CDS response for zone ${ZONE} at ns3 and ns4 ($n)"
|
||||
ret=0
|
||||
dig_with_opts ${ZONE} @10.53.0.3 CDS >dig.out.ns3.secondary.cds
|
||||
awk '$4 == "CDS" {print}' dig.out.ns3.secondary.cds >secondary.cds.ns3
|
||||
dig_with_opts ${ZONE} @10.53.0.4 CDS >dig.out.ns4.secondary.cds
|
||||
awk '$4 == "CDS" {print}' dig.out.ns4.secondary.cds >secondary.cds.ns4
|
||||
# Initially there should be one CDS.
|
||||
set_server "ns3" "10.53.0.3"
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
set_server "ns4" "10.53.0.4"
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "add cds record: update zone ${ZONE} at ns5 with CDS from provider ns4 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update add $(cat "secondary.cds.ns3")
|
||||
echo update add $(cat "secondary.cds.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be two CDS records (we test that BIND does not
|
||||
# skip it during DNSSEC maintenance).
|
||||
#
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 2 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "remove cds record: remove ns3 and ns4 CDS records from primary ns5 ($n)"
|
||||
ret=0
|
||||
set_server "ns5" "10.53.0.5"
|
||||
(
|
||||
echo zone "${ZONE}"
|
||||
echo server "${SERVER}" "${PORT}"
|
||||
echo update del $(cat "secondary.cds.ns3")
|
||||
echo update del $(cat "secondary.cds.ns4")
|
||||
echo send
|
||||
) | $NSUPDATE || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
# Now there should be one CDS record again.
|
||||
# While we did remove both CDS records, the bump in the wire signer, i.e
|
||||
# the secondary inline-signing zone, should add back the CDS belonging to
|
||||
# its own KSK when re-signing the zone.
|
||||
#
|
||||
# NS3
|
||||
n=$((n + 1))
|
||||
set_server "ns3" "10.53.0.3"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
# NS4
|
||||
n=$((n + 1))
|
||||
set_server "ns4" "10.53.0.4"
|
||||
echo_i "check server ${DIR} zone ${ZONE} CDS RRset after update ($n)"
|
||||
ret=0
|
||||
retry_quiet 10 records_published CDS 1 || ret=1
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
dnssec_verify
|
||||
no_dnssec_in_journal
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
650
bin/tests/system/multisigner/tests_multisigner.py
Normal file
650
bin/tests/system/multisigner/tests_multisigner.py
Normal file
|
|
@ -0,0 +1,650 @@
|
|||
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
from datetime import timedelta
|
||||
import os
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("dns", minversion="2.0.0")
|
||||
import dns
|
||||
import dns.update
|
||||
|
||||
import isctest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*.axfr",
|
||||
"*.created",
|
||||
"cdnskey.ns*",
|
||||
"cds.ns*",
|
||||
"dig.out.*",
|
||||
"rndc.dnssec.status.out.*",
|
||||
"secondary.cdnskey.ns*",
|
||||
"secondary.cds.ns*",
|
||||
"unused.*",
|
||||
"verify.out.*",
|
||||
"ns*/K*",
|
||||
"ns*/db-*",
|
||||
"ns*/keygen.out.*",
|
||||
"ns*/*.jbk",
|
||||
"ns*/*.jnl",
|
||||
"ns*/*.zsk",
|
||||
"ns*/*.signed",
|
||||
"ns*/*.journal.out.*",
|
||||
"ns*/settime.out.*",
|
||||
"ns*/model2.secondary.db",
|
||||
]
|
||||
)
|
||||
|
||||
ALGORITHM = os.environ["DEFAULT_ALGORITHM_NUMBER"]
|
||||
SIZE = os.environ["DEFAULT_BITS"]
|
||||
CONFIG = {
|
||||
"dnskey-ttl": timedelta(hours=1),
|
||||
"ds-ttl": timedelta(days=1),
|
||||
"max-zone-ttl": timedelta(days=1),
|
||||
"parent-propagation-delay": timedelta(hours=1),
|
||||
"publish-safety": timedelta(hours=1),
|
||||
"retire-safety": timedelta(hours=1),
|
||||
"signatures-refresh": timedelta(days=5),
|
||||
"signatures-validity": timedelta(days=14),
|
||||
"zone-propagation-delay": timedelta(minutes=5),
|
||||
}
|
||||
TTL = 3600
|
||||
|
||||
|
||||
def dsfromkey(key):
|
||||
dsfromkey_command = [
|
||||
os.environ.get("DSFROMKEY"),
|
||||
"-T",
|
||||
str(TTL),
|
||||
"-a",
|
||||
"SHA-256",
|
||||
"-C",
|
||||
"-w",
|
||||
str(key.keyfile),
|
||||
]
|
||||
out = isctest.run.cmd(dsfromkey_command)
|
||||
return out.stdout.decode("utf-8").split()
|
||||
|
||||
|
||||
def check_dnssec(server, zone, keys, expected):
|
||||
ksks = [k for k in keys if k.is_ksk()]
|
||||
zsks = [k for k in keys if not k.is_ksk()]
|
||||
|
||||
isctest.kasp.check_keys(zone, keys, expected)
|
||||
|
||||
for kp in expected:
|
||||
kp.set_expected_keytimes(CONFIG)
|
||||
kp.set_expected_keytimes(CONFIG)
|
||||
start = kp.key.get_timing("Created")
|
||||
kp.timing["Published"] = start
|
||||
kp.timing["Active"] = start
|
||||
if kp.role != "zsk":
|
||||
kp.timing["PublishCDS"] = start
|
||||
|
||||
isctest.kasp.check_dnssec_verify(server, zone)
|
||||
isctest.kasp.check_apex(server, zone, ksks, zsks)
|
||||
|
||||
|
||||
def check_no_dnssec_in_journal(server, zone):
|
||||
journalprint = [
|
||||
os.environ.get("JOURNALPRINT"),
|
||||
f"{server.identifier}/{zone}.db.jnl",
|
||||
]
|
||||
|
||||
out = isctest.run.cmd(journalprint)
|
||||
contents = out.stdout.decode("utf-8")
|
||||
pattern = re.compile(
|
||||
r"^\s*(?:\S+\s+){4}(NSEC|NSEC3|NSEC3PARAM|RRSIG)", flags=re.MULTILINE
|
||||
)
|
||||
match = pattern.search(contents)
|
||||
assert not match, f"{match.group(1)} record found in journal"
|
||||
|
||||
|
||||
def wait_for_serial(primary, server, zone):
|
||||
if primary.identifier == server.identifier:
|
||||
# No need to check if the transfer has been done.
|
||||
return
|
||||
|
||||
def check_serial():
|
||||
response = isctest.query.tcp(
|
||||
query, primary.ip, primary.ports.dns, timeout=3, attempts=1
|
||||
)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
soa = response.get_rrset(
|
||||
response.answer,
|
||||
dns.name.from_text(fqdn),
|
||||
dns.rdataclass.IN,
|
||||
dns.rdatatype.SOA,
|
||||
)
|
||||
serial1 = soa[0].serial
|
||||
|
||||
response = isctest.query.tcp(
|
||||
query, server.ip, server.ports.dns, timeout=3, attempts=1
|
||||
)
|
||||
assert response.rcode() == dns.rcode.NOERROR
|
||||
soa = response.get_rrset(
|
||||
response.answer,
|
||||
dns.name.from_text(fqdn),
|
||||
dns.rdataclass.IN,
|
||||
dns.rdatatype.SOA,
|
||||
)
|
||||
serial2 = soa[0].serial
|
||||
|
||||
return (
|
||||
f"zone {zone}/IN (signed): serial {serial2} (unsigned {serial1})"
|
||||
in server.log
|
||||
)
|
||||
|
||||
fqdn = f"{zone}."
|
||||
query = isctest.query.create(fqdn, dns.rdatatype.SOA)
|
||||
|
||||
isctest.run.retry_with_timeout(check_serial, timeout=10)
|
||||
|
||||
|
||||
def check_add_zsk(server, zone, keys, expected, extra_keys, extra, primary=None):
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info("add dnskey record:")
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: update zone with ZSK from other providers"
|
||||
)
|
||||
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for zsk in extra_keys:
|
||||
dnskey = str(zsk.dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg.add(f"{zone}.", TTL, "DNSKEY", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# Check the new DNSKEY RRset.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check DNSKEY RRset after update add"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Check the logs for find zone keys errors.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: make sure we did not try to sign with the keys added with nsupdate"
|
||||
)
|
||||
server.log.prohibit(f"dns_zone_findkeys: error reading ./K{zone}")
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
server.log.prohibit(f"dns_zone_findkeys: error reading ./K{zone}")
|
||||
|
||||
|
||||
def _check_remove_zsk_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None
|
||||
):
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: try to remove own ZSK (should fail)"
|
||||
)
|
||||
|
||||
zsks = [k for k in keys if not k.is_ksk()]
|
||||
dnskey = str(zsks[0].dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
update_msg.delete(f"{zone}.", "DNSKEY", rdata)
|
||||
with primary.watch_log_from_here() as watcher:
|
||||
primary.nsupdate(update_msg)
|
||||
watcher.wait_for_line(
|
||||
f"updating zone '{zone}/IN': attempt to delete in use DNSKEY ignored"
|
||||
)
|
||||
|
||||
# Both ZSKs should still be published.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check DNSKEY RRset after ignored remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
|
||||
def check_remove_zsk(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None, check_fail=False
|
||||
):
|
||||
isctest.log.info("remove dnskey record:")
|
||||
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
if check_fail:
|
||||
_check_remove_zsk_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=primary
|
||||
)
|
||||
|
||||
# Remove actual ZSK.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: remove ZSK from other providers"
|
||||
)
|
||||
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for zsk in extra_keys:
|
||||
dnskey = str(zsk.dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg.delete(f"{zone}.", "DNSKEY", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# We should have only the KSK and ZSK from server.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check DNSKEY RRset after update remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
|
||||
def check_add_cdnskey(server, zone, keys, expected, extra_keys, extra, primary=None):
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info("add cdnskey record:")
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: update zone with CDNSKEY from other providers"
|
||||
)
|
||||
|
||||
# Update the server with the CDNSKEY record from the other providers.
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for ksk in extra_keys:
|
||||
dnskey = str(ksk.dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg.add(f"{zone}.", TTL, "CDNSKEY", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# Now there should be two CDNSKEY records.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDNSKEY RRset after update add"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
|
||||
def _check_remove_cdnskey_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None
|
||||
):
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: try to remove own CDNSKEY (should fail)"
|
||||
)
|
||||
|
||||
ksks = [k for k in keys if not k.is_ksk()]
|
||||
dnskey = str(ksks[0].dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
update_msg.delete(f"{zone}.", "CDNSKEY", rdata)
|
||||
with primary.watch_log_from_here() as watcher:
|
||||
primary.nsupdate(update_msg)
|
||||
watcher.wait_for_line(
|
||||
f"updating zone '{zone}/IN': attempt to delete in use CDNSKEY ignored"
|
||||
)
|
||||
|
||||
# Both CDNSKEY records should still be published.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDNSKEY RRset after ignored remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
|
||||
def check_remove_cdnskey(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None, check_fail=False
|
||||
):
|
||||
isctest.log.info("remove cdnskey record:")
|
||||
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
if check_fail:
|
||||
_check_remove_cdnskey_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=primary
|
||||
)
|
||||
|
||||
# Remove actual CDNSKEY.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: remove CDNSKEY from other providers"
|
||||
)
|
||||
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for ksk in extra_keys:
|
||||
dnskey = str(ksk.dnskey).split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
update_msg.delete(f"{zone}.", "CDNSKEY", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# Now there should be one CDNSKEY record again.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDNSKEY RRset after update remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
|
||||
def check_add_cds(server, zone, keys, expected, extra_keys, extra, primary=None):
|
||||
isctest.log.info("add cds record:")
|
||||
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: update zone with CDS from other providers"
|
||||
)
|
||||
|
||||
# Update the server with the CDS record from the other providers.
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for ksk in extra_keys:
|
||||
ds = dsfromkey(ksk)
|
||||
rdata = " ".join(ds[4:])
|
||||
update_msg.add(f"{zone}.", TTL, "CDS", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# Now there should be two CDS records.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDS RRset after update add"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
|
||||
def _check_remove_cds_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None
|
||||
):
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: try to remove own CDS (should fail)"
|
||||
)
|
||||
|
||||
ksks = [k for k in keys if not k.is_ksk()]
|
||||
ds = dsfromkey(ksks[0])
|
||||
rdata = " ".join(ds[4:])
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
update_msg.delete(f"{zone}.", "CDS", rdata)
|
||||
with primary.watch_log_from_here() as watcher:
|
||||
primary.nsupdate(update_msg)
|
||||
watcher.wait_for_line(
|
||||
f"updating zone '{zone}/IN': attempt to delete in use CDS ignored"
|
||||
)
|
||||
|
||||
# Both CDS records should still be published.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDS RRset after ignored remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys + extra_keys, expected + extra)
|
||||
|
||||
|
||||
def check_remove_cds(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=None, check_fail=False
|
||||
):
|
||||
isctest.log.info("remove cds record:")
|
||||
|
||||
if primary is None:
|
||||
primary = server
|
||||
|
||||
if check_fail:
|
||||
_check_remove_cds_fail(
|
||||
server, zone, keys, expected, extra_keys, extra, primary=primary
|
||||
)
|
||||
|
||||
# Remove actual CDS.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {primary.identifier}: remove CDS from other providers"
|
||||
)
|
||||
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
for ksk in extra_keys:
|
||||
ds = dsfromkey(ksk)
|
||||
rdata = " ".join(ds[4:])
|
||||
update_msg.delete(f"{zone}.", "CDS", rdata)
|
||||
primary.nsupdate(update_msg)
|
||||
|
||||
wait_for_serial(primary, server, zone)
|
||||
|
||||
# Now there should be one CDS record again.
|
||||
isctest.log.info(
|
||||
f"- zone {zone} {server.identifier}: check CDS RRset after update remove"
|
||||
)
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
# Trigger keymgr.
|
||||
with server.watch_log_from_here() as watcher:
|
||||
server.rndc(f"loadkeys {zone}", log=False)
|
||||
watcher.wait_for_line(f"keymgr: {zone} done")
|
||||
|
||||
# Check again.
|
||||
isctest.log.info(f"- zone {zone} {server.identifier}: check again after keymgr run")
|
||||
check_dnssec(server, zone, keys, expected)
|
||||
|
||||
|
||||
def test_multisigner(ns3, ns4):
|
||||
zone = "model2.multisigner"
|
||||
keyprops = [
|
||||
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
|
||||
f"zsk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent",
|
||||
]
|
||||
|
||||
# First make sure the zone is properly signed.
|
||||
isctest.log.info(f"basic DNSSEC tests for {zone}")
|
||||
isctest.kasp.wait_keymgr_done(ns3, zone)
|
||||
isctest.kasp.wait_keymgr_done(ns4, zone)
|
||||
|
||||
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
|
||||
ksks3 = [k for k in keys3 if k.is_ksk()]
|
||||
zsks3 = [k for k in keys3 if not k.is_ksk()]
|
||||
expected3 = isctest.kasp.policy_to_properties(ttl=TTL, keys=keyprops)
|
||||
|
||||
check_dnssec(ns3, zone, keys3, expected3)
|
||||
|
||||
keys4 = isctest.kasp.keydir_to_keylist(zone, ns4.identifier)
|
||||
ksks4 = [k for k in keys4 if k.is_ksk()]
|
||||
zsks4 = [k for k in keys4 if not k.is_ksk()]
|
||||
expected4 = isctest.kasp.policy_to_properties(ttl=TTL, keys=keyprops)
|
||||
|
||||
check_dnssec(ns4, zone, keys4, expected4)
|
||||
|
||||
# Add DNSKEY to RRset.
|
||||
newprops = [f"zsk unlimited {ALGORITHM} {SIZE}"]
|
||||
extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops)
|
||||
extra[0].private = False # noqa
|
||||
extra[0].legacy = True # noqa
|
||||
|
||||
check_add_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra)
|
||||
check_add_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove DNSKEY from RRset.
|
||||
check_remove_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra, check_fail=True)
|
||||
check_remove_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra, check_fail=True)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Add CDNSKEY RRset.
|
||||
newprops = [f"ksk unlimited {ALGORITHM} {SIZE}"]
|
||||
extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops)
|
||||
extra[0].private = False # noqa
|
||||
extra[0].legacy = True # noqa
|
||||
|
||||
check_add_cdnskey(ns3, zone, keys3, expected3, [ksks4[0]], extra)
|
||||
check_add_cdnskey(ns4, zone, keys4, expected4, [ksks3[0]], extra)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove CDNSKEY RRset.
|
||||
check_remove_cdnskey(
|
||||
ns3, zone, keys3, expected3, [ksks4[0]], extra, check_fail=True
|
||||
)
|
||||
check_remove_cdnskey(
|
||||
ns4, zone, keys4, expected4, [ksks3[0]], extra, check_fail=True
|
||||
)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Update CDS RRset.
|
||||
check_add_cds(ns3, zone, keys3, expected3, [ksks4[0]], extra)
|
||||
check_add_cds(ns4, zone, keys4, expected4, [ksks3[0]], extra)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove CDS RRset.
|
||||
check_remove_cds(ns3, zone, keys3, expected3, [ksks4[0]], extra, check_fail=True)
|
||||
check_remove_cds(ns4, zone, keys4, expected4, [ksks3[0]], extra, check_fail=True)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
|
||||
def test_multisigner_secondary(ns3, ns4, ns5):
|
||||
zone = "model2.secondary"
|
||||
keyprops = [
|
||||
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
|
||||
f"zsk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent",
|
||||
]
|
||||
|
||||
# First make sure the zone is properly signed.
|
||||
isctest.log.info(f"basic DNSSEC tests for {zone}")
|
||||
isctest.kasp.wait_keymgr_done(ns3, zone)
|
||||
isctest.kasp.wait_keymgr_done(ns4, zone)
|
||||
|
||||
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
|
||||
ksks3 = [k for k in keys3 if k.is_ksk()]
|
||||
zsks3 = [k for k in keys3 if not k.is_ksk()]
|
||||
expected3 = isctest.kasp.policy_to_properties(ttl=TTL, keys=keyprops)
|
||||
|
||||
check_dnssec(ns3, zone, keys3, expected3)
|
||||
|
||||
keys4 = isctest.kasp.keydir_to_keylist(zone, ns4.identifier)
|
||||
ksks4 = [k for k in keys4 if k.is_ksk()]
|
||||
zsks4 = [k for k in keys4 if not k.is_ksk()]
|
||||
expected4 = isctest.kasp.policy_to_properties(ttl=TTL, keys=keyprops)
|
||||
|
||||
check_dnssec(ns4, zone, keys4, expected4)
|
||||
|
||||
# Add DNSKEY to RRset.
|
||||
newprops = [f"zsk unlimited {ALGORITHM} {SIZE}"]
|
||||
extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops)
|
||||
extra[0].private = False # noqa
|
||||
extra[0].legacy = True # noqa
|
||||
|
||||
check_add_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra, primary=ns5)
|
||||
check_add_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove DNSKEY from RRset.
|
||||
check_remove_zsk(ns3, zone, keys3, expected3, [zsks4[0]], extra, primary=ns5)
|
||||
check_remove_zsk(ns4, zone, keys4, expected4, [zsks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Add CDNSKEY RRset.
|
||||
newprops = [f"ksk unlimited {ALGORITHM} {SIZE}"]
|
||||
extra = isctest.kasp.policy_to_properties(ttl=TTL, keys=newprops)
|
||||
extra[0].private = False # noqa
|
||||
extra[0].legacy = True # noqa
|
||||
|
||||
check_add_cdnskey(ns3, zone, keys3, expected3, [ksks4[0]], extra, primary=ns5)
|
||||
check_add_cdnskey(ns4, zone, keys4, expected4, [ksks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove CDNSKEY RRset.
|
||||
check_remove_cdnskey(ns3, zone, keys3, expected3, [ksks4[0]], extra, primary=ns5)
|
||||
check_remove_cdnskey(ns4, zone, keys4, expected4, [ksks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Update CDS RRset.
|
||||
check_add_cds(ns3, zone, keys3, expected3, [ksks4[0]], extra, primary=ns5)
|
||||
check_add_cds(ns4, zone, keys4, expected4, [ksks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
||||
# Remove CDS RRset.
|
||||
check_remove_cds(ns3, zone, keys3, expected3, [ksks4[0]], extra, primary=ns5)
|
||||
check_remove_cds(ns4, zone, keys4, expected4, [ksks3[0]], extra, primary=ns5)
|
||||
check_no_dnssec_in_journal(ns3, zone)
|
||||
check_no_dnssec_in_journal(ns4, zone)
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
# 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 pytest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
[
|
||||
"*.created",
|
||||
"cdnskey.ns*",
|
||||
"cds.ns*",
|
||||
"created.*",
|
||||
"dig.out.*",
|
||||
"rndc.dnssec.status.out.*",
|
||||
"secondary.cdnskey.ns*",
|
||||
"secondary.cds.ns*",
|
||||
"unused.*",
|
||||
"verify.out.*",
|
||||
"ns*/K*",
|
||||
"ns*/db-*",
|
||||
"ns*/keygen.out.*",
|
||||
"ns*/*.jbk",
|
||||
"ns*/*.jnl",
|
||||
"ns*/*.zsk",
|
||||
"ns*/*.signed",
|
||||
"ns*/*.journal.out.*",
|
||||
"ns*/settime.out.*",
|
||||
"ns*/model2.secondary.db",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_multisigner(run_tests_sh):
|
||||
run_tests_sh()
|
||||
Loading…
Reference in a new issue