From 62adf9957f8cdde85737ac9b299a950dd3cd9655 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 19 Mar 2025 11:35:18 +0100 Subject: [PATCH 1/4] Convert policy changes tests to pytest These test cases involve a reconfiguration. The first one is a zone that changes from dynamic to inline-signing. The others are tests that key lifetimes are updated correctly after changing them. (cherry picked from commit de3c0970eb0ef9dea6e18a26f04b2c2810b68da0) --- bin/tests/system/kasp/ns6/named.conf.in | 32 ----- bin/tests/system/kasp/ns6/named2.conf.in | 32 ----- bin/tests/system/kasp/ns6/setup.sh | 8 -- bin/tests/system/kasp/tests.sh | 121 ----------------- bin/tests/system/rollover/ns6/csk1.conf.j2 | 30 +++++ bin/tests/system/rollover/ns6/csk2.conf.j2 | 30 +++++ bin/tests/system/rollover/ns6/kasp.conf.j2 | 50 +++++++ bin/tests/system/rollover/ns6/named.conf.j2 | 78 +++++++++++ bin/tests/system/rollover/ns6/named2.conf.j2 | 77 +++++++++++ bin/tests/system/rollover/ns6/setup.sh | 36 +++++ bin/tests/system/rollover/ns6/template.db.in | 27 ++++ bin/tests/system/rollover/setup.sh | 4 + bin/tests/system/rollover/tests_rollover.py | 131 +++++++++++++++++++ 13 files changed, 463 insertions(+), 193 deletions(-) create mode 100644 bin/tests/system/rollover/ns6/csk1.conf.j2 create mode 100644 bin/tests/system/rollover/ns6/csk2.conf.j2 create mode 100644 bin/tests/system/rollover/ns6/kasp.conf.j2 create mode 100644 bin/tests/system/rollover/ns6/named.conf.j2 create mode 100644 bin/tests/system/rollover/ns6/named2.conf.j2 create mode 100644 bin/tests/system/rollover/ns6/setup.sh create mode 100644 bin/tests/system/rollover/ns6/template.db.in diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in index b8d36dc6e4..f77069fdb3 100644 --- a/bin/tests/system/kasp/ns6/named.conf.in +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -44,14 +44,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* This zone switch from dynamic to inline-signing. */ -zone "dynamic2inline.kasp" { - type primary; - file "dynamic2inline.kasp.db"; - allow-update { any; }; - dnssec-policy "default"; -}; - /* These zones are going insecure. */ zone "step1.going-insecure.kasp" { type primary; @@ -99,27 +91,3 @@ zone example { file "example.db"; dnssec-policy modified; }; - -zone longer-lifetime { - type primary; - file "longer-lifetime.db"; - dnssec-policy short-lifetime; -}; - -zone shorter-lifetime { - type primary; - file "shorter-lifetime.db"; - dnssec-policy long-lifetime; -}; - -zone limit-lifetime { - type primary; - file "limit-lifetime.db"; - dnssec-policy unlimited-lifetime; -}; - -zone unlimit-lifetime { - type primary; - file "unlimit-lifetime.db"; - dnssec-policy short-lifetime; -}; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in index 0c9d6b0a89..88e67dc371 100644 --- a/bin/tests/system/kasp/ns6/named2.conf.in +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -43,14 +43,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* This zone switch from dynamic to inline-signing. */ -zone "dynamic2inline.kasp" { - type primary; - file "dynamic2inline.kasp.db"; - allow-update { any; }; - dnssec-policy "default"; -}; - /* Zones for testing going insecure. */ zone "step1.going-insecure.kasp" { type primary; @@ -177,27 +169,3 @@ zone example { file "example.db"; dnssec-policy modified; }; - -zone longer-lifetime { - type primary; - file "longer-lifetime.db"; - dnssec-policy long-lifetime; -}; - -zone shorter-lifetime { - type primary; - file "shorter-lifetime.db"; - dnssec-policy short-lifetime; -}; - -zone limit-lifetime { - type primary; - file "limit-lifetime.db"; - dnssec-policy short-lifetime; -}; - -zone unlimit-lifetime { - type primary; - file "unlimit-lifetime.db"; - dnssec-policy unlimited-lifetime; -}; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh index fcdabad355..6f963e33d0 100644 --- a/bin/tests/system/kasp/ns6/setup.sh +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -29,11 +29,6 @@ R="RUMOURED" O="OMNIPRESENT" U="UNRETENTIVE" -for zn in shorter-lifetime longer-lifetime limit-lifetime unlimit-lifetime; do - setup $zn - cp template.db.in $zonefile -done - # The child zones (step1, step2) beneath these zones represent the various # steps of unsigning a zone. for zn in going-insecure.kasp going-insecure-dynamic.kasp; do @@ -420,6 +415,3 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in # echo "example" >>zones cp example.db.in example.db - -setup "dynamic2inline.kasp" -cp template.db.in $zonefile diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 8a64d042bb..069f8a32b0 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -276,93 +276,6 @@ csk_rollover_predecessor_keytimes() { [ "$Lcsk" = 0 ] || set_retired_removed "KEY1" "${Lcsk}" "${IretCSK}" } -# Test dynamic zones that switch to inline-signing. -set_zone "dynamic2inline.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# The CSK is rumoured. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Test key lifetime changes -set_keytimes_lifetime_update() { - if [ $1 -eq 0 ]; then - set_keytime "KEY1" "RETIRED" "none" - set_keytime "KEY1" "REMOVED" "none" - else - active=$(key_get KEY1 ACTIVE) - set_addkeytime "KEY1" "RETIRED" "${active}" $1 - # The key is removed after the retire time plus max-zone-ttl (1d), - # sign delay (9d), zone propagation delay (5m), retire safety (1h) = - # 777600 + 86400 + 300 + 3600 = 867900 - retired=$(key_get KEY1 RETIRED) - set_addkeytime "KEY1" "REMOVED" "${retired}" 867900 - fi -} - -check_key_lifetime() { - zone=$1 - policy=$2 - lifetime=$3 - - set_zone "$zone" - set_policy "$policy" "1" "3600" - set_server "ns6" "10.53.0.6" - # Key properties. - key_clear "KEY1" - set_keyrole "KEY1" "csk" - set_keylifetime "KEY1" "$lifetime" - set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" - set_keysigning "KEY1" "yes" - set_zonesigning "KEY1" "yes" - key_clear "KEY2" - key_clear "KEY3" - key_clear "KEY4" - - # The CSK is rumoured. - set_keystate "KEY1" "GOAL" "omnipresent" - set_keystate "KEY1" "STATE_DNSKEY" "rumoured" - set_keystate "KEY1" "STATE_KRRSIG" "rumoured" - set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" - set_keystate "KEY1" "STATE_DS" "hidden" - check_keys - - # Key timings. - set_keytimes_csk_policy - set_keytimes_lifetime_update $lifetime - - # Variuous checks. - check_keytimes - check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - check_apex - check_subdomain - dnssec_verify -} -check_key_lifetime "shorter-lifetime" "long-lifetime" "31536000" -check_key_lifetime "longer-lifetime" "short-lifetime" "16070400" -check_key_lifetime "limit-lifetime" "unlimited-lifetime" "0" -check_key_lifetime "unlimit-lifetime" "short-lifetime" "16070400" - # # Testing algorithm rollover. # @@ -668,40 +581,6 @@ wait_for_done_signing() { status=$((status + ret)) } -# Test dynamic zones that switch to inline-signing. -set_zone "dynamic2inline.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# The CSK is rumoured. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "rumoured" -set_keystate "KEY1" "STATE_KRRSIG" "rumoured" -set_keystate "KEY1" "STATE_ZRRSIG" "rumoured" -set_keystate "KEY1" "STATE_DS" "hidden" -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Test key lifetime updates. -check_key_lifetime "shorter-lifetime" "short-lifetime" "16070400" -check_key_lifetime "longer-lifetime" "long-lifetime" "31536000" -check_key_lifetime "limit-lifetime" "short-lifetime" "16070400" -check_key_lifetime "unlimit-lifetime" "unlimited-lifetime" "0" - # # Testing going insecure. # diff --git a/bin/tests/system/rollover/ns6/csk1.conf.j2 b/bin/tests/system/rollover/ns6/csk1.conf.j2 new file mode 100644 index 0000000000..a5ff042db8 --- /dev/null +++ b/bin/tests/system/rollover/ns6/csk1.conf.j2 @@ -0,0 +1,30 @@ +/* + * 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 "csk-algoroll" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + csk lifetime unlimited algorithm rsasha256; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/rollover/ns6/csk2.conf.j2 b/bin/tests/system/rollover/ns6/csk2.conf.j2 new file mode 100644 index 0000000000..6d290c3c32 --- /dev/null +++ b/bin/tests/system/rollover/ns6/csk2.conf.j2 @@ -0,0 +1,30 @@ +/* + * 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 "csk-algoroll" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; diff --git a/bin/tests/system/rollover/ns6/kasp.conf.j2 b/bin/tests/system/rollover/ns6/kasp.conf.j2 new file mode 100644 index 0000000000..38a1784acf --- /dev/null +++ b/bin/tests/system/rollover/ns6/kasp.conf.j2 @@ -0,0 +1,50 @@ +/* + * 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 "unlimited-lifetime" { + keys { + csk lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + }; +}; +dnssec-policy "short-lifetime" { + keys { + csk lifetime P6M algorithm @DEFAULT_ALGORITHM@; + }; +}; + +dnssec-policy "long-lifetime" { + keys { + csk lifetime P1Y algorithm @DEFAULT_ALGORITHM@; + }; +}; + +{% if RSASHA1_SUPPORTED == "1" %} +dnssec-policy "rsasha1" { + signatures-refresh P5D; + signatures-validity 30d; + signatures-validity-dnskey 30d; + + keys { + ksk lifetime unlimited algorithm rsasha1; + zsk lifetime unlimited algorithm rsasha1; + }; + + dnskey-ttl 1h; + publish-safety PT1H; + retire-safety 2h; + zone-propagation-delay 3600; + max-zone-ttl 6h; + parent-propagation-delay pt1h; + parent-ds-ttl 7200; +}; +{% endif %} diff --git a/bin/tests/system/rollover/ns6/named.conf.j2 b/bin/tests/system/rollover/ns6/named.conf.j2 new file mode 100644 index 0000000000..03432878fe --- /dev/null +++ b/bin/tests/system/rollover/ns6/named.conf.j2 @@ -0,0 +1,78 @@ +/* + * 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. + */ + +// NS6 + +include "kasp.conf"; +include "csk1.conf"; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + key-directory "."; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +/* This zone switch from dynamic to inline-signing. */ +zone "dynamic2inline.kasp" { + type primary; + file "dynamic2inline.kasp.db"; + allow-update { any; }; + dnssec-policy "default"; +}; + +/* Lifetime changes. */ +zone longer-lifetime { + type primary; + file "longer-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone shorter-lifetime { + type primary; + file "shorter-lifetime.db"; + dnssec-policy long-lifetime; +}; + +zone limit-lifetime { + type primary; + file "limit-lifetime.db"; + dnssec-policy unlimited-lifetime; +}; + +zone unlimit-lifetime { + type primary; + file "unlimit-lifetime.db"; + dnssec-policy short-lifetime; +}; diff --git a/bin/tests/system/rollover/ns6/named2.conf.j2 b/bin/tests/system/rollover/ns6/named2.conf.j2 new file mode 100644 index 0000000000..b0cb1b6949 --- /dev/null +++ b/bin/tests/system/rollover/ns6/named2.conf.j2 @@ -0,0 +1,77 @@ +/* + * 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. + */ + +// NS6 + +include "kasp.conf"; +include "csk2.conf"; + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; + dnssec-validation no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../_common/root.hint.blackhole"; +}; + +/* This zone switch from dynamic to inline-signing. */ +zone "dynamic2inline.kasp" { + type primary; + file "dynamic2inline.kasp.db"; + allow-update { any; }; + dnssec-policy "default"; +}; + +/* Lifetime changes. */ +zone longer-lifetime { + type primary; + file "longer-lifetime.db"; + dnssec-policy long-lifetime; +}; + +zone shorter-lifetime { + type primary; + file "shorter-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone limit-lifetime { + type primary; + file "limit-lifetime.db"; + dnssec-policy short-lifetime; +}; + +zone unlimit-lifetime { + type primary; + file "unlimit-lifetime.db"; + dnssec-policy unlimited-lifetime; +}; diff --git a/bin/tests/system/rollover/ns6/setup.sh b/bin/tests/system/rollover/ns6/setup.sh new file mode 100644 index 0000000000..f8ab6048e9 --- /dev/null +++ b/bin/tests/system/rollover/ns6/setup.sh @@ -0,0 +1,36 @@ +#!/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 + +echo_i "ns6/setup.sh" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" +} + +# Make lines shorter by storing key states in environment variables. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" + +for zn in dynamic2inline.kasp shorter-lifetime longer-lifetime limit-lifetime \ + unlimit-lifetime; do + setup $zn + cp template.db.in $zonefile +done diff --git a/bin/tests/system/rollover/ns6/template.db.in b/bin/tests/system/rollover/ns6/template.db.in new file mode 100644 index 0000000000..f1d8b94e5a --- /dev/null +++ b/bin/tests/system/rollover/ns6/template.db.in @@ -0,0 +1,27 @@ +; 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. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns6 +ns6 A 10.53.0.6 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/rollover/setup.sh b/bin/tests/system/rollover/setup.sh index c72052cf48..56a8979855 100644 --- a/bin/tests/system/rollover/setup.sh +++ b/bin/tests/system/rollover/setup.sh @@ -20,3 +20,7 @@ set -e cd ns3 $SHELL setup.sh ) +( + cd ns6 + $SHELL setup.sh +) diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index bbfb473891..2d9f8275bb 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -10,6 +10,7 @@ # information regarding copyright ownership. import os +import shutil from datetime import timedelta @@ -1256,3 +1257,133 @@ def test_rollover_csk_roll2(servers): for step in steps: check_rollover_step(server, config, policy, step) + + +def test_rollover_policy_changes(servers): + server = servers["ns6"] + cdss = ["CDNSKEY", "CDS (SHA-256)"] + alg = os.environ["DEFAULT_ALGORITHM_NUMBER"] + size = os.environ["DEFAULT_BITS"] + + default_config = { + "dnskey-ttl": timedelta(hours=1), + "ds-ttl": timedelta(days=1), + "max-zone-ttl": timedelta(days=1), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "purge-keys": timedelta(days=90), + "retire-safety": timedelta(hours=1), + "signatures-refresh": timedelta(days=5), + "signatures-validity": timedelta(days=14), + "zone-propagation-delay": timedelta(seconds=300), + } + + start_time = KeyTimingMetadata.now() + + # Test dynamic zones that switch to inline-signing. + isctest.log.info("check dynamic zone that switches to inline-signing") + d2i = { + "zone": "dynamic2inline.kasp", + "cdss": cdss, + "config": default_config, + "policy": "default", + "keyprops": [ + f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + "nextev": None, + } + steps = [d2i] + + # Test key lifetime changes. + isctest.log.info("check key lifetime changes are updated correctly") + lifetime = { + "P1Y": int(timedelta(days=365).total_seconds()), + "P6M": int(timedelta(days=31 * 6).total_seconds()), + } + lifetime_update_tests = [ + { + "zone": "shorter-lifetime", + "policy": "long-lifetime", + "lifetime": lifetime["P1Y"], + }, + { + "zone": "longer-lifetime", + "policy": "short-lifetime", + "lifetime": lifetime["P6M"], + }, + { + "zone": "limit-lifetime", + "policy": "unlimited-lifetime", + "lifetime": 0, + }, + { + "zone": "unlimit-lifetime", + "policy": "short-lifetime", + "lifetime": lifetime["P6M"], + }, + ] + for lut in lifetime_update_tests: + step = { + "zone": lut["zone"], + "cdss": cdss, + "config": default_config, + "policy": lut["policy"], + "keyprops": [ + f"csk {lut['lifetime']} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + "nextev": None, + } + steps.append(step) + + for step in steps: + check_rollover_step(server, step["config"], step["policy"], step) + + # Reconfigure, changing DNSSEC policies and other configuration options, + # triggering algorithm rollovers and other dnssec-policy changes. + shutil.copyfile("ns6/named2.conf", "ns6/named.conf") + server.rndc("reconfig") + # Calculate time passed to correctly check for next key events. + now = KeyTimingMetadata.now() + time_passed = now.value - start_time.value + + # Test dynamic zones that switch to inline-signing (after reconfig). + steps = [d2i] + + # Test key lifetime changes (after reconfig). + lifetime_update_tests = [ + { + "zone": "shorter-lifetime", + "policy": "short-lifetime", + "lifetime": lifetime["P6M"], + }, + { + "zone": "longer-lifetime", + "policy": "long-lifetime", + "lifetime": lifetime["P1Y"], + }, + { + "zone": "limit-lifetime", + "policy": "short-lifetime", + "lifetime": lifetime["P6M"], + }, + { + "zone": "unlimit-lifetime", + "policy": "unlimited-lifetime", + "lifetime": 0, + }, + ] + for lut in lifetime_update_tests: + step = { + "zone": lut["zone"], + "cdss": cdss, + "config": default_config, + "policy": lut["policy"], + "keyprops": [ + f"csk {lut['lifetime']} {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + "nextev": None, + } + steps.append(step) + + for step in steps: + check_rollover_step(server, step["config"], step["policy"], step) From ffccf1fe8bdc132875333081f61efeead351aa53 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 19 Mar 2025 14:37:28 +0100 Subject: [PATCH 2/4] Convert going insecure kasp test to pytest When going insecure, we publish CDS and CDNSKEY DELETE records. Update the check_apex function to test this. Also, skip some tests in the 'check_rollover_step()' function. If we change the DNSSEC Policy, keys that no longer match the policy will be retired. When this exactly happens is hard to determine, as it happens on the reconfigure. So for these tests, we skip the key timing metadata checks. Also, the zone becomes unsigned, so don't call 'check_zone_is_signed' in those cases. (cherry picked from commit b1d8217d1a39f798983152345f29c48ffa2427f9) --- bin/tests/system/isctest/kasp.py | 70 ++-- bin/tests/system/kasp/ns6/named.conf.in | 29 -- bin/tests/system/kasp/ns6/named2.conf.in | 43 --- .../kasp/ns6/policies/kasp-fips.conf.in | 9 - bin/tests/system/kasp/ns6/setup.sh | 65 ---- bin/tests/system/kasp/tests.sh | 360 ------------------ bin/tests/system/rollover/ns6/kasp.conf.j2 | 9 + bin/tests/system/rollover/ns6/named.conf.j2 | 29 ++ bin/tests/system/rollover/ns6/named2.conf.j2 | 43 +++ bin/tests/system/rollover/ns6/setup.sh | 65 ++++ bin/tests/system/rollover/tests_rollover.py | 141 ++++++- 11 files changed, 330 insertions(+), 533 deletions(-) diff --git a/bin/tests/system/isctest/kasp.py b/bin/tests/system/isctest/kasp.py index 537ebce0ba..1aec27c3f5 100644 --- a/bin/tests/system/isctest/kasp.py +++ b/bin/tests/system/isctest/kasp.py @@ -997,6 +997,15 @@ def check_cdslog_prohibit(server, zone, key, substr): ) +def check_cdsdelete(rrset, expected): + numrrs = 0 + for rr in rrset: + for rdata in rr: + assert expected in f"{rdata}" + numrrs += 1 + assert numrrs == 1 + + def _query_rrset(server, fqdn, qtype, tsig=None): response = _query(server, fqdn, qtype, tsig=tsig) assert response.rcode() == dns.rcode.NOERROR @@ -1019,7 +1028,15 @@ def _query_rrset(server, fqdn, qtype, tsig=None): def check_apex( - server, zone, ksks, zsks, cdss=None, offline_ksk=False, zsk_missing=False, tsig=None + server, + zone, + ksks, + zsks, + cdss=None, + cds_delete=False, + offline_ksk=False, + zsk_missing=False, + tsig=None, ): # Test the apex of a zone. This checks that the SOA and DNSKEY RRsets # are signed correctly and with the appropriate keys. @@ -1052,10 +1069,13 @@ def check_apex( # test cdnskey query cdnskeys, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDNSKEY, tsig=tsig) - if "CDNSKEY" in cdss: - check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + if cds_delete: + check_cdsdelete(cdnskeys, "0 3 0 AA==") else: - assert len(cdnskeys) == 0 + if "CDNSKEY" in cdss: + check_dnskeys(cdnskeys, ksks, zsks, cdnskey=True) + else: + assert len(cdnskeys) == 0 if len(cdnskeys) > 0: assert len(rrsigs) > 0 @@ -1065,29 +1085,33 @@ def check_apex( # test cds query cds, rrsigs = _query_rrset(server, fqdn, dns.rdatatype.CDS, tsig=tsig) - cdsrrs = [] - for rr in cds: - for rdata in rr: - rdclass = dns.rdataclass.to_text(rr.rdclass) - rdtype = dns.rdatatype.to_text(rr.rdtype) - cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" - cdsrrs.append(cds) - numcds = 0 + if cds_delete: + check_cdsdelete(cds, "0 0 0 00") + else: + cdsrrs = [] + for rr in cds: + for rdata in rr: + rdclass = dns.rdataclass.to_text(rr.rdclass) + rdtype = dns.rdatatype.to_text(rr.rdtype) + cds = f"{rr.name} {rr.ttl} {rdclass} {rdtype} {rdata}" + cdsrrs.append(cds) - for alg in ["SHA-256", "SHA-384"]: - if f"CDS ({alg})" in cdss: - numcds += check_cds(cdsrrs, ksks, alg) - else: - check_cds_prohibit(cdsrrs, ksks, alg) + numcds = 0 - if len(cds) > 0: - assert len(rrsigs) > 0 - check_signatures( - rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk - ) + for alg in ["SHA-256", "SHA-384"]: + if f"CDS ({alg})" in cdss: + numcds += check_cds(cdsrrs, ksks, alg) + else: + check_cds_prohibit(cdsrrs, ksks, alg) - assert numcds == len(cdsrrs) + if len(cds) > 0: + assert len(rrsigs) > 0 + check_signatures( + rrsigs, dns.rdatatype.CDS, fqdn, ksks, zsks, offline_ksk=offline_ksk + ) + + assert numcds == len(cdsrrs) def check_subdomain( diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in index f77069fdb3..df02890922 100644 --- a/bin/tests/system/kasp/ns6/named.conf.in +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -44,35 +44,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* These zones are going insecure. */ -zone "step1.going-insecure.kasp" { - type primary; - file "step1.going-insecure.kasp.db"; - dnssec-policy "unsigning"; -}; - -zone "step1.going-insecure-dynamic.kasp" { - type primary; - file "step1.going-insecure-dynamic.kasp.db"; - dnssec-policy "unsigning"; - inline-signing no; - allow-update { any; }; -}; - -zone "step1.going-straight-to-none.kasp" { - type primary; - file "step1.going-straight-to-none.kasp.db"; - dnssec-policy "default"; -}; - -zone "step1.going-straight-to-none-dynamic.kasp" { - type primary; - file "step1.going-straight-to-none-dynamic.kasp.db.signed"; - inline-signing no; - dnssec-policy "default"; - allow-update { any; }; -}; - /* These are alorithm rollover test zones. */ zone "step1.algorithm-roll.kasp" { type primary; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in index 88e67dc371..83af019480 100644 --- a/bin/tests/system/kasp/ns6/named2.conf.in +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -43,49 +43,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* Zones for testing going insecure. */ -zone "step1.going-insecure.kasp" { - type primary; - file "step1.going-insecure.kasp.db"; - dnssec-policy "insecure"; -}; - -zone "step2.going-insecure.kasp" { - type primary; - file "step2.going-insecure.kasp.db"; - dnssec-policy "insecure"; -}; - -zone "step1.going-insecure-dynamic.kasp" { - type primary; - file "step1.going-insecure-dynamic.kasp.db"; - inline-signing no; - dnssec-policy "insecure"; - allow-update { any; }; -}; - -zone "step2.going-insecure-dynamic.kasp" { - type primary; - file "step2.going-insecure-dynamic.kasp.db"; - inline-signing no; - dnssec-policy "insecure"; - allow-update { any; }; -}; - -zone "step1.going-straight-to-none.kasp" { - type primary; - file "step1.going-straight-to-none.kasp.db"; - dnssec-policy "none"; -}; - -zone "step1.going-straight-to-none-dynamic.kasp" { - type primary; - file "step1.going-straight-to-none-dynamic.kasp.db.signed"; - inline-signing no; - dnssec-policy "none"; - allow-update { any; }; -}; - /* * Zones for testing KSK/ZSK algorithm roll. */ diff --git a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in index 51c4d88488..4f7db5ad51 100644 --- a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in +++ b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in @@ -11,15 +11,6 @@ * information regarding copyright ownership. */ -dnssec-policy "unsigning" { - dnskey-ttl 7200; - - keys { - ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; - zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; - }; -}; - dnssec-policy "nsec3" { nsec3param iterations 0 optout no salt-length 0; }; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh index 6f963e33d0..306178c7b3 100644 --- a/bin/tests/system/kasp/ns6/setup.sh +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -29,71 +29,6 @@ R="RUMOURED" O="OMNIPRESENT" U="UNRETENTIVE" -# The child zones (step1, step2) beneath these zones represent the various -# steps of unsigning a zone. -for zn in going-insecure.kasp going-insecure-dynamic.kasp; do - # Step 1: - # Set up a zone with dnssec-policy that is going insecure. - setup step1.$zn - echo "$zone" >>zones - T="now-10d" - ksktimes="-P $T -A $T -P sync $T" - zsktimes="-P $T -A $T" - KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) - ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) - cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" - cp $infile $zonefile - $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - - # Step 2: - # Set up a zone with dnssec-policy that is going insecure. Don't add - # this zone to the zones file, because this zone is no longer expected - # to be fully signed. - setup step2.$zn - # The DS was withdrawn from the parent zone 26 hours ago. - Trem="now-26h" - ksktimes="-P $T -A $T -P sync $T" - zsktimes="-P $T -A $T" - KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) - ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $zsktimes $zone 2>keygen.out.$zone.2) - $SETTIME -s -g $H -k $O $T -r $O $T -d $U $Trem -D ds $Trem "$KSK" >settime.out.$zone.1 2>&1 - $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 - # Fake lifetime of old algorithm keys. - echo "Lifetime: 0" >>"${KSK}.state" - echo "Lifetime: 5184000" >>"${ZSK}.state" - cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" - private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" - cp $infile $zonefile - $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 -done - -# This zone is going straight to "none" policy. This is undefined behavior. -setup step1.going-straight-to-none.kasp -echo "$zone" >>zones -TactN="now" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# This zone is going straight to "none" policy. This is undefined behavior. -setup step1.going-straight-to-none-dynamic.kasp -echo "$zone" >>zones -TactN="now" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O full -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - # # The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK # algorithm rollover. diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 069f8a32b0..28d182a607 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -372,166 +372,6 @@ dnssec_verify # interval. check_next_key_event 3600 -# -# Testing going insecure. -# - -# -# Zone step1.going-insecure.kasp -# -set_zone "step1.going-insecure.kasp" -set_policy "unsigning" "2" "7200" -set_server "ns6" "10.53.0.6" - -# Policy parameters. -# Lksk: 0 -# Lzsk: 60 days (5184000 seconds) -# Iret(KSK): DS TTL (1d) + DprpP (1h) + retire-safety (1h) -# Iret(KSK): 1d2h (93600 seconds) -# Iret(ZSK): RRSIG TTL (1d) + Dprp (5m) + Dsgn (9d) + retire-safety (1h) -# Iret(ZSK): 10d1h5m (867900 seconds) -Lksk=0 -Lzsk=5184000 -IretKSK=93600 -IretZSK=867900 - -init_migration_insecure() { - key_clear "KEY1" - set_keyrole "KEY1" "ksk" - set_keylifetime "KEY1" "${Lksk}" - set_keyalgorithm "KEY1" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" - set_keysigning "KEY1" "yes" - set_zonesigning "KEY1" "no" - - set_keystate "KEY1" "GOAL" "omnipresent" - set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" - set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" - set_keystate "KEY1" "STATE_DS" "omnipresent" - - key_clear "KEY2" - set_keyrole "KEY2" "zsk" - set_keylifetime "KEY2" "${Lzsk}" - set_keyalgorithm "KEY2" "$DEFAULT_ALGORITHM_NUMBER" "$DEFAULT_ALGORITHM" "$DEFAULT_BITS" - set_keysigning "KEY2" "no" - set_zonesigning "KEY2" "yes" - - set_keystate "KEY2" "GOAL" "omnipresent" - set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" - set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" - - key_clear "KEY3" - key_clear "KEY4" -} -init_migration_insecure - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# We have set the timing metadata to now - 10 days (864000 seconds). -rollover_predecessor_keytimes -864000 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-insecure-dynamic.kasp -# - -set_zone "step1.going-insecure-dynamic.kasp" -set_dynamic -set_policy "unsigning" "2" "7200" -set_server "ns6" "10.53.0.6" -init_migration_insecure - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# We have set the timing metadata to now - 10 days (864000 seconds). -rollover_predecessor_keytimes -864000 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-straight-to-none.kasp -# -set_zone "step1.going-straight-to-none.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# The first key is immediately published and activated. -created=$(key_get KEY1 CREATED) -set_keytime "KEY1" "PUBLISHED" "${created}" -set_keytime "KEY1" "ACTIVE" "${created}" -set_keytime "KEY1" "SYNCPUBLISH" "${created}" -# Key lifetime is unlimited, so not setting RETIRED and REMOVED. -check_keytimes - -check_apex -check_subdomain -dnssec_verify - -# -# Zone step1.going-straight-to-none-dynamic.kasp -# -set_zone "step1.going-straight-to-none-dynamic.kasp" -set_policy "default" "1" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# The first key is immediately published and activated. -created=$(key_get KEY1 CREATED) -set_keytime "KEY1" "PUBLISHED" "${created}" -set_keytime "KEY1" "ACTIVE" "${created}" -set_keytime "KEY1" "SYNCPUBLISH" "${created}" -# Key lifetime is unlimited, so not setting RETIRED and REMOVED. -check_keytimes - -check_apex -check_subdomain -dnssec_verify - # Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy # changes). echo_i "reconfig dnssec-policy to trigger algorithm rollover" @@ -581,206 +421,6 @@ wait_for_done_signing() { status=$((status + ret)) } -# -# Testing going insecure. -# - -# -# Zone: step1.going-insecure.kasp -# -set_zone "step1.going-insecure.kasp" -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" -# Expect a CDS/CDNSKEY Delete Record. -set_cdsdelete - -# Key goal states should be HIDDEN. -init_migration_insecure -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY2" "GOAL" "hidden" -# The DS may be removed if we are going insecure. -set_keystate "KEY1" "STATE_DS" "unretentive" - -# Various signing policy checks. -check_keys -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Tell named that the DS has been removed. -rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the DS becomes HIDDEN. This happens after the -# parent propagation delay, and DS TTL: -# 1h + 1d = 25h = 90000 seconds. -check_next_key_event 90000 - -# -# Zone: step2.going-insecure.kasp -# -set_zone "step2.going-insecure.kasp" -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" - -# The DS is long enough removed from the zone to be considered HIDDEN. -# This means the DNSKEY and the KSK signatures can be removed. -set_keystate "KEY1" "STATE_DS" "hidden" -set_keystate "KEY1" "STATE_DNSKEY" "unretentive" -set_keystate "KEY1" "STATE_KRRSIG" "unretentive" -set_keysigning "KEY1" "no" - -set_keystate "KEY2" "STATE_DNSKEY" "unretentive" -set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" -set_zonesigning "KEY2" "no" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -# Next key event is when the DNSKEY becomes HIDDEN. This happens after the -# propagation delay, plus DNSKEY TTL: -# 5m + 2h = 125m = 7500 seconds. -check_next_key_event 7500 - -# -# Zone: step1.going-insecure-dynamic.kasp -# -set_zone "step1.going-insecure-dynamic.kasp" -set_dynamic -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" -# Expect a CDS/CDNSKEY Delete Record. -set_cdsdelete - -# Key goal states should be HIDDEN. -init_migration_insecure -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY2" "GOAL" "hidden" -# The DS may be removed if we are going insecure. -set_keystate "KEY1" "STATE_DS" "unretentive" - -# Various signing policy checks. -check_keys -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Tell named that the DS has been removed. -rndc_checkds "$SERVER" "$DIR" "KEY1" "now" "withdrawn" "$ZONE" -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the DS becomes HIDDEN. This happens after the -# parent propagation delay, retire safety delay, and DS TTL: -# 1h + 1d = 25h = 90000 seconds. -check_next_key_event 90000 - -# -# Zone: step2.going-insecure-dynamic.kasp -# -set_zone "step2.going-insecure-dynamic.kasp" -set_dynamic -set_policy "insecure" "2" "3600" -set_server "ns6" "10.53.0.6" - -# The DS is long enough removed from the zone to be considered HIDDEN. -# This means the DNSKEY and the KSK signatures can be removed. -set_keystate "KEY1" "STATE_DS" "hidden" -set_keystate "KEY1" "STATE_DNSKEY" "unretentive" -set_keystate "KEY1" "STATE_KRRSIG" "unretentive" -set_keysigning "KEY1" "no" - -set_keystate "KEY2" "STATE_DNSKEY" "unretentive" -set_keystate "KEY2" "STATE_ZRRSIG" "unretentive" -set_zonesigning "KEY2" "no" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -check_apex -check_subdomain - -# Next key event is when the DNSKEY becomes HIDDEN. This happens after the -# propagation delay, plus DNSKEY TTL: -# 5m + 2h = 125m = 7500 seconds. -check_next_key_event 7500 - -# -# Zone: step1.going-straight-to-none.kasp -# -set_zone "step1.going-straight-to-none.kasp" -set_policy "none" "1" "3600" -set_server "ns6" "10.53.0.6" - -# The zone will go bogus after signatures expire, but remains validly signed for now. - -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -dnssec_verify - -# -# Zone: step1.going-straight-to-none-dynamic.kasp -# -set_zone "step1.going-straight-to-none-dynamic.kasp" -set_policy "none" "1" "3600" -set_server "ns6" "10.53.0.6" - -# The zone will go bogus after signatures expire, but remains validly signed for now. - -# Key properties. -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -# DNSKEY, RRSIG (ksk), RRSIG (zsk) are published. DS needs to wait. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -# This policy only has one key. -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -dnssec_verify - # # Testing KSK/ZSK algorithm rollover. # diff --git a/bin/tests/system/rollover/ns6/kasp.conf.j2 b/bin/tests/system/rollover/ns6/kasp.conf.j2 index 38a1784acf..73f0d5789a 100644 --- a/bin/tests/system/rollover/ns6/kasp.conf.j2 +++ b/bin/tests/system/rollover/ns6/kasp.conf.j2 @@ -28,6 +28,15 @@ dnssec-policy "long-lifetime" { }; }; +dnssec-policy "unsigning" { + dnskey-ttl 7200; + + keys { + ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@; + zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@; + }; +}; + {% if RSASHA1_SUPPORTED == "1" %} dnssec-policy "rsasha1" { signatures-refresh P5D; diff --git a/bin/tests/system/rollover/ns6/named.conf.j2 b/bin/tests/system/rollover/ns6/named.conf.j2 index 03432878fe..917281ea84 100644 --- a/bin/tests/system/rollover/ns6/named.conf.j2 +++ b/bin/tests/system/rollover/ns6/named.conf.j2 @@ -76,3 +76,32 @@ zone unlimit-lifetime { file "unlimit-lifetime.db"; dnssec-policy short-lifetime; }; + +/* These zones are going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "unsigning"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + dnssec-policy "unsigning"; + inline-signing no; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "default"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "default"; + allow-update { any; }; +}; diff --git a/bin/tests/system/rollover/ns6/named2.conf.j2 b/bin/tests/system/rollover/ns6/named2.conf.j2 index b0cb1b6949..21b721508e 100644 --- a/bin/tests/system/rollover/ns6/named2.conf.j2 +++ b/bin/tests/system/rollover/ns6/named2.conf.j2 @@ -75,3 +75,46 @@ zone unlimit-lifetime { file "unlimit-lifetime.db"; dnssec-policy unlimited-lifetime; }; + +/* Zones for testing going insecure. */ +zone "step1.going-insecure.kasp" { + type primary; + file "step1.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step2.going-insecure.kasp" { + type primary; + file "step2.going-insecure.kasp.db"; + dnssec-policy "insecure"; +}; + +zone "step1.going-insecure-dynamic.kasp" { + type primary; + file "step1.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step2.going-insecure-dynamic.kasp" { + type primary; + file "step2.going-insecure-dynamic.kasp.db"; + inline-signing no; + dnssec-policy "insecure"; + allow-update { any; }; +}; + +zone "step1.going-straight-to-none.kasp" { + type primary; + file "step1.going-straight-to-none.kasp.db"; + dnssec-policy "none"; +}; + +zone "step1.going-straight-to-none-dynamic.kasp" { + type primary; + file "step1.going-straight-to-none-dynamic.kasp.db.signed"; + inline-signing no; + dnssec-policy "none"; + allow-update { any; }; +}; diff --git a/bin/tests/system/rollover/ns6/setup.sh b/bin/tests/system/rollover/ns6/setup.sh index f8ab6048e9..0f58df983c 100644 --- a/bin/tests/system/rollover/ns6/setup.sh +++ b/bin/tests/system/rollover/ns6/setup.sh @@ -34,3 +34,68 @@ for zn in dynamic2inline.kasp shorter-lifetime longer-lifetime limit-lifetime \ setup $zn cp template.db.in $zonefile done + +# The child zones (step1, step2) beneath these zones represent the various +# steps of unsigning a zone. +for zn in going-insecure.kasp going-insecure-dynamic.kasp; do + # Step 1: + # Set up a zone with dnssec-policy that is going insecure. + setup step1.$zn + echo "$zone" >>zones + T="now-10d" + S="now-12955mi" + keytimes="-P $T -A $T" + cdstimes="-P sync $S" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2) + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + + # Step 2: + # Set up a zone with dnssec-policy that is going insecure. Don't add + # this zone to the zones file, because this zone is no longer expected + # to be fully signed. + setup step2.$zn + # The DS was withdrawn from the parent zone 26 hours ago. + D="now-26h" + keytimes="-P $T -A $T -I $D -D now" + cdstimes="-P sync $S -D sync $D" + KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 -f KSK $keytimes $cdstimes $zone 2>keygen.out.$zone.1) + ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 7200 $keytimes $zone 2>keygen.out.$zone.2) + $SETTIME -s -g $H -k $O $T -r $O $T -d $U $D -D ds $D "$KSK" >settime.out.$zone.1 2>&1 + $SETTIME -s -g $H -k $O $T -z $O $T "$ZSK" >settime.out.$zone.2 2>&1 + # Fake lifetime of old algorithm keys. + echo "Lifetime: 0" >>"${KSK}.state" + echo "Lifetime: 5184000" >>"${ZSK}.state" + cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK" >>"$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK" >>"$infile" + cp $infile $zonefile + $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 +done + +# These zones are going straight to "none" policy. This is undefined behavior. +T="now-10d" +S="now-12955mi" +csktimes="-P $T -A $T -P sync $S" + +setup step1.going-straight-to-none.kasp +echo "$zone" >>zones +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +setup step1.going-straight-to-none-dynamic.kasp +echo "$zone" >>zones +CSK=$($KEYGEN -k default $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -z $O $TactN -r $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O full -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index 2d9f8275bb..1331591f53 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -387,18 +387,25 @@ def check_rollover_step(server, config, policy, step): keyrelationships = step.get("keyrelationships", None) smooth = step.get("smooth", False) ds_swap = step.get("ds-swap", True) + cds_delete = step.get("cds-delete", False) + check_keytimes = step.get("check-keytimes", True) + zone_signed = step.get("zone-signed", True) isctest.log.info(f"check rollover step {zone}") + if zone_signed: + isctest.kasp.check_dnssec_verify(server, zone) + ttl = int(config["dnskey-ttl"].total_seconds()) expected = isctest.kasp.policy_to_properties(ttl, keyprops) - isctest.kasp.check_dnssec_verify(server, zone) keys = isctest.kasp.keydir_to_keylist(zone, server.identifier) ksks = [k for k in keys if k.is_ksk()] zsks = [k for k in keys if not k.is_ksk()] isctest.kasp.check_keys(zone, keys, expected) for kp in expected: + key = kp.key + # Set expected key timing metadata. kp.set_expected_keytimes(config) @@ -410,12 +417,19 @@ def check_rollover_step(server, config, policy, step): expected[suc].metadata["Predecessor"] = expected[prd].key.tag isctest.kasp.check_keyrelationships(keys, expected) + # Policy changes may retire keys, set expected timing metadata. + if kp.metadata["GoalState"] == "hidden" and "Retired" not in kp.timing: + retired = kp.key.get_timing("Inactive") + kp.timing["Retired"] = retired + kp.timing["Removed"] = retired + Iret( + config, zsk=key.is_zsk(), ksk=key.is_ksk() + ) + # Check that CDS publication/withdrawal is logged. if "KSK" not in kp.metadata: continue if kp.metadata["KSK"] == "no": continue - key = kp.key if ds_swap and kp.metadata["DSState"] == "rumoured": assert cdss is not None @@ -434,9 +448,11 @@ def check_rollover_step(server, config, policy, step): # delay, so set the DS withdraw time to now. server.rndc(f"dnssec -checkds -key {key.tag} withdrawn {zone}") - isctest.kasp.check_keytimes(keys, expected) + if check_keytimes: + isctest.kasp.check_keytimes(keys, expected) + isctest.kasp.check_dnssecstatus(server, zone, keys, policy=policy) - isctest.kasp.check_apex(server, zone, ksks, zsks, cdss=cdss) + isctest.kasp.check_apex(server, zone, ksks, zsks, cdss=cdss, cds_delete=cds_delete) isctest.kasp.check_subdomain(server, zone, ksks, zsks, smooth=smooth) def check_next_key_event(): @@ -1278,6 +1294,9 @@ def test_rollover_policy_changes(servers): "zone-propagation-delay": timedelta(seconds=300), } + unsigning_config = default_config.copy() + unsigning_config["dnskey-ttl"] = timedelta(seconds=7200) + start_time = KeyTimingMetadata.now() # Test dynamic zones that switch to inline-signing. @@ -1299,6 +1318,7 @@ def test_rollover_policy_changes(servers): lifetime = { "P1Y": int(timedelta(days=365).total_seconds()), "P6M": int(timedelta(days=31 * 6).total_seconds()), + "P60D": int(timedelta(days=60).total_seconds()), } lifetime_update_tests = [ { @@ -1335,6 +1355,47 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test going insecure. + isctest.log.info("check going insecure") + offset = -timedelta(days=10) + offval = int(offset.total_seconds()) + zones = [ + "step1.going-insecure.kasp", + "step1.going-insecure-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": unsigning_config, + "policy": "unsigning", + "keyprops": [ + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + + # Test going straight to none. + isctest.log.info("check going straight to none") + zones = [ + "step1.going-straight-to-none.kasp", + "step1.going-straight-to-none-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": default_config, + "policy": "default", + "keyprops": [ + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + for step in steps: check_rollover_step(server, step["config"], step["policy"], step) @@ -1385,5 +1446,77 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test going insecure (after reconfig). + isctest.log.info("check going insecure (after reconfig)") + oldttl = unsigning_config["dnskey-ttl"] + offset = -timedelta(days=10) + offval = int(offset.total_seconds()) + zones = ["going-insecure.kasp", "going-insecure-dynamic.kasp"] + for parent in zones: + # Step 1. + # Key goal states should be HIDDEN. + # The DS may be removed if we are going insecure. + step = { + "zone": f"step1.{parent}", + "cdss": cdss, + "config": default_config, + "policy": "insecure", + "keyprops": [ + f"ksk 0 {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + ], + # Next key event is when the DS becomes HIDDEN. This + # happens after the# parent propagation delay plus DS TTL. + "nextev": default_config["ds-ttl"] + + default_config["parent-propagation-delay"], + # Going insecure, check for CDS/CDNSKEY DELETE, and skip key timing checks. + "cds-delete": True, + "check-keytimes": False, + } + steps.append(step) + + # Step 2. + # The DS is long enough removed from the zone to be considered + # HIDDEN. This means the DNSKEY and the KSK signatures can be + # removed. + step = { + "zone": f"step2.{parent}", + "cdss": cdss, + "config": default_config, + "policy": "insecure", + "keyprops": [ + f"ksk 0 {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{offval}", + f"zsk {lifetime['P60D']} {alg} {size} goal:hidden dnskey:unretentive zrrsig:unretentive offset:{offval}", + ], + # Next key event is when the DNSKEY becomes HIDDEN. + # This happens after the propagation delay, plus DNSKEY TTL. + "nextev": oldttl + default_config["zone-propagation-delay"], + # Zone is no longer signed. + "zone-signed": False, + "check-keytimes": False, + } + steps.append(step) + + # Test going straight to none. + isctest.log.info("check going straight to none (after reconfig)") + zones = [ + "step1.going-straight-to-none.kasp", + "step1.going-straight-to-none-dynamic.kasp", + ] + for zone in zones: + step = { + "zone": zone, + "cdss": cdss, + "config": default_config, + "policy": None, + # These zones will go bogus after signatures expire, but + # remain validly signed for now. + "keyprops": [ + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + ], + "nextev": None, + } + steps.append(step) + for step in steps: check_rollover_step(server, step["config"], step["policy"], step) From 383605c902afa9af4492d0fb291e92a829317415 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 19 Mar 2025 16:28:33 +0100 Subject: [PATCH 3/4] Convert algorithm rollover tests to pytest Roll the algorithm rollover test cases over to the rollover directory and rewrite using pytest. (cherry picked from commit 80992c7b96d0fe1cc10130963766225780dd6ed1) --- bin/tests/system/kasp/ns6/named.conf.in | 13 - bin/tests/system/kasp/ns6/named2.conf.in | 78 -- .../kasp/ns6/policies/kasp-fips.conf.in | 38 - bin/tests/system/kasp/ns6/setup.sh | 329 ----- bin/tests/system/kasp/tests.sh | 1054 ----------------- bin/tests/system/rollover/ns6/kasp.conf.j2 | 38 + bin/tests/system/rollover/ns6/named.conf.j2 | 13 + bin/tests/system/rollover/ns6/named2.conf.j2 | 78 ++ bin/tests/system/rollover/ns6/setup.sh | 289 +++++ bin/tests/system/rollover/tests_rollover.py | 293 +++++ 10 files changed, 711 insertions(+), 1512 deletions(-) diff --git a/bin/tests/system/kasp/ns6/named.conf.in b/bin/tests/system/kasp/ns6/named.conf.in index df02890922..2bee0a04b9 100644 --- a/bin/tests/system/kasp/ns6/named.conf.in +++ b/bin/tests/system/kasp/ns6/named.conf.in @@ -44,19 +44,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* These are alorithm rollover test zones. */ -zone "step1.algorithm-roll.kasp" { - type primary; - file "step1.algorithm-roll.kasp.db"; - dnssec-policy "rsasha256"; -}; - -zone "step1.csk-algorithm-roll.kasp" { - type primary; - file "step1.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - zone example { type primary; file "example.db"; diff --git a/bin/tests/system/kasp/ns6/named2.conf.in b/bin/tests/system/kasp/ns6/named2.conf.in index 83af019480..85af830a3c 100644 --- a/bin/tests/system/kasp/ns6/named2.conf.in +++ b/bin/tests/system/kasp/ns6/named2.conf.in @@ -43,84 +43,6 @@ zone "." { file "../../_common/root.hint.blackhole"; }; -/* - * Zones for testing KSK/ZSK algorithm roll. - */ -zone "step1.algorithm-roll.kasp" { - type primary; - file "step1.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -zone "step2.algorithm-roll.kasp" { - type primary; - file "step2.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -zone "step3.algorithm-roll.kasp" { - type primary; - file "step3.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -zone "step4.algorithm-roll.kasp" { - type primary; - file "step4.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -zone "step5.algorithm-roll.kasp" { - type primary; - file "step5.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -zone "step6.algorithm-roll.kasp" { - type primary; - file "step6.algorithm-roll.kasp.db"; - dnssec-policy "ecdsa256"; -}; - -/* - * Zones for testing CSK algorithm roll. - */ -zone "step1.csk-algorithm-roll.kasp" { - type primary; - file "step1.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - -zone "step2.csk-algorithm-roll.kasp" { - type primary; - file "step2.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - -zone "step3.csk-algorithm-roll.kasp" { - type primary; - file "step3.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - -zone "step4.csk-algorithm-roll.kasp" { - type primary; - file "step4.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - -zone "step5.csk-algorithm-roll.kasp" { - type primary; - file "step5.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - -zone "step6.csk-algorithm-roll.kasp" { - type primary; - file "step6.csk-algorithm-roll.kasp.db"; - dnssec-policy "csk-algoroll"; -}; - zone example { type primary; file "example.db"; diff --git a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in index 4f7db5ad51..b217aa68cc 100644 --- a/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in +++ b/bin/tests/system/kasp/ns6/policies/kasp-fips.conf.in @@ -37,41 +37,3 @@ dnssec-policy "long-lifetime" { csk lifetime P1Y algorithm @DEFAULT_ALGORITHM@; }; }; - -dnssec-policy "rsasha256" { - signatures-refresh P5D; - signatures-validity 30d; - signatures-validity-dnskey 30d; - - keys { - ksk lifetime unlimited algorithm rsasha256; - zsk lifetime unlimited algorithm rsasha256; - }; - - dnskey-ttl 1h; - publish-safety PT1H; - retire-safety 2h; - zone-propagation-delay 3600; - max-zone-ttl 6h; - parent-propagation-delay pt1h; - parent-ds-ttl 7200; -}; - -dnssec-policy "ecdsa256" { - signatures-refresh P5D; - signatures-validity 30d; - signatures-validity-dnskey 30d; - - keys { - ksk lifetime unlimited algorithm ecdsa256; - zsk lifetime unlimited algorithm ecdsa256; - }; - - dnskey-ttl 1h; - publish-safety PT1H; - retire-safety 2h; - zone-propagation-delay 3600; - max-zone-ttl 6h; - parent-propagation-delay pt1h; - parent-ds-ttl 7200; -}; diff --git a/bin/tests/system/kasp/ns6/setup.sh b/bin/tests/system/kasp/ns6/setup.sh index 306178c7b3..e094e7efdd 100644 --- a/bin/tests/system/kasp/ns6/setup.sh +++ b/bin/tests/system/kasp/ns6/setup.sh @@ -16,335 +16,6 @@ echo_i "ns6/setup.sh" -setup() { - zone="$1" - echo_i "setting up zone: $zone" - zonefile="${zone}.db" - infile="${zone}.db.infile" -} - -# Make lines shorter by storing key states in environment variables. -H="HIDDEN" -R="RUMOURED" -O="OMNIPRESENT" -U="UNRETENTIVE" - -# -# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK -# algorithm rollover. -# - -# Step 1: -# Introduce the first key. This will immediately be active. -setup step1.algorithm-roll.kasp -echo "$zone" >>zones -TactN="now" -ksktimes="-P ${TactN} -A ${TactN} -P sync ${TactN}" -zsktimes="-P ${TactN} -A ${TactN}" -KSK=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) -ZSK=$($KEYGEN -a RSASHA256 -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 -cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" -private_type_record $zone 8 "$KSK" >>"$infile" -private_type_record $zone 8 "$ZSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 2: -# After the publication interval has passed the DNSKEY is OMNIPRESENT. -setup step2.algorithm-roll.kasp -# The time passed since the new algorithm keys have been introduced is 3 hours. -TactN="now-3h" -TpubN1="now-3h" -# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = -# now - 3h + 6h + 1h = now + 4h -TsbmN1="now+4h" -ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now" -zsk1times="-P ${TactN} -A ${TactN} -I now" -ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" -zsk2times="-P ${TpubN1} -A ${TpubN1}" -KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${KSK1}.state" -echo "Lifetime: 0" >>"${ZSK1}.state" -cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone 8 "$KSK1" >>"$infile" -private_type_record $zone 8 "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 3: -# The zone signatures are also OMNIPRESENT. -setup step3.algorithm-roll.kasp -# The time passed since the new algorithm keys have been introduced is 7 hours. -TactN="now-7h" -TretN="now-3h" -TpubN1="now-7h" -TsbmN1="now" -ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" -ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" -zsk2times="-P ${TpubN1} -A ${TpubN1}" -KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${KSK1}.state" -echo "Lifetime: 0" >>"${ZSK1}.state" -cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone 8 "$KSK1" >>"$infile" -private_type_record $zone 8 "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 4: -# The DS is swapped and can become OMNIPRESENT. -setup step4.algorithm-roll.kasp -# The time passed since the DS has been swapped is 29 hours. -TactN="now-36h" -TretN="now-33h" -TpubN1="now-36h" -TsbmN1="now-29h" -TactN1="now-27h" -ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" -ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" -zsk2times="-P ${TpubN1} -A ${TpubN1}" -KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TactN1 -D ds $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $R $TactN1 -P ds $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${KSK1}.state" -echo "Lifetime: 0" >>"${ZSK1}.state" -cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone 8 "$KSK1" >>"$infile" -private_type_record $zone 8 "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 5: -# The DNSKEY is removed long enough to be HIDDEN. -setup step5.algorithm-roll.kasp -# The time passed since the DNSKEY has been removed is 2 hours. -TactN="now-38h" -TretN="now-35h" -TremN="now-2h" -TpubN1="now-38h" -TsbmN1="now-31h" -TactN1="now-29h" -ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" -ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" -zsk2times="-P ${TpubN1} -A ${TpubN1}" -KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) -$SETTIME -s -g $H -k $U $TremN -r $U $TremN -d $H $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $U $TremN -z $U $TremN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${KSK1}.state" -echo "Lifetime: 0" >>"${ZSK1}.state" -cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone 8 "$KSK1" >>"$infile" -private_type_record $zone 8 "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 6: -# The RRSIGs have been removed long enough to be HIDDEN. -setup step6.algorithm-roll.kasp -# Additional time passed: 7h. -TactN="now-45h" -TretN="now-42h" -TremN="now-7h" -TpubN1="now-45h" -TsbmN1="now-38h" -TactN1="now-36h" -TdeaN="now-7h" -ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" -ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" -zsk2times="-P ${TpubN1} -A ${TpubN1}" -KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) -ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) -KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) -ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) -$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -d $H $TactN1 "$KSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $H -k $H $TremN -z $U $TdeaN "$ZSK1" >settime.out.$zone.2 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TactN1 "$KSK2" >settime.out.$zone.3 2>&1 -$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${KSK1}.state" -echo "Lifetime: 0" >>"${ZSK1}.state" -cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" -private_type_record $zone 8 "$KSK1" >>"$infile" -private_type_record $zone 8 "$ZSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# -# The zones at csk-algorithm-roll.kasp represent the various steps of a CSK -# algorithm rollover. -# - -# Step 1: -# Introduce the first key. This will immediately be active. -setup step1.csk-algorithm-roll.kasp -echo "$zone" >>zones -TactN="now" -csktimes="-P ${TactN} -P sync ${TactN} -A ${TactN}" -CSK=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -$SETTIME -s -g $O -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 -cat template.db.in "${CSK}.key" >"$infile" -private_type_record $zone 5 "$CSK" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 2: -# After the publication interval has passed the DNSKEY is OMNIPRESENT. -setup step2.csk-algorithm-roll.kasp -# The time passed since the new algorithm keys have been introduced is 3 hours. -TactN="now-3h" -TpubN1="now-3h" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now" -newtimes="-P ${TpubN1} -A ${TpubN1}" -CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${CSK1}.state" -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone 5 "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 3: -# The zone signatures are also OMNIPRESENT. -setup step3.csk-algorithm-roll.kasp -# The time passed since the new algorithm keys have been introduced is 7 hours. -TactN="now-7h" -TretN="now-3h" -TpubN1="now-7h" -TactN1="now-3h" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -newtimes="-P ${TpubN1} -A ${TpubN1}" -CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${CSK1}.state" -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone 5 "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 4: -# The DS is swapped and can become OMNIPRESENT. -setup step4.csk-algorithm-roll.kasp -# The time passed since the DS has been swapped is 29 hours. -TactN="now-36h" -TretN="now-33h" -TpubN1="now-36h" -TactN1="now-33h" -TsubN1="now-29h" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -newtimes="-P ${TpubN1} -A ${TpubN1}" -CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $U $TactN1 -D ds $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $R $TsubN1 -P ds $TsubN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${CSK1}.state" -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone 5 "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 5: -# The DNSKEY is removed long enough to be HIDDEN. -setup step5.csk-algorithm-roll.kasp -# The time passed since the DNSKEY has been removed is 2 hours. -TactN="now-38h" -TretN="now-35h" -TremN="now-2h" -TpubN1="now-38h" -TactN1="now-35h" -TsubN1="now-31h" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -newtimes="-P ${TpubN1} -A ${TpubN1}" -CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $U $TremN -r $U $TremN -z $U $TremN -d $H $TremN "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TremN "$CSK2" >settime.out.$zone.2 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${CSK1}.state" -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone 5 "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - -# Step 6: -# The RRSIGs have been removed long enough to be HIDDEN. -setup step6.csk-algorithm-roll.kasp -# Additional time passed: 7h. -TactN="now-45h" -TretN="now-42h" -TdeaN="now-9h" -TremN="now-7h" -TpubN1="now-45h" -TactN1="now-42h" -TsubN1="now-38h" -csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" -newtimes="-P ${TpubN1} -A ${TpubN1}" -CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) -CSK2=$($KEYGEN -k csk-algoroll -l policies/csk2.conf $newtimes $zone 2>keygen.out.$zone.2) -$SETTIME -s -g $H -k $H $TremN -r $U $TdeaN -z $U $TdeaN -d $H $TactN1 "$CSK1" >settime.out.$zone.1 2>&1 -$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TactN1 "$CSK2" >settime.out.$zone.2 2>&1 -# Fake lifetime of old algorithm keys. -echo "Lifetime: 0" >>"${CSK1}.state" -cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" -private_type_record $zone 5 "$CSK1" >>"$infile" -private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" -cp $infile $zonefile -$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 - # # Reload testing # diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh index 28d182a607..2114fd08cf 100644 --- a/bin/tests/system/kasp/tests.sh +++ b/bin/tests/system/kasp/tests.sh @@ -85,1059 +85,5 @@ retry_quiet 30 _wait_for_done_apexnsec || ret=1 test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -set_keytimes_csk_policy() { - # The first key is immediately published and activated. - created=$(key_get KEY1 CREATED) - set_keytime "KEY1" "PUBLISHED" "${created}" - set_keytime "KEY1" "ACTIVE" "${created}" - # The DS can be published if the DNSKEY and RRSIG records are - # OMNIPRESENT. This happens after max-zone-ttl (1d) plus - # zone-propagation-delay (300s) = 86400 + 300 = 86700. - set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 86700 - # Key lifetime is unlimited, so not setting RETIRED and REMOVED. -} - -# Set keytimes for dnssec-policy with various algorithms. -# These all use the same time values. -set_keytimes_algorithm_policy() { - # The first KSK is immediately published and activated. - created=$(key_get KEY1 CREATED) - set_keytime "KEY1" "PUBLISHED" "${created}" - set_keytime "KEY1" "ACTIVE" "${created}" - # Key was pregenerated. - if [ "$1" = "pregenerated" ]; then - keyfile=$(key_get KEY1 BASEFILE) - grep "; Publish:" "${keyfile}.key" >published.test${n}.key1 - published=$(awk '{print $3}' published.test${n}.key2 - published=$(awk '{print $3}' published.test${n}.key3 - published=$(awk '{print $3}' "keyevent.out.$ZONE.test$n" || return 1 - - # Get the latest next key event. - if [ "${DYNAMIC}" = "yes" ]; then - _time=$(awk '{print $9}' <"keyevent.out.$ZONE.test$n" | tail -1) - else - # inline-signing zone adds "(signed)" - _time=$(awk '{print $10}' <"keyevent.out.$ZONE.test$n" | tail -1) - fi - - # The next key event time must within threshold of the - # expected time. - _expectmin=$((_expect - next_key_event_threshold)) - _expectmax=$((_expect + next_key_event_threshold)) - - test $_expectmin -le "$_time" || return 1 - test $_expectmax -ge "$_time" || return 1 - - return 0 -} - -check_next_key_event() { - n=$((n + 1)) - echo_i "check next key event for zone ${ZONE} ($n)" - ret=0 - - retry_quiet 3 _check_next_key_event $1 || log_error "bad next key event time for zone ${ZONE} (expect ${_expect})" - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) - -} - -set_retired_removed() { - _Lkey=$2 - _Iret=$3 - - _active=$(key_get $1 ACTIVE) - set_addkeytime "${1}" "RETIRED" "${_active}" "${_Lkey}" - _retired=$(key_get $1 RETIRED) - set_addkeytime "${1}" "REMOVED" "${_retired}" "${_Iret}" -} - -rollover_predecessor_keytimes() { - _addtime=$1 - - _created=$(key_get KEY1 CREATED) - set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}" - set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}" - set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}" - [ "$Lksk" = 0 ] || set_retired_removed "KEY1" "${Lksk}" "${IretKSK}" - - _created=$(key_get KEY2 CREATED) - set_addkeytime "KEY2" "PUBLISHED" "${_created}" "${_addtime}" - set_addkeytime "KEY2" "ACTIVE" "${_created}" "${_addtime}" - [ "$Lzsk" = 0 ] || set_retired_removed "KEY2" "${Lzsk}" "${IretZSK}" -} - -csk_rollover_predecessor_keytimes() { - _addtime=$1 - - _created=$(key_get KEY1 CREATED) - set_addkeytime "KEY1" "PUBLISHED" "${_created}" "${_addtime}" - set_addkeytime "KEY1" "SYNCPUBLISH" "${_created}" "${_addtime}" - set_addkeytime "KEY1" "ACTIVE" "${_created}" "${_addtime}" - [ "$Lcsk" = 0 ] || set_retired_removed "KEY1" "${Lcsk}" "${IretCSK}" -} - -# -# Testing algorithm rollover. -# -Lksk=0 -Lzsk=0 -IretKSK=0 -IretZSK=0 - -# -# Zone: step1.algorithm-roll.kasp -# -set_zone "step1.algorithm-roll.kasp" -set_policy "rsasha256" "2" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -key_clear "KEY2" -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "0" -set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" -key_clear "KEY3" -key_clear "KEY4" - -# The KSK (KEY1) and ZSK (KEY2) start in OMNIPRESENT. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" - -set_keystate "KEY2" "GOAL" "omnipresent" -set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# These keys are immediately published and activated. -rollover_predecessor_keytimes 0 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the successor keys need to be published. -# Since the lifetime of the keys are unlimited, so default to loadkeys -# interval. -check_next_key_event 3600 - -# -# Zone: step1.csk-algorithm-roll.kasp -# -set_zone "step1.csk-algorithm-roll.kasp" -set_policy "csk-algoroll" "1" "3600" -set_server "ns6" "10.53.0.6" -# Key properties. -key_clear "KEY1" -set_keyrole "KEY1" "csk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "yes" -key_clear "KEY2" -key_clear "KEY3" -key_clear "KEY4" -# The CSK (KEY1) starts in OMNIPRESENT. -set_keystate "KEY1" "GOAL" "omnipresent" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_ZRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" - -# Various signing policy checks. -check_keys -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" -# This key is immediately published and activated. -Lcsk=0 -IretCSK=0 -csk_rollover_predecessor_keytimes 0 -check_keytimes -check_apex -check_subdomain -dnssec_verify - -# Next key event is when the successor keys need to be published. -# Since the lifetime of the keys are unlimited, so default to loadkeys -# interval. -check_next_key_event 3600 - -# Reconfig dnssec-policy (triggering algorithm roll and other dnssec-policy -# changes). -echo_i "reconfig dnssec-policy to trigger algorithm rollover" -copy_setports ns6/named2.conf.in ns6/named.conf -rndc_reconfig ns6 10.53.0.6 - -# Calculate time passed to correctly check for next key events. -now="$(TZ=UTC date +%s)" -time_passed=$((now - start_time)) -echo_i "${time_passed} seconds passed between start of tests and reconfig" - -# Wait until we have seen "zone_rekey done:" message for this key. -_wait_for_done_signing() { - _zone=$1 - - _ksk=$(key_get $2 KSK) - _zsk=$(key_get $2 ZSK) - if [ "$_ksk" = "yes" ]; then - _role="KSK" - _expect_type=EXPECT_KRRSIG - elif [ "$_zsk" = "yes" ]; then - _role="ZSK" - _expect_type=EXPECT_ZRRSIG - fi - - if [ "$(key_get ${2} $_expect_type)" = "yes" ] && [ "$(key_get $2 $_role)" = "yes" ]; then - _keyid=$(key_get $2 ID) - _keyalg=$(key_get $2 ALG_STR) - echo_i "wait for zone ${_zone} is done signing with $2 ${_zone}/${_keyalg}/${_keyid}" - grep "zone_rekey done: key ${_keyid}/${_keyalg}" "${DIR}/named.run" >/dev/null || return 1 - fi - - return 0 -} - -wait_for_done_signing() { - n=$((n + 1)) - echo_i "wait for zone ${ZONE} is done signing ($n)" - ret=0 - - retry_quiet 30 _wait_for_done_signing ${ZONE} KEY1 || ret=1 - retry_quiet 30 _wait_for_done_signing ${ZONE} KEY2 || ret=1 - retry_quiet 30 _wait_for_done_signing ${ZONE} KEY3 || ret=1 - retry_quiet 30 _wait_for_done_signing ${ZONE} KEY4 || ret=1 - - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -} - -# -# Testing KSK/ZSK algorithm rollover. -# - -# Policy parameters. -# Lksk: unlimited -# Lzsk: unlimited -Lksk=0 -Lzsk=0 - -# -# Zone: step1.algorithm-roll.kasp -# -set_zone "step1.algorithm-roll.kasp" -set_policy "ecdsa256" "4" "3600" -set_server "ns6" "10.53.0.6" -# Old RSASHA1 keys. -key_clear "KEY1" -set_keyrole "KEY1" "ksk" -set_keylifetime "KEY1" "0" -set_keyalgorithm "KEY1" "8" "RSASHA256" "2048" -set_keysigning "KEY1" "yes" -set_zonesigning "KEY1" "no" - -key_clear "KEY2" -set_keyrole "KEY2" "zsk" -set_keylifetime "KEY2" "0" -set_keyalgorithm "KEY2" "8" "RSASHA256" "2048" -set_keysigning "KEY2" "no" -set_zonesigning "KEY2" "yes" -# New ECDSAP256SHA256 keys. -key_clear "KEY3" -set_keyrole "KEY3" "ksk" -set_keylifetime "KEY3" "0" -set_keyalgorithm "KEY3" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY3" "yes" -set_zonesigning "KEY3" "no" - -key_clear "KEY4" -set_keyrole "KEY4" "zsk" -set_keylifetime "KEY4" "0" -set_keyalgorithm "KEY4" "13" "ECDSAP256SHA256" "256" -set_keysigning "KEY4" "no" -set_zonesigning "KEY4" "yes" -# The RSAHSHA1 keys are outroducing. -set_keystate "KEY1" "GOAL" "hidden" -set_keystate "KEY1" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY1" "STATE_KRRSIG" "omnipresent" -set_keystate "KEY1" "STATE_DS" "omnipresent" -set_keystate "KEY2" "GOAL" "hidden" -set_keystate "KEY2" "STATE_DNSKEY" "omnipresent" -set_keystate "KEY2" "STATE_ZRRSIG" "omnipresent" -# The ECDSAP256SHA256 keys are introducing. -set_keystate "KEY3" "GOAL" "omnipresent" -set_keystate "KEY3" "STATE_DNSKEY" "rumoured" -set_keystate "KEY3" "STATE_KRRSIG" "rumoured" -set_keystate "KEY3" "STATE_DS" "hidden" -set_keystate "KEY4" "GOAL" "omnipresent" -set_keystate "KEY4" "STATE_DNSKEY" "rumoured" -set_keystate "KEY4" "STATE_ZRRSIG" "rumoured" - -# Various signing policy checks. -check_keys -wait_for_done_signing -check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" - -# Set expected key times: -# - The old keys are published and activated. -rollover_predecessor_keytimes 0 -# - KSK must be retired since it no longer matches the policy. -keyfile=$(key_get KEY1 BASEFILE) -grep "; Inactive:" "${keyfile}.key" >retired.test${n}.ksk -retired=$(awk '{print $3}' retired.test${n}.zsk -retired=$(awk '{print $3}' retired.test${n}.ksk -retired=$(awk '{print $3}' "$infile" private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >>"$infile" cp $infile $zonefile $SIGNER -S -z -x -s now-1h -e now+2w -o $zone -O full -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at algorithm-roll.kasp represent the various steps of a ZSK/KSK +# algorithm rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.algorithm-roll.kasp +echo "$zone" >>zones +TactN="now-7d" +TsbmN="now-161h" +ksktimes="-P ${TactN} -A ${TactN}" +zsktimes="-P ${TactN} -A ${TactN}" +KSK=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksktimes $zone 2>keygen.out.$zone.1) +ZSK=$($KEYGEN -a RSASHA256 -L 3600 $zsktimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -d $O $TactN "$KSK" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN -z $O $TactN "$ZSK" >settime.out.$zone.2 2>&1 +cat template.db.in "${KSK}.key" "${ZSK}.key" >"$infile" +private_type_record $zone 8 "$KSK" >>"$infile" +private_type_record $zone 8 "$ZSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# After the publication interval has passed the DNSKEY is OMNIPRESENT. +setup step2.algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 3 hours. +TpubN1="now-3h" +# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = now - 3h + 6h + 1h = now + 4h +TsbmN1="now+4h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TsbmN1}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures are also OMNIPRESENT. +setup step3.algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 7 hours. +TpubN1="now-7h" +TsbmN1="now" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TsbmN1}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $O $TactN "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $H $TpubN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS is swapped and can become OMNIPRESENT. +setup step4.algorithm-roll.kasp +# The time passed since the DS has been swapped is 3 hours. +TpubN1="now-10h" +TsbmN1="now-3h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TsbmN1}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -d $U $TsbmN1 -D ds $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $O $TactN -z $O $TactN "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $R $TsbmN1 -P ds $TsbmN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The DNSKEY is removed long enough to be HIDDEN. +setup step5.algorithm-roll.kasp +# The time passed since the DNSKEY has been removed is 2 hours. +TpubN1="now-12h" +TsbmN1="now-5h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TsbmN1}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $U $TsbmN1 -r $U $TsbmN1 -d $H $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $U $TsbmN1 -z $U $TsbmN1 "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TsbmN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The RRSIGs have been removed long enough to be HIDDEN. +setup step6.algorithm-roll.kasp +# Additional time passed: 7h. +TpubN1="now-19h" +TsbmN1="now-12h" +ksk1times="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +zsk1times="-P ${TactN} -A ${TactN} -I ${TsbmN1}" +ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +zsk2times="-P ${TpubN1} -A ${TpubN1}" +KSK1=$($KEYGEN -a RSASHA256 -L 3600 -f KSK $ksk1times $zone 2>keygen.out.$zone.1) +ZSK1=$($KEYGEN -a RSASHA256 -L 3600 $zsk1times $zone 2>keygen.out.$zone.2) +KSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $ksk2times $zone 2>keygen.out.$zone.3) +ZSK2=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsk2times $zone 2>keygen.out.$zone.4) +$SETTIME -s -g $H -k $H $TsbmN1 -r $U $TsbmN1 -d $H $TsbmN1 "$KSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $H -k $H $TsbmN1 -z $U $TsbmN1 "$ZSK1" >settime.out.$zone.2 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -d $O $TsbmN1 "$KSK2" >settime.out.$zone.3 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -z $R $TpubN1 "$ZSK2" >settime.out.$zone.4 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${KSK1}.state" +echo "Lifetime: 0" >>"${ZSK1}.state" +cat template.db.in "${KSK1}.key" "${ZSK1}.key" "${KSK2}.key" "${ZSK2}.key" >"$infile" +private_type_record $zone 8 "$KSK1" >>"$infile" +private_type_record $zone 8 "$ZSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$KSK2" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$ZSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# +# The zones at csk-algorithm-roll.kasp represent the various steps of a CSK +# algorithm rollover. +# + +# Step 1: +# Introduce the first key. This will immediately be active. +setup step1.csk-algorithm-roll.kasp +echo "$zone" >>zones +TactN="now-7d" +TsbmN="now-161h" +csktimes="-P ${TactN} -A ${TactN}" +CSK=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +$SETTIME -s -g $O -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK" >settime.out.$zone.1 2>&1 +cat template.db.in "${CSK}.key" >"$infile" +private_type_record $zone 5 "$CSK" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 2: +# After the publication interval has passed the DNSKEY is OMNIPRESENT. +setup step2.csk-algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 3 hours. +TpubN1="now-3h" +# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = now - 3h + 6h + 1h = now + 4h +TsbmN1="now+4h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I now" +newtimes="-P ${TpubN1} -A ${TpubN1}" +CSK1=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $R $TpubN1 -r $R $TpubN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 3: +# The zone signatures are also OMNIPRESENT. +setup step3.csk-algorithm-roll.kasp +# The time passed since the new algorithm keys have been introduced is 7 hours. +TpubN1="now-7h" +TsbmN1="now" +ckstimes="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +newtimes="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +CSK1=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TactN -d $O $TactN "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -z $R $TpubN1 -d $H $TpubN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 4: +# The DS is swapped and can become OMNIPRESENT. +setup step4.csk-algorithm-roll.kasp +# The time passed since the DS has been swapped is 3 hours. +TpubN1="now-10h" +TsbmN1="now-3h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +newtimes="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +CSK1=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $O $TactN -r $O $TactN -z $O $TsbmN1 -d $U $TsbmN1 -D ds $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -z $O $TsbmN1 -d $R $TsbmN1 -P ds $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 5: +# The DNSKEY is removed long enough to be HIDDEN. +setup step5.csk-algorithm-roll.kasp +# The time passed since the DNSKEY has been removed is 2 hours. +TpubN1="now-12h" +TsbmN1="now-5h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +newtimes="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +CSK1=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $U $TactN -r $U $TactN -z $U $TsbmN1 -d $H $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TpubN1 -r $O $TpubN1 -z $O $TsbmN1 -d $O $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 + +# Step 6: +# The RRSIGs have been removed long enough to be HIDDEN. +setup step6.csk-algorithm-roll.kasp +# Additional time passed: 7h. +TpubN1="now-19h" +TsbmN1="now-12h" +csktimes="-P ${TactN} -A ${TactN} -P sync ${TsbmN} -I ${TsbmN1}" +newtimes="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" +CSK1=$($KEYGEN -k csk-algoroll -l csk1.conf $csktimes $zone 2>keygen.out.$zone.1) +CSK2=$($KEYGEN -k csk-algoroll -l csk2.conf $newtimes $zone 2>keygen.out.$zone.2) +$SETTIME -s -g $H -k $H $TactN -r $U $TactN -z $U $TactN -d $H $TsbmN1 "$CSK1" >settime.out.$zone.1 2>&1 +$SETTIME -s -g $O -k $O $TactN1 -r $O $TactN1 -z $O $TsubN1 -d $O $TsbmN1 "$CSK2" >settime.out.$zone.2 2>&1 +# Fake lifetime of old algorithm keys. +echo "Lifetime: 0" >>"${CSK1}.state" +cat template.db.in "${CSK1}.key" "${CSK2}.key" >"$infile" +private_type_record $zone 5 "$CSK1" >>"$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK2" >>"$infile" +cp $infile $zonefile +$SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infile >signer.out.$zone.1 2>&1 diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index 1331591f53..f30eb2fad9 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -1297,6 +1297,19 @@ def test_rollover_policy_changes(servers): unsigning_config = default_config.copy() unsigning_config["dnskey-ttl"] = timedelta(seconds=7200) + algoroll_config = { + "dnskey-ttl": timedelta(hours=1), + "ds-ttl": timedelta(seconds=7200), + "max-zone-ttl": timedelta(hours=6), + "parent-propagation-delay": timedelta(hours=1), + "publish-safety": timedelta(hours=1), + "purge-keys": timedelta(days=90), + "retire-safety": timedelta(hours=2), + "signatures-refresh": timedelta(days=5), + "signatures-validity": timedelta(days=30), + "zone-propagation-delay": timedelta(seconds=3600), + } + start_time = KeyTimingMetadata.now() # Test dynamic zones that switch to inline-signing. @@ -1396,6 +1409,37 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test algorithm rollover (KSK/ZSK split). + isctest.log.info("check algorithm rollover ksk/zsk split") + offset = -timedelta(days=7) + offval = int(offset.total_seconds()) + step = { + "zone": "step1.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "rsasha256", + "keyprops": [ + f"ksk 0 8 2048 goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offval}", + f"zsk 0 8 2048 goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + ], + "nextev": timedelta(hours=1), + } + steps.append(step) + + # Test algorithm rollover (CSK). + isctest.log.info("check algorithm rollover csk") + step = { + "zone": "step1.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + f"csk 0 8 2048 goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + ], + "nextev": timedelta(hours=1), + } + steps.append(step) + for step in steps: check_rollover_step(server, step["config"], step["policy"], step) @@ -1518,5 +1562,254 @@ def test_rollover_policy_changes(servers): } steps.append(step) + # Test algorithm rollover (KSK/ZSK split) (after reconfig). + isctest.log.info("check algorithm rollover ksk/zsk split (after reconfig)") + offset = -timedelta(days=7) + offval = int(offset.total_seconds()) + ipub = Ipub(algoroll_config) + ipubc = IpubC(algoroll_config, rollover=False) + iret = Iret(algoroll_config, rollover=False) + iretKSK = Iret(algoroll_config, zsk=False, ksk=True, rollover=False) + keyttlprop = ( + algoroll_config["dnskey-ttl"] + algoroll_config["zone-propagation-delay"] + ) + offsets = {} + offsets["step2"] = -int(ipub.total_seconds()) + offsets["step3"] = -int(iret.total_seconds()) + offsets["step4"] = offsets["step3"] - int(iretKSK.total_seconds()) + offsets["step5"] = offsets["step4"] - int(keyttlprop.total_seconds()) + offsets["step6"] = offsets["step5"] - int(iret.total_seconds()) + algo_steps = [ + { + # Step 1. + "zone": "step1.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The RSASHA keys are outroducing. + f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + # The ECDSAP256SHA256 keys are introducing. + f"ksk 0 {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured ds:hidden", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:rumoured zrrsig:rumoured", + ], + # Next key event is when the ecdsa256 keys have been propagated. + "nextev": ipub, + }, + { + # Step 2. + "zone": "step2.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The RSASHA keys are outroducing, but need to stay present + # until the new algorithm chain of trust has been established. + # Thus the expected key states of these keys stay the same. + f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + # The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is + # omnipresent, but the zone signatures are not. + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:hidden offset:{offsets['step2']}", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:rumoured offset:{offsets['step2']}", + ], + # Next key event is when all zone signatures are signed with the new + # algorithm. This is the max-zone-ttl plus zone propagation delay. But + # the publication interval has already passed. Also, prevent intermittent + # false positives on slow platforms by subtracting the time passed between + # key creation and invoking 'rndc reconfig'. + "nextev": ipubc - ipub - time_passed, + }, + { + # Step 3. + "zone": "step3.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The DS can be swapped. + f"ksk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{offval}", + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:rumoured offset:{offsets['step3']}", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step3']}", + ], + # Next key event is when the DS becomes OMNIPRESENT. This happens + # after the retire interval. + "nextev": iretKSK - time_passed, + }, + { + # Step 4. + "zone": "step4.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The old DS is HIDDEN, we can remove the old algorithm records. + f"ksk 0 8 2048 goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:unretentive zrrsig:unretentive offset:{offval}", + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step4']}", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step4']}", + ], + # Next key event is when the old DNSKEY becomes HIDDEN. + # This happens after the DNSKEY TTL plus zone propagation delay. + "nextev": keyttlprop, + }, + { + # Step 5. + "zone": "step5.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The DNSKEY becomes HIDDEN. + f"ksk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:hidden zrrsig:unretentive offset:{offval}", + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step5']}", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step5']}", + ], + # Next key event is when the RSASHA signatures become HIDDEN. + # This happens after the max-zone-ttl plus zone propagation delay + # minus the time already passed since the UNRETENTIVE state has + # been reached. Prevent intermittent false positives on slow + # platforms by subtracting the number of seconds which passed + # between key creation and invoking 'rndc reconfig'. + "nextev": iret - iretKSK - keyttlprop - time_passed, + }, + { + # Step 6. + "zone": "step6.algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "ecdsa256", + "keyprops": [ + # The zone signatures are now HIDDEN. + f"ksk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden ds:hidden offset:{offval}", + f"zsk 0 8 2048 goal:hidden dnskey:hidden zrrsig:hidden offset:{offval}", + f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{offsets['step6']}", + f"zsk 0 {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{offsets['step6']}", + ], + # Next key event is never since we established the policy and the + # keys have an unlimited lifetime. Fallback to the default + # loadkeys interval. + "nextev": timedelta(hours=1), + }, + ] + steps = steps + algo_steps + + # Test algorithm rollover (CSK) (after reconfig). + isctest.log.info("check algorithm rollover csk (after reconfig)") + offsets = {} + offsets["step2"] = -int(ipub.total_seconds()) + offsets["step3"] = -int(iret.total_seconds()) + offsets["step4"] = offsets["step3"] - int(iretKSK.total_seconds()) + offsets["step5"] = offsets["step4"] - int(keyttlprop.total_seconds()) + offsets["step6"] = offsets["step5"] - int(iret.total_seconds()) + algo_steps = [ + { + # Step 1. + "zone": "step1.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The RSASHA keys are outroducing. + f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + # The ECDSAP256SHA256 keys are introducing. + f"csk 0 {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden", + ], + # Next key event is when the ecdsa256 keys have been propagated. + "nextev": ipub, + }, + { + # Step 2. + "zone": "step2.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The RSASHA keys are outroducing, but need to stay present + # until the new algorithm chain of trust has been established. + # Thus the expected key states of these keys stay the same. + f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offval}", + # The ECDSAP256SHA256 keys are introducing. The DNSKEY RRset is + # omnipresent, but the zone signatures are not. + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{offsets['step2']}", + ], + # Next key event is when all zone signatures are signed with the + # new algorithm. This is the child publication interval, minus + # the publication interval has already passed. Also, prevent + # intermittent false positives on slow platforms by subtracting + # the time passed between key creation and invoking 'rndc reconfig'. + "nextev": ipubc - ipub - time_passed, + }, + { + # Step 3. + "zone": "step3.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The DS can be swapped. + f"csk 0 8 2048 goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:unretentive offset:{offval}", + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{offsets['step3']}", + ], + # Next key event is when the DS becomes OMNIPRESENT. This happens + # after the publication interval of the parent side. + "nextev": iretKSK - time_passed, + }, + { + # Step 4. + "zone": "step4.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The old DS is HIDDEN, we can remove the old algorithm records. + f"csk 0 8 2048 goal:hidden dnskey:unretentive krrsig:unretentive zrrsig:unretentive ds:hidden offset:{offval}", + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step4']}", + ], + # Next key event is when the old DNSKEY becomes HIDDEN. + # This happens after the DNSKEY TTL plus zone propagation delay. + "nextev": keyttlprop, + }, + { + # Step 5. + "zone": "step5.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The DNSKEY becomes HIDDEN. + f"csk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden zrrsig:unretentive ds:hidden offset:{offval}", + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step5']}", + ], + # Next key event is when the RSASHA signatures become HIDDEN. + # This happens after the max-zone-ttl plus zone propagation delay + # minus the time already passed since the UNRETENTIVE state has + # been reached. Prevent intermittent false positives on slow + # platforms by subtracting the number of seconds which passed + # between key creation and invoking 'rndc reconfig'. + "nextev": iret - iretKSK - keyttlprop - time_passed, + }, + { + # Step 6. + "zone": "step6.csk-algorithm-roll.kasp", + "cdss": cdss, + "config": algoroll_config, + "policy": "csk-algoroll", + "keyprops": [ + # The zone signatures are now HIDDEN. + f"csk 0 8 2048 goal:hidden dnskey:hidden krrsig:hidden zrrsig:hidden ds:hidden offset:{offval}", + f"csk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{offsets['step6']}", + ], + # Next key event is never since we established the policy and the + # keys have an unlimited lifetime. Fallback to the default + # loadkeys interval. + "nextev": timedelta(hours=1), + }, + ] + steps = steps + algo_steps + for step in steps: check_rollover_step(server, step["config"], step["policy"], step) From 546fdb9c2084c8dd244a53193a8670e796ca0c4c Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 19 Mar 2025 16:32:12 +0100 Subject: [PATCH 4/4] Remove kasp shell script remainders Now that all tests have been converted, we can remove 'kasp/tests.sh' and 'kasp/tests_sh_kasp.py'. (cherry picked from commit 6994a604a7943cccfb60d62a0a38ce8fa8f0e8ed) --- bin/tests/system/kasp/tests.sh | 89 -------------------------- bin/tests/system/kasp/tests_sh_kasp.py | 65 ------------------- 2 files changed, 154 deletions(-) delete mode 100644 bin/tests/system/kasp/tests.sh delete mode 100644 bin/tests/system/kasp/tests_sh_kasp.py diff --git a/bin/tests/system/kasp/tests.sh b/bin/tests/system/kasp/tests.sh deleted file mode 100644 index 2114fd08cf..0000000000 --- a/bin/tests/system/kasp/tests.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh - -# Copyright (C) Internet Systems Consortium, Inc. ("ISC") -# -# SPDX-License-Identifier: MPL-2.0 -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, you can obtain one at https://mozilla.org/MPL/2.0/. -# -# See the COPYRIGHT file distributed with this work for additional -# information regarding copyright ownership. - -set -e - -# shellcheck source=conf.sh -. ../conf.sh -# shellcheck source=kasp.sh -. ../kasp.sh - -start_time="$(TZ=UTC date +%s)" -status=0 -n=0 - -############################################################################### -# 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 ../_common/rndc.conf -p "$CONTROLPORT" -s "$@" -} - -# Log error and increment failure rate. -log_error() { - echo_i "error: $1" - ret=$((ret + 1)) -} - -# Default next key event threshold. May be extended by wait periods. -next_key_event_threshold=100 - -############################################################################### -# Tests # -############################################################################### - -# -# 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 an error. -n=$((n + 1)) -echo_i "waiting for kasp signing changes to take effect ($n)" -ret=0 - -_wait_for_done_apexnsec() { - while read -r zone; do - dig_with_opts "$zone" @10.53.0.3 nsec >"dig.out.ns3.test$n.$zone" || return 1 - grep "NS SOA" "dig.out.ns3.test$n.$zone" >/dev/null || return 1 - grep "$zone\..*IN.*RRSIG" "dig.out.ns3.test$n.$zone" >/dev/null || return 1 - done "dig.out.ns6.test$n.$zone" || return 1 - grep "NS SOA" "dig.out.ns6.test$n.$zone" >/dev/null || return 1 - grep "$zone\..*IN.*RRSIG" "dig.out.ns6.test$n.$zone" >/dev/null || return 1 - done