mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-07 07:50:29 -05:00
The kasp system test has a call to sed to retrieve the key identifier without leading zeros. The sed call could not handle key id 0. Update the kasp test to also correctly deal with this case.
2041 lines
76 KiB
Bash
2041 lines
76 KiB
Bash
#!/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 http://mozilla.org/MPL/2.0/.
|
|
#
|
|
# See the COPYRIGHT file distributed with this work for additional
|
|
# information regarding copyright ownership.
|
|
|
|
# shellcheck source=conf.sh
|
|
SYSTEMTESTTOP=..
|
|
. "$SYSTEMTESTTOP/conf.sh"
|
|
|
|
status=0
|
|
n=0
|
|
|
|
###############################################################################
|
|
# Constants #
|
|
###############################################################################
|
|
DEFAULT_TTL=300
|
|
|
|
###############################################################################
|
|
# Query properties #
|
|
###############################################################################
|
|
TSIG=""
|
|
SHA1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
|
|
SHA224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
|
|
SHA256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
|
|
|
|
###############################################################################
|
|
# Key properties #
|
|
###############################################################################
|
|
# ID=0
|
|
# EXPECT=1
|
|
# ROLE=2
|
|
# KSK=3
|
|
# ZSK=4
|
|
# LIFETIME=5
|
|
# ALG_NUM=6
|
|
# ALG_STR=7
|
|
# ALG_LEN=8
|
|
# PUBLISHED=9
|
|
# ACTIVE=10
|
|
# RETIRED=11
|
|
# REVOKED=12
|
|
# REMOVED=13
|
|
# GOAL=14
|
|
# STATE_DNSKEY=15
|
|
# STATE_ZRRSIG=16
|
|
# STATE_KRRSIG=17
|
|
# STATE_DS=18
|
|
# EXPECT_ZRRSIG=19
|
|
# EXPECT_KRRSIG=20
|
|
|
|
key_key() {
|
|
echo "${1}__${2}"
|
|
}
|
|
|
|
key_get() {
|
|
eval "echo \${$(key_key "$1" "$2")}"
|
|
}
|
|
|
|
key_set() {
|
|
eval "$(key_key "$1" "$2")='$3'"
|
|
}
|
|
|
|
# Clear key state.
|
|
#
|
|
# This will update either the KEY1, KEY2, or KEY3 array.
|
|
key_clear() {
|
|
key_set "$1" "ID" 'no'
|
|
key_set "$1" "EXPECT" 'no'
|
|
key_set "$1" "ROLE" 'none'
|
|
key_set "$1" "KSK" 'no'
|
|
key_set "$1" "ZSK" 'no'
|
|
key_set "$1" "LIFETIME" '0'
|
|
key_set "$1" "ALG_NUM" '0'
|
|
key_set "$1" "ALG_STR" 'none'
|
|
key_set "$1" "ALG_LEN" '0'
|
|
key_set "$1" "PUBLISHED" 'none'
|
|
key_set "$1" "ACTIVE" 'none'
|
|
key_set "$1" "RETIRED" 'none'
|
|
key_set "$1" "REVOKED" 'none'
|
|
key_set "$1" "REMOVED" 'none'
|
|
key_set "$1" "GOAL" 'none'
|
|
key_set "$1" "STATE_DNSKEY" 'none'
|
|
key_set "$1" "STATE_KRRSIG" 'none'
|
|
key_set "$1" "STATE_ZRRSIG" 'none'
|
|
key_set "$1" "STATE_DS" 'none'
|
|
key_set "$1" "EXPECT_ZRRSIG" 'no'
|
|
key_set "$1" "EXPECT_KRRSIG" 'no'
|
|
}
|
|
|
|
# Start clear.
|
|
key_clear "KEY1"
|
|
key_clear "KEY2"
|
|
key_clear "KEY3"
|
|
|
|
###############################################################################
|
|
# Utilities #
|
|
###############################################################################
|
|
|
|
# Call dig with default options.
|
|
dig_with_opts() {
|
|
if [ -n "$TSIG" ]; then
|
|
"$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" -y "$TSIG" "$@"
|
|
else
|
|
"$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "$PORT" "$@"
|
|
fi
|
|
}
|
|
|
|
# RNDC.
|
|
rndccmd() {
|
|
"$RNDC" -c "$SYSTEMTESTTOP/common/rndc.conf" -p "$CONTROLPORT" -s "$@"
|
|
}
|
|
|
|
# Print IDs of keys used for generating RRSIG records for RRsets of type $1
|
|
# found in dig output file $2.
|
|
get_keys_which_signed() {
|
|
_qtype=$1
|
|
_output=$2
|
|
# The key ID is the 11th column of the RRSIG record line.
|
|
awk -v qt="$_qtype" '$4 == "RRSIG" && $5 == qt {print $11}' < "$_output"
|
|
}
|
|
|
|
# Get the key ids from key files for zone $2 in directory $1
|
|
# that matches algorithm $3.
|
|
get_keyids() {
|
|
_dir=$1
|
|
_zone=$2
|
|
_algorithm=$(printf "%03d" "$3")
|
|
_start="K${_zone}.+${_algorithm}+"
|
|
_end=".key"
|
|
|
|
if [ "$_algorithm" -ne 0 ]; then
|
|
find "${_dir}" -mindepth 1 -maxdepth 1 -name "${_start}*${_end}" | sed "s,$_dir/K${_zone}.+${_algorithm}+\([0-9]\{5\}\)${_end},\1,"
|
|
fi
|
|
}
|
|
|
|
# By default log errors and don't quit immediately.
|
|
_log=1
|
|
log_error() {
|
|
test $_log -eq 1 && echo_i "error: $1"
|
|
ret=$((ret+1))
|
|
}
|
|
|
|
# Set zone properties for testing keys.
|
|
# $1: Key directory
|
|
# $2: Zone name
|
|
# $3: Policy name
|
|
# $4: DNSKEY TTL
|
|
# $5: Number of keys
|
|
# $6: Name server
|
|
#
|
|
# This will set the following environment variables for testing:
|
|
# DIR, ZONE, POLICY, DNSKEY_TTL, NUM_KEYS, SERVER
|
|
zone_properties() {
|
|
DIR=$1
|
|
ZONE=$2
|
|
POLICY=$3
|
|
DNSKEY_TTL=$4
|
|
NUM_KEYS=$5
|
|
SERVER=$6
|
|
}
|
|
|
|
# Set key properties for testing keys.
|
|
# $1: Key to update
|
|
# $2: Role
|
|
# $3: Lifetime
|
|
# $4: Algorithm (number)
|
|
# $5: Algorithm (string-format)
|
|
# $6: Algorithm length
|
|
# $7: Is zone signing
|
|
# $8: Is key signing
|
|
#
|
|
# This will update either the KEY1, KEY2 or KEY3 array.
|
|
key_properties() {
|
|
key_set "$1" "EXPECT" "yes"
|
|
key_set "$1" "ROLE" "$2"
|
|
key_set "$1" "KSK" "no"
|
|
key_set "$1" "ZSK" "no"
|
|
test "$2" = "ksk" && key_set "$1" "KSK" "yes"
|
|
test "$2" = "zsk" && key_set "$1" "ZSK" "yes"
|
|
test "$2" = "csk" && key_set "$1" "KSK" "yes"
|
|
test "$2" = "csk" && key_set "$1" "ZSK" "yes"
|
|
key_set "$1" "LIFETIME" "$3"
|
|
key_set "$1" "ALG_NUM" "$4"
|
|
key_set "$1" "ALG_STR" "$5"
|
|
key_set "$1" "ALG_LEN" "$6"
|
|
key_set "$1" "EXPECT_ZRRSIG" "$7"
|
|
key_set "$1" "EXPECT_KRRSIG" "$8"
|
|
}
|
|
|
|
# Set key timing metadata. Set to "none" to unset.
|
|
# These times are hard to test, so it is just an indication that we expect the
|
|
# respective timing metadata in the key files.
|
|
# $1: Key to update
|
|
# $2: Published
|
|
# $3: Active
|
|
# $4: Retired
|
|
# $5: Revoked
|
|
# $6: Removed
|
|
#
|
|
# This will update either the KEY1, KEY2 or KEY3 array.
|
|
key_timings() {
|
|
key_set "$1" "EXPECT" "yes"
|
|
key_set "$1" "PUBLISHED" "$2"
|
|
key_set "$1" "ACTIVE" "$3"
|
|
key_set "$1" "RETIRED" "$4"
|
|
key_set "$1" "REVOKED" "$5"
|
|
key_set "$1" "REMOVED" "$6"
|
|
}
|
|
|
|
# Set key state metadata. Set to "none" to unset.
|
|
# $1: Key to update
|
|
# $2: Goal state
|
|
# $3: DNSKEY state
|
|
# $4: RRSIG state (zsk)
|
|
# $5: RRSIG state (ksk)
|
|
# $6: DS state
|
|
#
|
|
# This will update either the KEY1, KEY2, OR KEY3 array.
|
|
key_states() {
|
|
key_set "$1" "EXPECT" "yes"
|
|
key_set "$1" "GOAL" "$2"
|
|
key_set "$1" "STATE_DNSKEY" "$3"
|
|
key_set "$1" "STATE_ZRRSIG" "$4"
|
|
key_set "$1" "STATE_KRRSIG" "$5"
|
|
key_set "$1" "STATE_DS" "$6"
|
|
}
|
|
|
|
# Check the key $1 with id $2.
|
|
# This requires environment variables to be set with 'zone_properties',
|
|
# 'key_properties', 'key_timings', and 'key_states'.
|
|
#
|
|
# This will set the following environment variables for testing:
|
|
# BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
|
|
# KEY_FILE="${BASE_FILE}.key"
|
|
# PRIVATE_FILE="${BASE_FILE}.private"
|
|
# STATE_FILE="${BASE_FILE}.state"
|
|
# KEY_ID=$(echo $1 | sed 's/^0\{0,4\}//')
|
|
check_key() {
|
|
_dir="$DIR"
|
|
_zone="$ZONE"
|
|
_role=$(key_get "$1" ROLE)
|
|
_key_idpad="$2"
|
|
_key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//')
|
|
_alg_num=$(key_get "$1" ALG_NUM)
|
|
_alg_numpad=$(printf "%03d" "$_alg_num")
|
|
_alg_string=$(key_get "$1" ALG_STR)
|
|
_length=$(key_get "$1" "ALG_LEN")
|
|
_dnskey_ttl="$DNSKEY_TTL"
|
|
_lifetime=$(key_get "$1" LIFETIME)
|
|
|
|
_published=$(key_get "$1" PUBLISHED)
|
|
_active=$(key_get "$1" ACTIVE)
|
|
_retired=$(key_get "$1" RETIRED)
|
|
_revoked=$(key_get "$1" REVOKED)
|
|
_removed=$(key_get "$1" REMOVED)
|
|
|
|
_goal=$(key_get "$1" GOAL)
|
|
_state_dnskey=$(key_get "$1" STATE_DNSKEY)
|
|
_state_zrrsig=$(key_get "$1" STATE_ZRRSIG)
|
|
_state_krrsig=$(key_get "$1" STATE_KRRSIG)
|
|
_state_ds=$(key_get "$1" STATE_DS)
|
|
|
|
_ksk="no"
|
|
_zsk="no"
|
|
if [ "$_role" = "ksk" ]; then
|
|
_role2="key-signing"
|
|
_ksk="yes"
|
|
_flags="257"
|
|
elif [ "$_role" = "zsk" ]; then
|
|
_role2="zone-signing"
|
|
_zsk="yes"
|
|
_flags="256"
|
|
elif [ "$_role" = "csk" ]; then
|
|
_role2="key-signing"
|
|
_zsk="yes"
|
|
_ksk="yes"
|
|
_flags="257"
|
|
fi
|
|
|
|
BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
|
|
KEY_FILE="${BASE_FILE}.key"
|
|
PRIVATE_FILE="${BASE_FILE}.private"
|
|
STATE_FILE="${BASE_FILE}.state"
|
|
KEY_ID="${_key_id}"
|
|
|
|
test $_log -eq 1 && echo_i "check key $BASE_FILE"
|
|
|
|
# Check the public key file.
|
|
grep "This is a ${_role2} key, keyid ${_key_id}, for ${_zone}." "$KEY_FILE" > /dev/null || log_error "mismatch top comment in $KEY_FILE"
|
|
grep "${_zone}\. ${_dnskey_ttl} IN DNSKEY ${_flags} 3 ${_alg_num}" "$KEY_FILE" > /dev/null || log_error "mismatch DNSKEY record in $KEY_FILE"
|
|
# Now check the private key file.
|
|
grep "Private-key-format: v1.3" "$PRIVATE_FILE" > /dev/null || log_error "mismatch private key format in $PRIVATE_FILE"
|
|
grep "Algorithm: ${_alg_num} (${_alg_string})" "$PRIVATE_FILE" > /dev/null || log_error "mismatch algorithm in $PRIVATE_FILE"
|
|
# Now check the key state file.
|
|
grep "This is the state of key ${_key_id}, for ${_zone}." "$STATE_FILE" > /dev/null || log_error "mismatch top comment in $STATE_FILE"
|
|
grep "Lifetime: ${_lifetime}" "$STATE_FILE" > /dev/null || log_error "mismatch lifetime in $STATE_FILE"
|
|
grep "Algorithm: ${_alg_num}" "$STATE_FILE" > /dev/null || log_error "mismatch algorithm in $STATE_FILE"
|
|
grep "Length: ${_length}" "$STATE_FILE" > /dev/null || log_error "mismatch length in $STATE_FILE"
|
|
grep "KSK: ${_ksk}" "$STATE_FILE" > /dev/null || log_error "mismatch ksk in $STATE_FILE"
|
|
grep "ZSK: ${_zsk}" "$STATE_FILE" > /dev/null || log_error "mismatch zsk in $STATE_FILE"
|
|
|
|
# Check key states.
|
|
if [ "$_goal" = "none" ]; then
|
|
grep "GoalState: " "$STATE_FILE" > /dev/null && log_error "unexpected goal state in $STATE_FILE"
|
|
else
|
|
grep "GoalState: ${_goal}" "$STATE_FILE" > /dev/null || log_error "mismatch goal state in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_state_dnskey" = "none" ]; then
|
|
grep "DNSKEYState: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey state in $STATE_FILE"
|
|
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null && log_error "unexpected dnskey change in $STATE_FILE"
|
|
else
|
|
grep "DNSKEYState: ${_state_dnskey}" "$STATE_FILE" > /dev/null || log_error "mismatch dnskey state in $STATE_FILE"
|
|
grep "DNSKEYChange: " "$STATE_FILE" > /dev/null || log_error "mismatch dnskey change in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_state_zrrsig" = "none" ]; then
|
|
grep "ZRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig state in $STATE_FILE"
|
|
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected zrrsig change in $STATE_FILE"
|
|
else
|
|
grep "ZRRSIGState: ${_state_zrrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig state in $STATE_FILE"
|
|
grep "ZRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch zrrsig change in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_state_krrsig" = "none" ]; then
|
|
grep "KRRSIGState: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig state in $STATE_FILE"
|
|
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null && log_error "unexpected krrsig change in $STATE_FILE"
|
|
else
|
|
grep "KRRSIGState: ${_state_krrsig}" "$STATE_FILE" > /dev/null || log_error "mismatch krrsig state in $STATE_FILE"
|
|
grep "KRRSIGChange: " "$STATE_FILE" > /dev/null || log_error "mismatch krrsig change in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_state_ds" = "none" ]; then
|
|
grep "DSState: " "$STATE_FILE" > /dev/null && log_error "unexpected ds state in $STATE_FILE"
|
|
grep "DSChange: " "$STATE_FILE" > /dev/null && log_error "unexpected ds change in $STATE_FILE"
|
|
else
|
|
grep "DSState: ${_state_ds}" "$STATE_FILE" > /dev/null || log_error "mismatch ds state in $STATE_FILE"
|
|
grep "DSChange: " "$STATE_FILE" > /dev/null || log_error "mismatch ds change in $STATE_FILE"
|
|
fi
|
|
|
|
# Check timing metadata.
|
|
if [ "$_published" = "none" ]; then
|
|
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
|
|
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
|
|
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
|
|
else
|
|
grep "; Publish:" "$KEY_FILE" > /dev/null || log_error "mismatch publish comment in $KEY_FILE ($KEY_PUBLISHED)"
|
|
grep "Publish:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch publish in $PRIVATE_FILE ($KEY_PUBLISHED)"
|
|
grep "Published:" "$STATE_FILE" > /dev/null || log_error "mismatch publish in $STATE_FILE ($KEY_PUBLISHED)"
|
|
fi
|
|
|
|
if [ "$_active" = "none" ]; then
|
|
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
|
|
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
|
|
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
|
|
else
|
|
grep "; Activate:" "$KEY_FILE" > /dev/null || log_error "mismatch active comment in $KEY_FILE"
|
|
grep "Activate:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch active in $PRIVATE_FILE"
|
|
grep "Active: " "$STATE_FILE" > /dev/null || log_error "mismatch active in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_retired" = "none" ]; then
|
|
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
|
|
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
|
|
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
|
|
else
|
|
grep "; Inactive:" "$KEY_FILE" > /dev/null || log_error "mismatch retired comment in $KEY_FILE"
|
|
grep "Inactive:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch retired in $PRIVATE_FILE"
|
|
grep "Retired: " "$STATE_FILE" > /dev/null || log_error "mismatch retired in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_revoked" = "none" ]; then
|
|
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
|
|
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
|
|
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
|
|
else
|
|
grep "; Revoke:" "$KEY_FILE" > /dev/null || log_error "mismatch revoked comment in $KEY_FILE"
|
|
grep "Revoke:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch revoked in $PRIVATE_FILE"
|
|
grep "Revoked: " "$STATE_FILE" > /dev/null || log_error "mismatch revoked in $STATE_FILE"
|
|
fi
|
|
|
|
if [ "$_removed" = "none" ]; then
|
|
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
|
|
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
|
|
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
|
|
else
|
|
grep "; Delete:" "$KEY_FILE" > /dev/null || log_error "mismatch removed comment in $KEY_FILE"
|
|
grep "Delete:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch removed in $PRIVATE_FILE"
|
|
grep "Removed: " "$STATE_FILE" > /dev/null || log_error "mismatch removed in $STATE_FILE"
|
|
fi
|
|
|
|
grep "; Created:" "$KEY_FILE" > /dev/null || log_error "mismatch created comment in $KEY_FILE"
|
|
grep "Created:" "$PRIVATE_FILE" > /dev/null || log_error "mismatch created in $PRIVATE_FILE"
|
|
grep "Generated: " "$STATE_FILE" > /dev/null || log_error "mismatch generated in $STATE_FILE"
|
|
}
|
|
|
|
# Check the key with key id $1 and see if it is unused.
|
|
# This requires environment variables to be set with 'zone_properties',
|
|
# and 'key_properties'.
|
|
#
|
|
# This will set the following environment variables for testing:
|
|
# BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
|
|
# KEY_FILE="${BASE_FILE}.key"
|
|
# PRIVATE_FILE="${BASE_FILE}.private"
|
|
# STATE_FILE="${BASE_FILE}.state"
|
|
# KEY_ID=$(echo $1 | sed 's/^0\{0,4\}//')
|
|
key_unused() {
|
|
_dir=$DIR
|
|
_zone=$ZONE
|
|
_key_idpad=$1
|
|
_key_id=$(echo "$_key_idpad" | sed 's/^0\{0,4\}//')
|
|
_alg_num=$(key_get KEY1 ALG_NUM)
|
|
_alg_numpad=$(printf "%03d" "$_alg_num")
|
|
|
|
BASE_FILE="${_dir}/K${_zone}.+${_alg_numpad}+${_key_idpad}"
|
|
KEY_FILE="${BASE_FILE}.key"
|
|
PRIVATE_FILE="${BASE_FILE}.private"
|
|
STATE_FILE="${BASE_FILE}.state"
|
|
KEY_ID="${_key_id}"
|
|
|
|
test $_log -eq 1 && echo_i "key unused $KEY_ID?"
|
|
|
|
# Check timing metadata.
|
|
grep "; Publish:" "$KEY_FILE" > /dev/null && log_error "unexpected publish comment in $KEY_FILE"
|
|
grep "Publish:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected publish in $PRIVATE_FILE"
|
|
grep "Published: " "$STATE_FILE" > /dev/null && log_error "unexpected publish in $STATE_FILE"
|
|
grep "; Activate:" "$KEY_FILE" > /dev/null && log_error "unexpected active comment in $KEY_FILE"
|
|
grep "Activate:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected active in $PRIVATE_FILE"
|
|
grep "Active: " "$STATE_FILE" > /dev/null && log_error "unexpected active in $STATE_FILE"
|
|
grep "; Inactive:" "$KEY_FILE" > /dev/null && log_error "unexpected retired comment in $KEY_FILE"
|
|
grep "Inactive:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected retired in $PRIVATE_FILE"
|
|
grep "Retired: " "$STATE_FILE" > /dev/null && log_error "unexpected retired in $STATE_FILE"
|
|
grep "; Revoke:" "$KEY_FILE" > /dev/null && log_error "unexpected revoked comment in $KEY_FILE"
|
|
grep "Revoke:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected revoked in $PRIVATE_FILE"
|
|
grep "Revoked: " "$STATE_FILE" > /dev/null && log_error "unexpected revoked in $STATE_FILE"
|
|
grep "; Delete:" "$KEY_FILE" > /dev/null && log_error "unexpected removed comment in $KEY_FILE"
|
|
grep "Delete:" "$PRIVATE_FILE" > /dev/null && log_error "unexpected removed in $PRIVATE_FILE"
|
|
grep "Removed: " "$STATE_FILE" > /dev/null && log_error "unexpected removed in $STATE_FILE"
|
|
}
|
|
|
|
# Test: dnssec-verify zone $1.
|
|
dnssec_verify()
|
|
{
|
|
n=$((n+1))
|
|
echo_i "dnssec-verify zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" AXFR > dig.out.axfr.test$n || log_error "dig ${ZONE} AXFR failed"
|
|
$VERIFY -z -o "$ZONE" dig.out.axfr.test$n > /dev/null || log_error "dnssec verify zone $ZONE failed"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
}
|
|
|
|
###############################################################################
|
|
# Tests #
|
|
###############################################################################
|
|
|
|
#
|
|
# dnssec-keygen
|
|
#
|
|
zone_properties "keys" "kasp" "kasp" "200" "10.53.0.1"
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-keygen -k' (configured policy) creates valid files ($n)"
|
|
ret=0
|
|
$KEYGEN -K keys -k "$POLICY" -l kasp.conf "$ZONE" > "keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
|
|
lines=$(wc -l < "keygen.out.$POLICY.test$n")
|
|
test "$lines" -eq 4 || log_error "wrong number of keys created for policy kasp: $lines"
|
|
# Temporarily don't log errors because we are searching multiple files.
|
|
_log=0
|
|
# Check one algorithm.
|
|
key_properties "KEY1" "csk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "none" "none" "none" "none" "none"
|
|
key_states "KEY1" "none" "none" "none" "none" "none"
|
|
ids=$(get_keyids "$DIR" "$ZONE" "$(key_get KEY1 ALG_NUM)")
|
|
for id in $ids; do
|
|
check_key "KEY1" "$id"
|
|
done
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
# Check the other algorithm.
|
|
key_properties "KEY1" "ksk" "31536000" "8" "RSASHA256" "2048" "no" "yes"
|
|
key_timings "KEY1" "none" "none" "none" "none" "none"
|
|
key_states "KEY1" "none" "none" "none" "none" "none"
|
|
|
|
key_properties "KEY2" "zsk" "2592000" "8" "RSASHA256" "1024" "yes" "no"
|
|
key_timings "KEY2" "none" "none" "none" "none" "none"
|
|
key_states "KEY2" "none" "none" "none" "none" "none"
|
|
|
|
key_properties "KEY3" "zsk" "16070400" "8" "RSASHA256" "2000" "yes" "no"
|
|
key_timings "KEY3" "none" "none" "none" "none" "none"
|
|
key_states "KEY3" "none" "none" "none" "none" "none"
|
|
|
|
ids=$(get_keyids "$DIR" "$ZONE" "$(key_get KEY1 ALG_NUM)")
|
|
for id in $ids; do
|
|
# There are three key files with the same algorithm.
|
|
# Check them until a match is found.
|
|
ret=0 && check_key "KEY1" "$id"
|
|
test "$ret" -eq 0 && continue
|
|
|
|
ret=0 && check_key "KEY2" "$id"
|
|
test "$ret" -eq 0 && continue
|
|
|
|
ret=0 && check_key "KEY3" "$id"
|
|
# If ret is still non-zero, non of the files matched.
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
done
|
|
# Turn error logs on again.
|
|
_log=1
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
|
ret=0
|
|
zone_properties "." "kasp" "default" "3600" "10.53.0.1"
|
|
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "none" "none" "none" "none" "none"
|
|
key_states "KEY1" "none" "none" "none" "none" "none"
|
|
$KEYGEN -k "$POLICY" "$ZONE" > "keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
|
|
lines=$(wc -l < "keygen.out.default.test$n")
|
|
test "$lines" -eq 1 || log_error "wrong number of keys created for policy default: $lines"
|
|
ids=$(get_keyids "$DIR" "$ZONE" "$(key_get KEY1 ALG_NUM)")
|
|
for id in $ids; do
|
|
check_key "KEY1" "$id"
|
|
done
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-keygen -k' (default policy) creates valid files ($n)"
|
|
ret=0
|
|
zone_properties "." "kasp" "default" "3600" "10.53.0.1"
|
|
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "none" "none" "none" "none" "none"
|
|
key_states "KEY1" "none" "none" "none" "none" "none"
|
|
$KEYGEN -k "$POLICY" "$ZONE" > "keygen.out.$POLICY.test$n" 2>/dev/null || ret=1
|
|
lines=$(wc -l < "keygen.out.$POLICY.test$n")
|
|
test "$lines" -eq 1 || log_error "wrong number of keys created for policy default: $lines"
|
|
ids=$(get_keyids "$DIR" "$ZONE" "$(key_get KEY1 ALG_NUM)")
|
|
for id in $ids; do
|
|
check_key "KEY1" "$id"
|
|
done
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
#
|
|
# dnssec-settime
|
|
#
|
|
|
|
# These test builds upon the latest created key with dnssec-keygen and uses the
|
|
# environment variables BASE_FILE, KEY_FILE, PRIVATE_FILE and STATE_FILE.
|
|
CMP_FILE="${BASE_FILE}.cmp"
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-settime' by default does not edit key state file ($n)"
|
|
ret=0
|
|
cp "$STATE_FILE" "$CMP_FILE"
|
|
$SETTIME -P +3600 "$BASE_FILE" > /dev/null || log_error "settime failed"
|
|
grep "; Publish: " "$KEY_FILE" > /dev/null || log_error "mismatch published in $KEY_FILE"
|
|
grep "Publish: " "$PRIVATE_FILE" > /dev/null || log_error "mismatch published in $PRIVATE_FILE"
|
|
$DIFF "$CMP_FILE" "$STATE_FILE" || log_error "unexpected file change in $STATE_FILE"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-settime -s' also sets publish time metadata and states in key state file ($n)"
|
|
ret=0
|
|
cp "$STATE_FILE" "$CMP_FILE"
|
|
now=$(date +%Y%m%d%H%M%S)
|
|
$SETTIME -s -P "$now" -g "omnipresent" -k "rumoured" "$now" -z "omnipresent" "$now" -r "rumoured" "$now" -d "hidden" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
|
|
key_timings "KEY1" "published" "none" "none" "none" "none"
|
|
key_states "KEY1" "omnipresent" "rumoured" "omnipresent" "rumoured" "hidden"
|
|
check_key "KEY1" "$id"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-settime -s' also unsets publish time metadata and states in key state file ($n)"
|
|
ret=0
|
|
cp "$STATE_FILE" "$CMP_FILE"
|
|
$SETTIME -s -P "none" -g "none" -k "none" "$now" -z "none" "$now" -r "none" "$now" -d "none" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
|
|
key_timings "KEY1" "none" "none" "none" "none" "none"
|
|
key_states "KEY1" "none" "none" "none" "none" "none"
|
|
check_key "KEY1" "$id"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
n=$((n+1))
|
|
echo_i "check that 'dnssec-settime -s' also sets active time metadata and states in key state file (uppercase) ($n)"
|
|
ret=0
|
|
cp "$STATE_FILE" "$CMP_FILE"
|
|
now=$(date +%Y%m%d%H%M%S)
|
|
$SETTIME -s -A "$now" -g "HIDDEN" -k "UNRETENTIVE" "$now" -z "UNRETENTIVE" "$now" -r "OMNIPRESENT" "$now" -d "OMNIPRESENT" "$now" "$BASE_FILE" > /dev/null || log_error "settime failed"
|
|
key_timings "KEY1" "none" "active" "none" "none" "none"
|
|
key_states "KEY1" "hidden" "unretentive" "unretentive" "omnipresent" "omnipresent"
|
|
check_key "KEY1" "$id"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
|
|
#
|
|
# named
|
|
#
|
|
#
|
|
# The NSEC record at the apex of the zone and its RRSIG records are
|
|
# added as part of the last step in signing a zone. We wait for the
|
|
# NSEC records to appear before proceeding with a counter to prevent
|
|
# infinite loops if there is a error.
|
|
#
|
|
n=$((n+1))
|
|
echo_i "waiting for kasp signing changes to take effect ($n)"
|
|
i=0
|
|
while [ $i -lt 30 ]
|
|
do
|
|
ret=0
|
|
while read -r zone
|
|
do
|
|
dig_with_opts "$zone" @10.53.0.3 nsec > "dig.out.ns3.test$n.$zone" || ret=1
|
|
grep "NS SOA" "dig.out.ns3.test$n.$zone" > /dev/null || ret=1
|
|
grep "$zone\..*IN.*RRSIG" "dig.out.ns3.test$n.$zone" > /dev/null || ret=1
|
|
done < ns3/zones
|
|
i=$((i+1))
|
|
if [ $ret = 0 ]; then break; fi
|
|
echo_i "waiting ... ($i)"
|
|
sleep 1
|
|
done
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
#
|
|
# Zone: default.kasp.
|
|
#
|
|
|
|
# Check the zone with default kasp policy has loaded and is signed.
|
|
zone_properties "ns3" "default.kasp" "default" "3600" "1" "10.53.0.3"
|
|
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
# The first key is immediately published and activated.
|
|
key_timings "KEY1" "published" "active" "none" "none" "none" "none"
|
|
# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait.
|
|
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
|
|
|
|
n=$((n+1))
|
|
echo_i "check key is created for zone ${ZONE} ($n)"
|
|
ret=0
|
|
ids=$(get_keyids "$DIR" "$ZONE" "$(key_get KEY1 ALG_NUM)")
|
|
for id in $ids; do
|
|
check_key "KEY1" "$id"
|
|
done
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Verify signed zone.
|
|
dnssec_verify "$ZONE"
|
|
|
|
# Test DNSKEY query.
|
|
qtype="DNSKEY"
|
|
n=$((n+1))
|
|
echo_i "check ${qtype} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" $qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${qtype}.*257.*.3.*${KEY1__ALG_NUM}" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${qtype} record in response"
|
|
lines=$(get_keys_which_signed $qtype "dig.out.$DIR.test$n" | wc -l)
|
|
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
|
|
get_keys_which_signed $qtype "dig.out.$DIR.test$n" | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Test SOA query.
|
|
qtype="SOA"
|
|
n=$((n+1))
|
|
echo_i "check ${qtype} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" $qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*${qtype}.*mname1\..*\." "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${qtype} record in response"
|
|
lines=$(get_keys_which_signed $qtype "dig.out.$DIR.test$n" | wc -l)
|
|
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
|
|
get_keys_which_signed $qtype "dig.out.$DIR.test$n" | grep "^${KEY_ID}$" > /dev/null || log_error "${qtype} RRset not signed with key ${KEY_ID}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Update zone.
|
|
n=$((n+1))
|
|
echo_i "check that we can update unsigned zone file and new record gets signed for zone ${ZONE} ($n)"
|
|
ret=0
|
|
cp "${DIR}/template2.db.in" "${DIR}/${ZONE}.db"
|
|
rndccmd 10.53.0.3 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
|
|
_log=0
|
|
i=0
|
|
while [ $i -lt 5 ]
|
|
do
|
|
ret=0
|
|
|
|
dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || log_error "dig a.${ZONE} A failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" > /dev/null || log_error "missing a.${ZONE} A record in response"
|
|
lines=$(get_keys_which_signed A "dig.out.$DIR.test$n.a" | wc -l)
|
|
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
|
|
get_keys_which_signed A "dig.out.$DIR.test$n.a" | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
|
|
|
|
dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n".d || log_error "dig d.${ZONE} A failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n".d > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n".d > /dev/null || log_error "missing d.${ZONE} A record in response"
|
|
lines=$(get_keys_which_signed A "dig.out.$DIR.test$n".d | wc -l)
|
|
test "$lines" -eq 1 || log_error "bad number ($lines) of RRSIG records in DNS response"
|
|
get_keys_which_signed A "dig.out.$DIR.test$n".d | grep "^${KEY_ID}$" > /dev/null || log_error "A RRset not signed with key ${KEY_ID}"
|
|
|
|
i=$((i+1))
|
|
if [ $ret = 0 ]; then break; fi
|
|
echo_i "waiting ... ($i)"
|
|
sleep 1
|
|
done
|
|
_log=1
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
#
|
|
# Zone: rsasha1.kasp.
|
|
#
|
|
zone_properties "ns3" "rsasha1.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "5" "RSASHA1" "2048" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "5" "RSASHA1" "2048" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "5" "RSASHA1" "2000" "yes" "no"
|
|
# The first keys are immediately published and activated.
|
|
# Because lifetime > 0, retired timing is also set.
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
key_timings "KEY3" "published" "active" "retired" "none" "none"
|
|
# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
|
|
# ZSK: DNSKEY, RRSIG (zsk) published.
|
|
key_states "KEY1" "omnipresent" "rumoured" "none" "rumoured" "hidden"
|
|
key_states "KEY2" "omnipresent" "rumoured" "rumoured" "none" "none"
|
|
key_states "KEY3" "omnipresent" "rumoured" "rumoured" "none" "none"
|
|
|
|
# Check keys for a configured zone. This verifies:
|
|
# 1. The right number of keys exist in the key pool ($1).
|
|
# 2. The right number of keys is active (always expect three keys).
|
|
# The algorithm expected is set with $2 (string) and $3 (number), and the
|
|
# expected sizes for the keys are set with $4 (ksk), $5 and $6 (zsk).
|
|
# A size set to 0 means the corresponding key (KEY1, KEY2 or KEY3) is not
|
|
# expected.
|
|
#
|
|
# It is expected that KEY1, KEY2 and KEY3 arrays are set correctly. Found key
|
|
# identifiers are stored in the right key array.
|
|
check_keys()
|
|
{
|
|
n=$((n+1))
|
|
echo_i "check keys are created for zone ${ZONE} ($n)"
|
|
ret=0
|
|
|
|
_key_algnum=$(key_get KEY1 ALG_NUM)
|
|
|
|
n=$((n+1))
|
|
echo_i "check number of keys with algorithm ${_key_algnum} for zone ${ZONE} in dir ${DIR} ($n)"
|
|
ret=0
|
|
_numkeys=$(get_keyids "$DIR" "$ZONE" "$_key_algnum" | wc -l)
|
|
test "$_numkeys" -eq "$NUM_KEYS" || log_error "bad number ($_numkeys) of key files for zone $ZONE (expected $NUM_KEYS)"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Temporarily don't log errors because we are searching multiple files.
|
|
_log=0
|
|
|
|
# Clear key ids.
|
|
key_set KEY1 ID 0
|
|
key_set KEY2 ID 0
|
|
key_set KEY3 ID 0
|
|
|
|
# Check key files.
|
|
_ids=$(get_keyids "$DIR" "$ZONE" "$_key_algnum")
|
|
for _id in $_ids; do
|
|
# There are three key files with the same algorithm.
|
|
# Check them until a match is found.
|
|
echo_i "check key $_id"
|
|
|
|
if [ "0" = "$(key_get KEY1 ID)" ] && [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
|
ret=0
|
|
check_key "KEY1" "$_id"
|
|
test "$ret" -eq 0 && key_set KEY1 "ID" "$KEY_ID" && continue
|
|
fi
|
|
if [ "0" = "$(key_get KEY2 ID)" ] && [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
|
ret=0
|
|
check_key "KEY2" "$_id"
|
|
test "$ret" -eq 0 && key_set KEY2 "ID" "$KEY_ID" && continue
|
|
fi
|
|
if [ "0" = "$(key_get KEY3 ID)" ] && [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
|
ret=0
|
|
check_key "KEY3" "$_id"
|
|
test "$ret" -eq 0 && key_set KEY3 ID "$KEY_ID" && continue
|
|
fi
|
|
|
|
# This may be an unused key.
|
|
ret=0 && key_unused "$_id"
|
|
test "$ret" -eq 0 && continue
|
|
|
|
# If ret is still non-zero, non of the files matched.
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+1))
|
|
done
|
|
|
|
# Turn error logs on again.
|
|
_log=1
|
|
|
|
ret=0
|
|
if [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
|
test "0" = "$(key_get KEY1 ID)" && log_error "No KEY1 found for zone ${ZONE}"
|
|
fi
|
|
if [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
|
test "0" = "$(key_get KEY2 ID)" && log_error "No KEY2 found for zone ${ZONE}"
|
|
fi
|
|
if [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
|
test "0" = "$(key_get KEY3 ID)" && log_error "No KEY3 found for zone ${ZONE}"
|
|
fi
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
}
|
|
|
|
# Check if RRset of type $1 in file $2 is signed with the right keys.
|
|
# The right keys are the ones that expect a signature and matches the role $3.
|
|
check_signatures() {
|
|
_qtype=$1
|
|
_file=$2
|
|
_role=$3
|
|
|
|
if [ "$_role" = "KSK" ]; then
|
|
_expect_type=EXPECT_KRRSIG
|
|
elif [ "$_role" = "ZSK" ]; then
|
|
_expect_type=EXPECT_ZRRSIG
|
|
fi
|
|
|
|
if [ "$(key_get KEY1 "$_expect_type")" = "yes" ] && [ "$(key_get KEY1 "$_role")" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY1 ID)$" > /dev/null || log_error "${_qtype} RRset not signed with key $(key_get KEY1 ID)"
|
|
elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY1 ID)$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key $(key_get KEY1 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY2 "$_expect_type")" = "yes" ] && [ "$(key_get KEY2 "$_role")" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY2 ID)$" > /dev/null || log_error "${_qtype} RRset not signed with key $(key_get KEY2 ID)"
|
|
elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY2 ID)$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key $(key_get KEY2 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY3 "$_expect_type")" = "yes" ] && [ "$(key_get KEY3 "$_role")" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY3 ID)$" > /dev/null || log_error "${_qtype} RRset not signed with key $(key_get KEY3 ID)"
|
|
elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
|
get_keys_which_signed "$_qtype" "$_file" | grep "^$(key_get KEY3 ID)$" > /dev/null && log_error "${_qtype} RRset signed unexpectedly with key $(key_get KEY3 ID)"
|
|
fi
|
|
}
|
|
|
|
response_has_cds_for_key() (
|
|
awk -v zone="${ZONE%%.}." \
|
|
-v ttl="${DNSKEY_TTL}" \
|
|
-v qtype="${_qtype}" \
|
|
-v keyid="$(key_get "${1}" ID)" \
|
|
-v keyalg="${_key_algnum}" \
|
|
-v hashalg="2" \
|
|
'BEGIN { ret=1; }
|
|
$1 == zone && $2 == ttl && $4 == qtype && $5 == keyid && $6 == keyalg && $7 == hashalg { ret=0; exit; }
|
|
END { exit ret; }' \
|
|
"$2"
|
|
)
|
|
|
|
# Test CDS and CDNSKEY publication.
|
|
check_cds() {
|
|
|
|
_qtype="CDS"
|
|
_key_algnum="$(key_get KEY1 ALG_NUM)"
|
|
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" $_qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
|
|
if [ "$(key_get KEY1 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DS)" = "omnipresent" ]; then
|
|
response_has_cds_for_key KEY1 "dig.out.$DIR.test$n" || log_error "missing ${_qtype} record in response for key $(key_get KEY1 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
|
response_has_cds_for_key KEY1 "dig.out.$DIR.test$n" && log_error "unexpected ${_qtype} record in response for key $(key_get KEY1 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY2 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DS)" = "omnipresent" ]; then
|
|
response_has_cds_for_key KEY2 "dig.out.$DIR.test$n" || log_error "missing ${_qtype} record in response for key $(key_get KEY2 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
|
response_has_cds_for_key KEY2 "dig.out.$DIR.test$n" && log_error "unexpected ${_qtype} record in response for key $(key_get KEY2 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY3 STATE_DS)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DS)" = "omnipresent" ]; then
|
|
response_has_cds_for_key KEY3 "dig.out.$DIR.test$n" || log_error "missing ${_qtype} record in response for key $(key_get KEY3 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
|
response_has_cds_for_key KEY3 "dig.out.$DIR.test$n" && log_error "unexpected ${_qtype} record in response for key $(key_get KEY3 ID)"
|
|
fi
|
|
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
}
|
|
|
|
# Test the apex of a configured zone. This checks that the SOA and DNSKEY
|
|
# RRsets are signed correctly and with the appropriate keys.
|
|
check_apex() {
|
|
|
|
# Test DNSKEY query.
|
|
_qtype="DNSKEY"
|
|
_key_algnum="$(key_get KEY1 ALG_NUM)"
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" $_qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
|
|
if [ "$(key_get KEY1 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY1 STATE_DNSKEY)" = "omnipresent" ]; then
|
|
grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${_qtype} record in response for key $(key_get KEY1 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
numkeys=$((numkeys+1))
|
|
elif [ "$(key_get KEY1 EXPECT)" = "yes" ]; then
|
|
grep "${ZONE}\.*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null && log_error "unexpected ${_qtype} record in response for key $(key_get KEY1 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY2 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY2 STATE_DNSKEY)" = "omnipresent" ]; then
|
|
grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${_qtype} record in response for key $(key_get KEY2 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
numkeys=$((numkeys+1))
|
|
elif [ "$(key_get KEY2 EXPECT)" = "yes" ]; then
|
|
grep "${ZONE}\.*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null && log_error "unexpected ${_qtype} record in response for key $(key_get KEY2 ID)"
|
|
fi
|
|
|
|
if [ "$(key_get KEY3 STATE_DNSKEY)" = "rumoured" ] || [ "$(key_get KEY3 STATE_DNSKEY)" = "omnipresent" ]; then
|
|
grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${_qtype} record in response for key $(key_get KEY3 ID)"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
numkeys=$((numkeys+1))
|
|
elif [ "$(key_get KEY3 EXPECT)" = "yes" ]; then
|
|
grep "${ZONE}\..*${DNSKEY_TTL}.*IN.*${_qtype}.*257.*.3.*${_key_algnum}" "dig.out.$DIR.test$n" > /dev/null && log_error "unexpected ${_qtype} record in response for key $(key_get KEY3 ID)"
|
|
fi
|
|
|
|
lines=$(get_keys_which_signed $_qtype "dig.out.$DIR.test$n" | wc -l)
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "KSK"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Test SOA query.
|
|
_qtype="SOA"
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" $_qtype > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*${DEFAULT_TTL}.*IN.*${_qtype}.*" "dig.out.$DIR.test$n" > /dev/null || log_error "missing ${_qtype} record in response"
|
|
lines=$(get_keys_which_signed $_qtype "dig.out.$DIR.test$n" | wc -l)
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "ZSK"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# Test CDS publication.
|
|
check_cds
|
|
}
|
|
|
|
# Test an RRset below the apex and verify it is signed correctly.
|
|
check_subdomain() {
|
|
_qtype="A"
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} a.${ZONE} rrset is signed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "a.$ZONE" "@${SERVER}" $_qtype > "dig.out.$DIR.test$n" || log_error "dig a.${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*${_qtype}.*10\.0\.0\.1" "dig.out.$DIR.test$n" > /dev/null || log_error "missing a.${ZONE} ${_qtype} record in response"
|
|
lines=$(get_keys_which_signed $_qtype "dig.out.$DIR.test$n" | wc -l)
|
|
check_signatures $_qtype "dig.out.$DIR.test$n" "ZSK"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
}
|
|
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: unsigned.kasp.
|
|
#
|
|
zone_properties "ns3" "unsigned.kasp" "none" "0" "0" "10.53.0.3"
|
|
key_clear "KEY1"
|
|
key_clear "KEY2"
|
|
key_clear "KEY3"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
#
|
|
# Zone: inherit.kasp.
|
|
#
|
|
zone_properties "ns3" "inherit.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "5" "RSASHA1" "2048" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "5" "RSASHA1" "2048" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "5" "RSASHA1" "2000" "yes" "no"
|
|
# The first keys are immediately published and activated.
|
|
# Because lifetime > 0, retired timing is also set.
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
key_timings "KEY3" "published" "active" "retired" "none" "none"
|
|
# KSK: DNSKEY, RRSIG (ksk) published. DS needs to wait.
|
|
# ZSK: DNSKEY, RRSIG (zsk) published.
|
|
key_states "KEY1" "omnipresent" "rumoured" "none" "rumoured" "hidden"
|
|
key_states "KEY2" "omnipresent" "rumoured" "rumoured" "none" "none"
|
|
key_states "KEY3" "omnipresent" "rumoured" "rumoured" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: dnssec-keygen.kasp.
|
|
#
|
|
zone_properties "ns3" "dnssec-keygen.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: some-keys.kasp.
|
|
#
|
|
zone_properties "ns3" "some-keys.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: legacy-keys.kasp.
|
|
#
|
|
zone_properties "ns3" "legacy-keys.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: pregenerated.kasp.
|
|
#
|
|
# There are more pregenerated keys than needed, hence the number of keys is
|
|
# six, not three.
|
|
zone_properties "ns3" "pregenerated.kasp" "rsasha1" "1234" "6" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: secondary.kasp.
|
|
#
|
|
zone_properties "ns3" "secondary.kasp" "rsasha1" "1234" "3" "10.53.0.3"
|
|
# KSK properties, timings and states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Update zone.
|
|
n=$((n+1))
|
|
echo_i "check that we correctly sign the zone after IXFR for zone ${ZONE} ($n)"
|
|
ret=0
|
|
cp ns2/secondary.kasp.db.in2 ns2/secondary.kasp.db
|
|
rndccmd 10.53.0.2 reload "$ZONE" > /dev/null || log_error "rndc reload zone ${ZONE} failed"
|
|
_log=0
|
|
i=0
|
|
while [ $i -lt 5 ]
|
|
do
|
|
ret=0
|
|
|
|
dig_with_opts "a.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.a" || log_error "dig a.${ZONE} A failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n.a" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "a.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.11" "dig.out.$DIR.test$n.a" > /dev/null || log_error "missing a.${ZONE} A record in response"
|
|
check_signatures $_qtype "dig.out.$DIR.test$n.a" "ZSK"
|
|
|
|
dig_with_opts "d.${ZONE}" "@${SERVER}" A > "dig.out.$DIR.test$n.d" || log_error "dig d.${ZONE} A failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n.d" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "d.${ZONE}\..*${DEFAULT_TTL}.*IN.*A.*10\.0\.0\.4" "dig.out.$DIR.test$n.d" > /dev/null || log_error "missing d.${ZONE} A record in response"
|
|
lines=$(get_keys_which_signed A "dig.out.$DIR.test$n.d" | wc -l)
|
|
check_signatures $_qtype "dig.out.$DIR.test$n.d" "ZSK"
|
|
|
|
i=$((i+1))
|
|
if [ $ret = 0 ]; then break; fi
|
|
echo_i "waiting ... ($i)"
|
|
sleep 1
|
|
done
|
|
_log=1
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
|
|
# TODO: we might want to test:
|
|
# - configuring a zone with too many active keys (should trigger retire).
|
|
# - configuring a zone with keys not matching the policy.
|
|
|
|
#
|
|
# Zone: rsasha1-nsec3.kasp.
|
|
#
|
|
zone_properties "ns3" "rsasha1-nsec3.kasp" "rsasha1-nsec3" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "7" "NSEC3RSASHA1" "2048" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "7" "NSEC3RSASHA1" "2048" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "7" "NSEC3RSASHA1" "2000" "yes" "no"
|
|
# key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: rsasha256.kasp.
|
|
#
|
|
zone_properties "ns3" "rsasha256.kasp" "rsasha256" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "8" "RSASHA256" "2048" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "8" "RSASHA256" "2048" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "8" "RSASHA256" "2000" "yes" "no"
|
|
# key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: rsasha512.kasp.
|
|
#
|
|
zone_properties "ns3" "rsasha512.kasp" "rsasha512" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "10" "RSASHA512" "2048" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "10" "RSASHA512" "2048" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "10" "RSASHA512" "2000" "yes" "no"
|
|
# key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: ecdsa256.kasp.
|
|
#
|
|
zone_properties "ns3" "ecdsa256.kasp" "ecdsa256" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
# key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
#
|
|
# Zone: ecdsa512.kasp.
|
|
#
|
|
zone_properties "ns3" "ecdsa384.kasp" "ecdsa384" "1234" "3" "10.53.0.3"
|
|
key_properties "KEY1" "ksk" "315360000" "14" "ECDSAP384SHA384" "384" "no" "yes"
|
|
key_properties "KEY2" "zsk" "157680000" "14" "ECDSAP384SHA384" "384" "yes" "no"
|
|
key_properties "KEY3" "zsk" "31536000" "14" "ECDSAP384SHA384" "384" "yes" "no"
|
|
# key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# TODO: ED25519 and ED448.
|
|
|
|
#
|
|
# Zone: expired-sigs.autosign.
|
|
#
|
|
zone_properties "ns3" "expired-sigs.autosign" "autosign" "300" "2" "10.53.0.3"
|
|
# Both KSK and ZSK stay OMNIPRESENT.
|
|
key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent"
|
|
key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
# Expect only two keys.
|
|
key_clear "KEY3"
|
|
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Verify all signatures have been refreshed.
|
|
check_rrsig_refresh() {
|
|
# Apex.
|
|
_qtypes="DNSKEY SOA NS NSEC"
|
|
for _qtype in $_qtypes
|
|
do
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
|
|
# If this exact RRSIG is also in the zone file it is not refreshed.
|
|
_rrsig=$(cat "rrsig.out.$ZONE.$_qtype")
|
|
grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
done
|
|
|
|
# Below apex.
|
|
_labels="a b c ns3"
|
|
for _label in $_labels;
|
|
do
|
|
_qtypes="A NSEC"
|
|
for _qtype in $_qtypes
|
|
do
|
|
n=$((n+1))
|
|
echo_i "check ${_label} ${_qtype} rrsig is refreshed correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "${_label}.${ZONE}" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${_label}.${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
|
|
_rrsig=$(cat "rrsig.out.$ZONE.$_qtype")
|
|
grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null && log_error "RRSIG (${_qtype}) not refreshed in zone ${ZONE}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
done
|
|
done
|
|
}
|
|
|
|
check_rrsig_refresh
|
|
|
|
#
|
|
# Zone: fresh-sigs.autosign.
|
|
#
|
|
zone_properties "ns3" "fresh-sigs.autosign" "autosign" "300" "2" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Verify signature reuse.
|
|
check_rrsig_reuse() {
|
|
# Apex.
|
|
_qtypes="NS NSEC"
|
|
for _qtype in $_qtypes
|
|
do
|
|
n=$((n+1))
|
|
echo_i "check ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "$ZONE" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
|
|
# If this exact RRSIG is also in the zone file it is not refreshed.
|
|
_rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < "rrsig.out.$ZONE.$_qtype")
|
|
grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
done
|
|
|
|
# Below apex.
|
|
_labels="a b c ns3"
|
|
for _label in $_labels;
|
|
do
|
|
_qtypes="A NSEC"
|
|
for _qtype in $_qtypes
|
|
do
|
|
n=$((n+1))
|
|
echo_i "check ${_label} ${_qtype} rrsig is reused correctly for zone ${ZONE} ($n)"
|
|
ret=0
|
|
dig_with_opts "${_label}.${ZONE}" "@${SERVER}" "$_qtype" > "dig.out.$DIR.test$n" || log_error "dig ${_label}.${ZONE} ${_qtype} failed"
|
|
grep "status: NOERROR" "dig.out.$DIR.test$n" > /dev/null || log_error "mismatch status in DNS response"
|
|
grep "${ZONE}\..*IN.*RRSIG.*${_qtype}.*${ZONE}" "dig.out.$DIR.test$n" > "rrsig.out.$ZONE.$_qtype" || log_error "missing RRSIG (${_qtype}) record in response"
|
|
_rrsig=$(awk '{print $5, $6, $7, $8, $9, $10, $11, $12, $13, $14;}' < "rrsig.out.$ZONE.$_qtype")
|
|
grep "${_rrsig}" "${DIR}/${ZONE}.db" > /dev/null || log_error "RRSIG (${_qtype}) not reused in zone ${ZONE}"
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
done
|
|
done
|
|
}
|
|
|
|
check_rrsig_reuse
|
|
|
|
#
|
|
# Zone: unfresh-sigs.autosign.
|
|
#
|
|
zone_properties "ns3" "unfresh-sigs.autosign" "autosign" "300" "2" "10.53.0.3"
|
|
# key_properties, key_timings and key_states same as above.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
check_rrsig_refresh
|
|
|
|
#
|
|
# Zone: zsk-missing.autosign.
|
|
#
|
|
zone_properties "ns3" "zsk-missing.autosign" "autosign" "300" "2" "10.53.0.3"
|
|
# KSK stays OMNIPRESENT.
|
|
key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent"
|
|
# key_properties, key_timings and key_states same as above.
|
|
# TODO
|
|
|
|
#
|
|
# Zone: zsk-retired.autosign.
|
|
#
|
|
zone_properties "ns3" "zsk-retired.autosign" "autosign" "300" "3" "10.53.0.3"
|
|
# KSK properties, timings and states same as above.
|
|
# The ZSK goal is set to HIDDEN but records stay OMNIPRESENT until the new ZSK
|
|
# is active.
|
|
key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
key_states "KEY2" "hidden" "omnipresent" "omnipresent" "none" "none"
|
|
# A new ZSK should be introduced, so expect a key with goal OMNIPRESENT,
|
|
# the DNSKEY introduced (RUMOURED) and the signatures HIDDEN.
|
|
key_properties "KEY3" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_timings "KEY3" "published" "active" "retired" "none" "none"
|
|
key_states "KEY3" "omnipresent" "rumoured" "hidden" "none" "none"
|
|
|
|
#
|
|
# Test dnssec-policy inheritance.
|
|
#
|
|
|
|
# These zones should be unsigned:
|
|
# ns2/unsigned.tld
|
|
# ns4/none.inherit.signed
|
|
# ns4/none.override.signed
|
|
# ns4/inherit.none.signed
|
|
# ns4/none.none.signed
|
|
# ns5/inherit.inherit.unsigned
|
|
# ns5/none.inherit.unsigned
|
|
# ns5/none.override.unsigned
|
|
# ns5/inherit.none.unsigned
|
|
# ns5/none.none.unsigned
|
|
key_clear "KEY1"
|
|
key_clear "KEY2"
|
|
key_clear "KEY3"
|
|
|
|
zone_properties "ns2" "unsigned.tld" "none" "0" "0" "10.53.0.2"
|
|
TSIG=""
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns4" "none.inherit.signed" "none" "0" "0" "10.53.0.4"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns4" "none.override.signed" "none" "0" "0" "10.53.0.4"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns4" "inherit.none.signed" "none" "0" "0" "10.53.0.4"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns4" "none.none.signed" "none" "0" "0" "10.53.0.4"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns5" "inherit.inherit.unsigned" "none" "0" "0" "10.53.0.5"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns5" "none.inherit.unsigned" "none" "0" "0" "10.53.0.5"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns5" "none.override.unsigned" "none" "0" "0" "10.53.0.5"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns5" "inherit.none.unsigned" "none" "0" "0" "10.53.0.5"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
zone_properties "ns5" "none.none.unsigned" "none" "0" "0" "10.53.0.5"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
|
|
# These zones should be signed with the default policy:
|
|
# ns2/signed.tld
|
|
# ns4/override.inherit.signed
|
|
# ns4/inherit.override.signed
|
|
# ns5/override.inherit.signed
|
|
# ns5/inherit.override.signed
|
|
key_properties "KEY1" "csk" "0" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "published" "active" "none" "none" "none" "none"
|
|
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
|
|
|
|
zone_properties "ns2" "signed.tld" "default" "3600" "1" "10.53.0.2"
|
|
TSIG=""
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns4" "override.inherit.signed" "default" "3600" "1" "10.53.0.4"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns4" "inherit.override.signed" "default" "3600" "1" "10.53.0.4"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns5" "override.inherit.unsigned" "default" "3600" "1" "10.53.0.5"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns5" "inherit.override.unsigned" "default" "3600" "1" "10.53.0.5"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# These zones should be signed with the test policy:
|
|
# ns4/inherit.inherit.signed
|
|
# ns4/override.override.signed
|
|
# ns4/override.none.signed
|
|
# ns5/override.override.unsigned
|
|
# ns5/override.none.unsigned
|
|
key_properties "KEY1" "csk" "0" "14" "ECDSAP384SHA384" "384" "yes" "yes"
|
|
key_timings "KEY1" "published" "active" "none" "none" "none" "none"
|
|
key_states "KEY1" "omnipresent" "rumoured" "rumoured" "rumoured" "hidden"
|
|
|
|
zone_properties "ns4" "inherit.inherit.signed" "test" "3600" "1" "10.53.0.4"
|
|
TSIG="hmac-sha1:sha1:$SHA1"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns4" "override.override.signed" "test" "3600" "1" "10.53.0.4"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns4" "override.none.signed" "test" "3600" "1" "10.53.0.4"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns5" "override.override.unsigned" "test" "3600" "1" "10.53.0.5"
|
|
TSIG="hmac-sha224:sha224:$SHA224"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
zone_properties "ns5" "override.none.unsigned" "test" "3600" "1" "10.53.0.5"
|
|
TSIG="hmac-sha256:sha256:$SHA256"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Clear TSIG.
|
|
TSIG=""
|
|
|
|
#
|
|
# Testing ZSK Pre-Publication rollover.
|
|
#
|
|
|
|
#
|
|
# Zone: step1.zsk-prepub.autosign.
|
|
#
|
|
zone_properties "ns3" "step1.zsk-prepub.autosign" "zsk-prepub" "3600" "2" "10.53.0.3"
|
|
# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
|
|
key_properties "KEY1" "ksk" "63072000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent"
|
|
key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
# Initially only two keys.
|
|
key_clear "KEY3"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
check_next_key_event() {
|
|
_expect=$1
|
|
|
|
n=$((n+1))
|
|
echo_i "check next key event for zone ${ZONE} ($n)"
|
|
ret=0
|
|
grep "zone ${ZONE}.*: next key event in .* seconds" "${DIR}/named.run" > "keyevent.out.$ZONE.test$n" || log_error "no next key event for zone ${ZONE}"
|
|
|
|
_time=$(awk '{print $10}' < "keyevent.out.$ZONE.test$n")
|
|
|
|
# The next key event time must within 60 seconds of the
|
|
# expected time.
|
|
_expectmin=$((_expect-60))
|
|
_expectmax=$((_expect+60))
|
|
|
|
test $_expectmin -le "$_time" || log_error "bad next key event time ${_time} for zone ${ZONE} (expect ${_expect})"
|
|
test $_expectmax -ge "$_time" || log_error "bad next key event time ${_time} for zone ${ZONE} (expect ${_expect})"
|
|
|
|
test "$ret" -eq 0 || echo_i "failed"
|
|
status=$((status+ret))
|
|
}
|
|
|
|
# Next key event is when the successor ZSK needs to be published. That is
|
|
# the ZSK lifetime - prepublication time. The prepublication time is DNSKEY
|
|
# TTL plus publish safety plus the zone propagation delay. For the
|
|
# zsk-prepub policy that means: 30d - 3600s + 1d + 1h = 2498400 seconds.
|
|
check_next_key_event 2498400
|
|
#
|
|
# Zone: step2.zsk-prepub.autosign.
|
|
#
|
|
zone_properties "ns3" "step2.zsk-prepub.autosign" "zsk-prepub" "3600" "3" "10.53.0.3"
|
|
# KSK (KEY1) doesn't change.
|
|
# ZSK (KEY2) remains active, no change in properties/timings/states.
|
|
# New ZSK (KEY3) is prepublished.
|
|
key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY3" "omnipresent" "rumoured" "hidden" "none" "none"
|
|
key_timings "KEY3" "published" "active" "retired" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor ZSK becomes OMNIPRESENT. That is the
|
|
# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
|
|
# the zsk-prepub policy, this means: 3600s + 1h + 1d = 93600 seconds.
|
|
check_next_key_event 93600
|
|
|
|
#
|
|
# Zone: step3.zsk-prepub.autosign.
|
|
#
|
|
zone_properties "ns3" "step3.zsk-prepub.autosign" "zsk-prepub" "3600" "3" "10.53.0.3"
|
|
# KSK (KEY1) doesn't change.
|
|
# ZSK (KEY2) properties and timing metadata same as above.
|
|
# ZSK (KEY2) no longer is actively signing, RRSIG state in UNRETENTIVE.
|
|
# New ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED.
|
|
key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY2" "hidden" "omnipresent" "unretentive" "none" "none"
|
|
|
|
key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_states "KEY3" "omnipresent" "omnipresent" "rumoured" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
# Subdomain still has good signatures of ZSK (KEY2)
|
|
key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when all the RRSIG records have been replaced with
|
|
# signatures of the new ZSK, in other words when ZRRSIG becomes OMNIPRESENT.
|
|
# That is Dsgn plus the maximum zone TTL plus the zone propagation delay plus
|
|
# retire-safety. For the zsk-prepub policy that means: 1w (because 2w validity
|
|
# and refresh within a week) + 1d + 1h + 2d = 10d1h = 867600 seconds.
|
|
check_next_key_event 867600
|
|
|
|
#
|
|
# Zone: step4.zsk-prepub.autosign.
|
|
#
|
|
zone_properties "ns3" "step4.zsk-prepub.autosign" "zsk-prepub" "3600" "3" "10.53.0.3"
|
|
# KSK (KEY1) doesn't change.
|
|
# ZSK (KEY2) properties and timing metadata same as above.
|
|
# ZSK (KEY2) DNSKEY is no longer needed.
|
|
# ZSK (KEY3) is now actively signing, RRSIG state in RUMOURED.
|
|
key_properties "KEY2" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY2" "hidden" "unretentive" "hidden" "none" "none"
|
|
key_properties "KEY3" "zsk" "2592000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_states "KEY3" "omnipresent" "omnipresent" "omnipresent" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the DNSKEY enters the HIDDEN state. This is the
|
|
# DNSKEY TTL plus zone propagation delay. For the zsk-prepub policy this is:
|
|
# 3600s + 1h = 7200s
|
|
check_next_key_event 7200
|
|
|
|
#
|
|
# Zone: step5.zsk-prepub.autosign.
|
|
#
|
|
zone_properties "ns3" "step5.zsk-prepub.autosign" "zsk-prepub" "3600" "3" "10.53.0.3"
|
|
# KSK (KEY1) doesn't change.
|
|
# ZSK (KEY2) properties and timing metadata same as above.
|
|
# ZSK (KEY3) DNSKEY is now completely HIDDEN and removed.
|
|
key_timings "KEY2" "published" "active" "retired" "none" "removed"
|
|
key_states "KEY2" "hidden" "hidden" "hidden" "none" "none"
|
|
# ZSK (KEY3) remains actively signing, staying in OMNIPRESENT.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the new successor needs to be published. This is the
|
|
# ZSK lifetime minus Iret minus Ipub minus DNSKEY TTL. For the zsk-prepub
|
|
# policy this is: 30d - 867600s - 93600s - 3600s = 1627200 seconds.
|
|
check_next_key_event 1627200
|
|
|
|
#
|
|
# Testing KSK Double-KSK rollover.
|
|
#
|
|
|
|
#
|
|
# Zone: step1.ksk-doubleksk.autosign.
|
|
#
|
|
zone_properties "ns3" "step1.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "2" "10.53.0.3"
|
|
# Both KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT.
|
|
key_properties "KEY1" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent"
|
|
key_properties "KEY2" "zsk" "31536000" "13" "ECDSAP256SHA256" "256" "yes" "no"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "none" "none"
|
|
# Initially only two keys.
|
|
key_clear "KEY3"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor KSK needs to be published. That is
|
|
# the KSK lifetime - prepublication time - DS registration delay. The
|
|
# prepublication time is DNSKEY TTL plus publish safety plus the zone
|
|
# propagation delay. For the ksk-doubleksk policy that means:
|
|
# 60d - (1d3h) - (1d) = 5000400 seconds.
|
|
check_next_key_event 5000400
|
|
|
|
#
|
|
# Zone: step2.ksk-doubleksk.autosign.
|
|
#
|
|
zone_properties "ns3" "step2.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" "10.53.0.3"
|
|
# ZSK (KEY2) doesn't change.
|
|
# KSK (KEY1) remains active, no change in properties/timings/states.
|
|
# New KSK (KEY3) is prepublished (and signs DNSKEY RRset).
|
|
key_properties "KEY3" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY3" "omnipresent" "rumoured" "none" "rumoured" "hidden"
|
|
key_timings "KEY3" "published" "active" "retired" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor KSK becomes OMNIPRESENT. That is the
|
|
# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
|
|
# the ksk-doubleksk policy, this means: 7200s + 1h + 1d = 97200 seconds.
|
|
check_next_key_event 97200
|
|
|
|
#
|
|
# Zone: step3.ksk-doubleksk.autosign.
|
|
#
|
|
zone_properties "ns3" "step3.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" "10.53.0.3"
|
|
# ZSK (KEY2) doesn't change.
|
|
# KSK (KEY1) DS will be removed, so it is UNRETENTIVE.
|
|
key_states "KEY1" "hidden" "omnipresent" "none" "omnipresent" "unretentive"
|
|
# New KSK (KEY3) has its DS submitted.
|
|
key_states "KEY3" "omnipresent" "omnipresent" "none" "omnipresent" "rumoured"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the predecessor DS has been replaced with the
|
|
# successor DS and enough time has passed such that the all validators that
|
|
# have this DS RRset cached only know about the successor DS. This is the
|
|
# registration delay plus the retire interval, which is the parent
|
|
# propagation delay plus the DS TTL plus the retire-safety. For the
|
|
# ksk-double-ksk policy this means: 1d + 1h + 3600s + 2d = 3d2h =
|
|
# 266400 seconds.
|
|
check_next_key_event 266400
|
|
|
|
#
|
|
# Zone: step4.ksk-doubleksk.autosign.
|
|
#
|
|
zone_properties "ns3" "step4.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" "10.53.0.3"
|
|
# ZSK (KEY2) doesn't change.
|
|
# KSK (KEY1) DNSKEY can be removed.
|
|
key_properties "KEY1" "ksk" "5184000" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "unretentive" "none" "unretentive" "hidden"
|
|
# New KSK (KEY3) DS is now OMNIPRESENT.
|
|
key_states "KEY3" "omnipresent" "omnipresent" "none" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the DNSKEY enters the HIDDEN state. This is the
|
|
# DNSKEY TTL plus zone propagation delay. For the ksk-doubleksk policy this is:
|
|
# 7200s + 1h = 10800s
|
|
check_next_key_event 10800
|
|
|
|
#
|
|
# Zone: step5.ksk-doubleksk.autosign.
|
|
#
|
|
zone_properties "ns3" "step5.ksk-doubleksk.autosign" "ksk-doubleksk" "7200" "3" "10.53.0.3"
|
|
# ZSK (KEY2) doesn't change.
|
|
# KSK (KEY1) DNSKEY is now HIDDEN.
|
|
key_states "KEY1" "hidden" "hidden" "none" "hidden" "hidden"
|
|
# New KSK (KEY3) stays OMNIPRESENT.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the new successor needs to be published. This is the
|
|
# KSK lifetime minus Ipub minus Dreg minus Iret minus DNSKEY TTL. For the
|
|
# ksk-doubleksk this is: 60d - 1d3h - 1d - 2d2h - 2h =
|
|
# 5184000 - 97200 - 86400 - 180000 - 7200 = 4813200 seconds.
|
|
check_next_key_event 4813200
|
|
|
|
#
|
|
# Testing CSK key rollover (1).
|
|
#
|
|
|
|
#
|
|
# Zone: step1.csk-roll.autosign.
|
|
#
|
|
zone_properties "ns3" "step1.csk-roll.autosign" "csk-roll" "3600" "1" "10.53.0.3"
|
|
# The CSK (KEY1) starts in OMNIPRESENT.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
# Initially only one key.
|
|
key_clear "KEY2"
|
|
key_clear "KEY3"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor CSK needs to be published. That is
|
|
# the CSK lifetime - prepublication time - DS registration delay. The
|
|
# prepublication time is DNSKEY TTL plus publish safety plus the zone
|
|
# propagation delay. For the csk-roll policy that means:
|
|
# 6mo - 1d - 3h = 15973200 seconds.
|
|
check_next_key_event 15973200
|
|
|
|
#
|
|
# Zone: step2.csk-roll.autosign.
|
|
#
|
|
# Set key properties for testing keys.
|
|
zone_properties "ns3" "step2.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# CSK (KEY1) remains active, no change in properties/timings/states.
|
|
# New CSK (KEY2) is prepublished (and signs DNSKEY RRset).
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY2" "omnipresent" "rumoured" "hidden" "rumoured" "hidden"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor CSK becomes OMNIPRESENT. That is the
|
|
# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
|
|
# the csk-roll policy, this means 3 hours = 10800 seconds.
|
|
check_next_key_event 10800
|
|
|
|
#
|
|
# Zone: step3.csk-roll.autosign.
|
|
#
|
|
# Set key properties for testing keys.
|
|
zone_properties "ns3" "step3.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# CSK (KEY1) DS and ZRRSIG will be removed, so it is UNRETENTIVE.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY1" "hidden" "omnipresent" "unretentive" "omnipresent" "unretentive"
|
|
# New CSK (KEY2) has its DS submitted, and is signing, so the DS and ZRRSIG
|
|
# are in RUMOURED state.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "rumoured" "omnipresent" "rumoured"
|
|
check_keys
|
|
check_apex
|
|
# Subdomain still has good signatures of old CSK (KEY1)
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the predecessor DS has been replaced with the
|
|
# successor DS and enough time has passed such that the all validators that
|
|
# have this DS RRset cached only know about the successor DS. This is the
|
|
# registration delay plus the retire interval, which is the parent
|
|
# propagation delay plus the DS TTL plus the retire-safety. For the
|
|
# csk-roll policy this means: 1d + 1h + 1h + 2h = 1d4h = 100800 seconds.
|
|
check_next_key_event 100800
|
|
|
|
#
|
|
# Zone: step4.csk-roll.autosign.
|
|
#
|
|
zone_properties "ns3" "step4.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) DS is hidden. We still need to keep the DNSKEY public
|
|
# but can remove the KRRSIG records.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "omnipresent" "unretentive" "unretentive" "hidden"
|
|
# The new CSK (KEY2) DS is now OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "rumoured" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the KRRSIG enters the HIDDEN state. This is the
|
|
# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
|
|
# 1h + 1h = 7200 seconds.
|
|
check_next_key_event 7200
|
|
|
|
#
|
|
# Zone: step5.csk-roll.autosign.
|
|
#
|
|
zone_properties "ns3" "step5.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) KRRSIG records are now all hidden.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "omnipresent" "unretentive" "hidden" "hidden"
|
|
# The new CSK (KEY2) state does not change.
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the DNSKEY can be removed. This is when all ZRRSIG
|
|
# records have been replaced with signatures of the new CSK. We have
|
|
# calculated the interval to be 26d3h of which 1d4h (Dreg + Iret(KSK)) plus
|
|
# 2h (DNSKEY TTL + Dprp) have already passed. So next key event is in
|
|
# 26d3h - 1d4h - 2h = 597h = 2149200 seconds.
|
|
check_next_key_event 2149200
|
|
|
|
#
|
|
# Zone: step6.csk-roll.autosign.
|
|
#
|
|
zone_properties "ns3" "step6.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) DNSKEY can be removed.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "unretentive" "hidden" "hidden" "hidden"
|
|
# The new CSK (KEY2) is now fully OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the DNSKEY enters the HIDDEN state. This is the
|
|
# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
|
|
# 1h + 1h = 7200 seconds.
|
|
check_next_key_event 7200
|
|
|
|
#
|
|
# Zone: step7.csk-roll.autosign.
|
|
#
|
|
zone_properties "ns3" "step7.csk-roll.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) is now completely HIDDEN.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "hidden" "hidden" "hidden" "hidden"
|
|
# The new CSK (KEY2) is now fully OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the new successor needs to be published. This is the
|
|
# CSK lifetime minus Ipub minus Dreg minus Iret minus DNSKEY TTL minus zone
|
|
# propagation delay. For the csk-roll this is:
|
|
# 6mo - 3h - 1d - 26d3h - 1h - 1h = 6mo - 27d8h = 13708800 seconds.
|
|
check_next_key_event 13708800
|
|
|
|
#
|
|
# Testing CSK key rollover (1).
|
|
#
|
|
|
|
#
|
|
# Zone: step1.csk-roll2.autosign.
|
|
#
|
|
zone_properties "ns3" "step1.csk-roll2.autosign" "csk-roll2" "3600" "1" "10.53.0.3"
|
|
# The CSK (KEY1) starts in OMNIPRESENT.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_timings "KEY1" "published" "active" "retired" "none" "none"
|
|
key_states "KEY1" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
# Initially only one key.
|
|
key_clear "KEY2"
|
|
key_clear "KEY3"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor CSK needs to be published. That is
|
|
# the CSK lifetime - prepublication time - DS registration delay. The
|
|
# prepublication time is DNSKEY TTL plus publish safety plus the zone
|
|
# propagation delay. For the csk-roll2 policy that means:
|
|
# 6mo - 3h - 1w = 15454800 seconds.
|
|
check_next_key_event 15454800
|
|
|
|
#
|
|
# Zone: step2.csk-roll2.autosign.
|
|
#
|
|
# Set key properties for testing keys.
|
|
zone_properties "ns3" "step2.csk-roll2.autosign" "csk-roll2" "3600" "2" "10.53.0.3"
|
|
# CSK (KEY1) remains active, no change in properties/timings/states.
|
|
# New CSK (KEY2) is prepublished (and signs DNSKEY RRset).
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY2" "omnipresent" "rumoured" "hidden" "rumoured" "hidden"
|
|
key_timings "KEY2" "published" "active" "retired" "none" "none"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the successor CSK becomes OMNIPRESENT. That is the
|
|
# DNSKEY TTL plus the zone propagation delay, plus the publish-safety. For
|
|
# the csk-roll2 policy, this means 3 hours = 10800 seconds.
|
|
check_next_key_event 10800
|
|
|
|
#
|
|
# Zone: step3.csk-roll2.autosign.
|
|
#
|
|
# Set key properties for testing keys.
|
|
zone_properties "ns3" "step3.csk-roll2.autosign" "csk-roll2" "3600" "2" "10.53.0.3"
|
|
# CSK (KEY1) DS and ZRRSIG will be removed, so it is UNRETENTIVE.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY1" "hidden" "omnipresent" "unretentive" "omnipresent" "unretentive"
|
|
# New CSK (KEY2) has its DS submitted, and is signing, so the DS and ZRRSIG
|
|
# are in RUMOURED state.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "rumoured" "omnipresent" "rumoured"
|
|
check_keys
|
|
check_apex
|
|
# Subdomain still has good signatures of old CSK (KEY1)
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the predecessor ZRRSIG records have been replaced
|
|
# with that of the successor and enough time has passed such that the all
|
|
# validators that have such signed RRsets in cache only know about the
|
|
# successor signatures. This is the retire interval: Dsgn plus the
|
|
# maximum zone TTL plus the zone propagation delay plus retire-safety. For the
|
|
# csk-roll2 policy that means: 12h (because 1d validity and refresh within
|
|
# 12 hours) + 1d + 1h + 1h = 38h = 136800 seconds.
|
|
check_next_key_event 136800
|
|
|
|
#
|
|
# Zone: step4.csk-roll2.autosign.
|
|
#
|
|
zone_properties "ns3" "step4.csk-roll2.autosign" "csk-roll2" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) ZRRSIG is now HIDDEN.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "yes"
|
|
key_states "KEY1" "hidden" "omnipresent" "hidden" "omnipresent" "unretentive"
|
|
# The new CSK (KEY2) ZRRSIG is now OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "rumoured"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the predecessor DS has been replaced with the
|
|
# successor DS and enough time has passed such that the all validators that
|
|
# have this DS RRset cached only know about the successor DS. This is the
|
|
# registration delay plus the retire interval, which is the parent
|
|
# propagation delay plus the DS TTL plus the retire-safety. For the
|
|
# csk-roll2 policy this means: 1w + 1h + 1h + 1h = 171h = 615600 seconds.
|
|
# However, 136800 seconds have passed already, so 478800 seconds left.
|
|
check_next_key_event 478800
|
|
|
|
#
|
|
# Zone: step5.csk-roll2.autosign.
|
|
#
|
|
zone_properties "ns3" "step5.csk-roll2.autosign" "csk-roll2" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) DNSKEY can be removed.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "unretentive" "hidden" "unretentive" "hidden"
|
|
# The new CSK (KEY2) is now fully OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the DNSKEY enters the HIDDEN state. This is the
|
|
# DNSKEY TTL plus zone propagation delay. For the csk-roll policy this is:
|
|
# 1h + 1h = 7200 seconds.
|
|
check_next_key_event 7200
|
|
|
|
#
|
|
# Zone: step6.csk-roll2.autosign.
|
|
#
|
|
zone_properties "ns3" "step6.csk-roll2.autosign" "csk-roll" "3600" "2" "10.53.0.3"
|
|
# The old CSK (KEY1) is now completely HIDDEN.
|
|
key_properties "KEY1" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "no" "no"
|
|
key_states "KEY1" "hidden" "hidden" "hidden" "hidden" "hidden"
|
|
# The new CSK (KEY2) is now fully OMNIPRESENT.
|
|
key_properties "KEY2" "csk" "16070400" "13" "ECDSAP256SHA256" "256" "yes" "yes"
|
|
key_states "KEY2" "omnipresent" "omnipresent" "omnipresent" "omnipresent" "omnipresent"
|
|
check_keys
|
|
check_apex
|
|
check_subdomain
|
|
dnssec_verify
|
|
|
|
# Next key event is when the new successor needs to be published.
|
|
check_next_key_event 14684400
|
|
|
|
echo_i "exit status: $status"
|
|
[ $status -eq 0 ] || exit 1
|