diff --git a/bin/tests/system/Makefile.am b/bin/tests/system/Makefile.am index d640bda038..842bb5db8b 100644 --- a/bin/tests/system/Makefile.am +++ b/bin/tests/system/Makefile.am @@ -128,6 +128,7 @@ TESTS = \ kasp \ keepalive \ keyfromlabel \ + ksr \ legacy \ limits \ logfileconfig \ diff --git a/bin/tests/system/ksr/clean.sh b/bin/tests/system/ksr/clean.sh new file mode 100644 index 0000000000..9c19a7d88b --- /dev/null +++ b/bin/tests/system/ksr/clean.sh @@ -0,0 +1,21 @@ +#!/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 + +rm -f ./created.out +rm -f ./python.out +rm -f ./named.conf +rm -f ./K* +rm -f ./ksr.out.* +rm -rf ./keydir diff --git a/bin/tests/system/ksr/named.conf.in b/bin/tests/system/ksr/named.conf.in new file mode 100644 index 0000000000..abc64fb9e8 --- /dev/null +++ b/bin/tests/system/ksr/named.conf.in @@ -0,0 +1,41 @@ +/* + * 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. + */ + +dnssec-policy "common" { + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "csk" { + keys { + csk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "unlimited" { + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "two-tone" { + keys { + ksk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + ksk lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@; + zsk lifetime P3M algorithm @DEFAULT_ALGORITHM@; + zsk lifetime P5M algorithm @ALTERNATIVE_ALGORITHM@; + }; +}; diff --git a/bin/tests/system/ksr/setup.sh b/bin/tests/system/ksr/setup.sh new file mode 100644 index 0000000000..3e95924fc6 --- /dev/null +++ b/bin/tests/system/ksr/setup.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +# shellcheck source=conf.sh +. ../conf.sh + +set -e + +$SHELL clean.sh + +mkdir keydir + +copy_setports named.conf.in named.conf diff --git a/bin/tests/system/ksr/tests.sh b/bin/tests/system/ksr/tests.sh new file mode 100644 index 0000000000..6d3d7c9bdb --- /dev/null +++ b/bin/tests/system/ksr/tests.sh @@ -0,0 +1,232 @@ +#!/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. + +# shellcheck source=conf.sh +. ../conf.sh +# shellcheck source=kasp.sh +. ../kasp.sh + +set -e + +status=0 +n=0 + +# Get timing metadata from a value plus additional time. +# $1: Value +# $2: Additional time +addtime() { + if [ -x "$PYTHON" ]; then + # Convert "%Y%m%d%H%M%S" format to epoch seconds. + # Then, add the additional time (can be negative). + _value=$1 + _plus=$2 + $PYTHON > python.out < created.out || return 1 + created=$(awk '{print $3}' < created.out) + # active: created + inception + active=$(addtime $created $inception) + # published: 2h5m (dnskey-ttl + publish-safety + propagation) + published=$(addtime $active -7500) + # retired: zsk-lifetime + retired=$(addtime $active $lifetime) + # removed: 10d1h5m (ttlsig + retire-safety + sign-delay + propagation) + removed=$(addtime $retired 867900) + + echo_i "check metadata on $key" + statefile="${dir}/${key}.state" + grep "Algorithm: $alg" $statefile > /dev/null || return 1 + grep "Length: $size" $statefile > /dev/null || return 1 + grep "Lifetime: $lifetime" $statefile > /dev/null || return 1 + grep "KSK: no" $statefile > /dev/null || return 1 + grep "ZSK: yes" $statefile > /dev/null || return 1 + grep "Published: $published" $statefile > /dev/null || return 1 + grep "Active: $active" $statefile > /dev/null || return 1 + grep "Retired: $retired" $statefile > /dev/null || return 1 + grep "Removed: $removed" $statefile > /dev/null || return 1 + + inception=$((inception+lifetime)) + + cp ${dir}/${key}.key ${key}.key.expect + cp ${dir}/${key}.private ${key}.private.expect + cp ${dir}/${key}.state ${key}.state.expect + done + + return 0 +) + + +# Call the dnssec-ksr command: +# ksr [options] +ksr () { + $KSR -l named.conf -k "$@" +} + +# Unknown action. +n=$((n+1)) +echo_i "check that 'dnssec-ksr' errors on unknown action ($n)" +ret=0 +ksr common foobar common.test > ksr.out.$n 2>&1 && ret=1 +grep "dnssec-ksr: fatal: unknown command 'foobar'" ksr.out.$n > /dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +# Key generation. +set_zsk () { + ALG=$1 + SIZE=$2 + LIFETIME=$3 +} + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' errors on missing end date ($n)" +ret=0 +ksr common keygen common.test > ksr.out.$n 2>&1 && ret=1 +grep "dnssec-ksr: fatal: keygen requires an end date" ksr.out.$n > /dev/null|| ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' pregenerates right amount of keys in the common case ($n)" +ret=0 +ksr common -i now -e +1y keygen common.test > ksr.out.$n 2>&1 || ret=1 +num=$(cat ksr.out.$n | wc -l) +[ $num -eq 2 ] || ret=1 +set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400 +check_keys common.test "." || ret=1 +cp ksr.out.$n ksr.out.expect +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' selects pregenerated keys for the same time bundle ($n)" +ret=0 +ksr common -e +1y keygen common.test > ksr.out.$n 2>&1 || ret=1 +diff ksr.out.expect ksr.out.$n > /dev/null|| ret=1 +for key in $(cat ksr.out.$n) +do + # Ensure the files are not modified. + diff ${key}.key ${key}.key.expect > /dev/null || ret=1 + diff ${key}.private ${key}.private.expect > /dev/null || ret=1 + diff ${key}.state ${key}.state.expect > /dev/null || ret=1 +done +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' selects generates only necessary keys for overlapping time bundle ($n)" +ret=0 +ksr common -e +2y -v 1 keygen common.test > ksr.out.$n 2>&1 || ret=1 +num=$(cat ksr.out.$n | wc -l) +[ $num -eq 4 ] || ret=1 +# 2 selected, 2 generated +num=$(grep "Selecting" ksr.out.$n | wc -l) +[ $num -eq 2 ] || ret=1 +num=$(grep "Generating" ksr.out.$n | wc -l) +[ $num -eq 2 ] || ret=1 +set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400 +check_keys "." || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' pregenerates keys in the given key-directory ($n)" +ret=0 +ksr common -i now -e +1y -K keydir keygen common.test > ksr.out.$n 2>&1 || ret=1 +num=$(cat ksr.out.$n | wc -l) +[ $num -eq 2 ] || ret=1 +set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 16070400 +check_keys "keydir" || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' creates only one key for zsk with unlimited lifetime ($n)" +ret=0 +ksr unlimited -e +2y keygen unlimited.test > ksr.out.$n 2>&1 || ret=1 +num=$(cat ksr.out.$n | wc -l) +[ $num -eq 1 ] || ret=1 +key=$(cat ksr.out.$n) +grep "; Created:" "${key}.key" > created.out || ret=1 +created=$(awk '{print $3}' < created.out) +active=$created +published=$(addtime $active -7500) +echo_i "check metadata on $key" +grep "Algorithm: $DEFAULT_ALGORITHM_NUMBER" ${key}.state > /dev/null || ret=1 +grep "Length: $DEFAULT_BITS" ${key}.state > /dev/null || ret=1 +grep "Lifetime: 0" ${key}.state > /dev/null || ret=1 +grep "KSK: no" ${key}.state > /dev/null || ret=1 +grep "ZSK: yes" ${key}.state > /dev/null || ret=1 +grep "Published: $published" ${key}.state > /dev/null || ret=1 +grep "Active: $active" ${key}.state > /dev/null || ret=1 +grep "Retired:" ${key}.state > /dev/null && ret=1 +grep "Removed:" ${key}.state > /dev/null && ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' creates no keys for policy with csk ($n)" +ret=0 +ksr csk -e +2y keygen csk.test > ksr.out.$n 2>&1 && ret=1 +grep "dnssec-ksr: fatal: policy 'csk' has no zsks" ksr.out.$n > /dev/null || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +n=$((n+1)) +echo_i "check that 'dnssec-ksr' creates keys for different algorithms ($n)" +ret=0 +ksr two-tone -e +1y keygen two-tone.test > ksr.out.$n 2>&1 || ret=1 +# First algorithm keys have a lifetime of 3 months, so there should be 4 created keys. +alg=$(printf "%03d" "$DEFAULT_ALGORITHM_NUMBER") +num=$(grep "Ktwo-tone.test.+$alg+" ksr.out.$n | wc -l) +[ $num -eq 4 ] || ret=1 +set_zsk $DEFAULT_ALGORITHM_NUMBER $DEFAULT_BITS 8035200 +check_keys two-tone.test "." || ret=1 +# Second algorithm keys have a lifetime of 5 months, so there should be 3 created keys. +# While only two time bundles of 5 months fit into one year, we need to create an +# extra key for the remainder of the bundle. +alg=$(printf "%03d" "$ALTERNATIVE_ALGORITHM_NUMBER") +num=$(grep "Ktwo-tone.test.+$alg+" ksr.out.$n | wc -l) +[ $num -eq 3 ] || ret=1 +set_zsk $ALTERNATIVE_ALGORITHM_NUMBER $ALTERNATIVE_BITS 13392000 +check_keys two-tone.test "." $ALTERNATIVE_ALGORITHM_NUMBER 13392000 || ret=1 +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/ksr/tests_sh_ksr.py b/bin/tests/system/ksr/tests_sh_ksr.py new file mode 100644 index 0000000000..56f07ce094 --- /dev/null +++ b/bin/tests/system/ksr/tests_sh_ksr.py @@ -0,0 +1,14 @@ +# 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. + + +def test_ksr(run_tests_sh): + run_tests_sh()