<<: *precheck_job
needs: []
script:
- - vulture --exclude "*ans.py,conftest.py,isctest" --ignore-names "pytestmark" bin/tests/system/
+ - vulture --exclude "*ans.py,conftest.py,isctest" --ignore-names "pytestmark,reconfigure_policy" bin/tests/system/
ci-variables:
<<: *precheck_job
--- /dev/null
+../rollover/common.py
\ No newline at end of file
--- /dev/null
+/*
+ * 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 "unsigning" {
+ dnskey-ttl 7200;
+
+ keys {
+ ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
+ zsk key-directory lifetime P60D algorithm @DEFAULT_ALGORITHM@;
+ };
+};
--- /dev/null
+../../rollover-dynamic2inline/ns6/named.common.conf.j2
\ No newline at end of file
--- /dev/null
+/*
+ * 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 policy = policy | default("unsigning") %}
+
+include "kasp.conf";
+include "named.common.conf";
+
+zone "step1.going-insecure.kasp" {
+ type primary;
+ file "step1.going-insecure.kasp.db";
+ dnssec-policy @policy@;
+};
+
+{% if policy == "insecure" %}
+zone "step2.going-insecure.kasp" {
+ type primary;
+ file "step2.going-insecure.kasp.db";
+ dnssec-policy insecure;
+};
+{% endif %}
+
+zone "step1.going-insecure-dynamic.kasp" {
+ type primary;
+ file "step1.going-insecure-dynamic.kasp.db";
+ dnssec-policy @policy@;
+ inline-signing no;
+ allow-update { any; };
+};
+
+{% if policy == "insecure" %}
+zone "step2.going-insecure-dynamic.kasp" {
+ type primary;
+ file "step2.going-insecure-dynamic.kasp.db";
+ dnssec-policy insecure;
+ inline-signing no;
+ allow-update { any; };
+};
+{% endif %}
--- /dev/null
+../../rollover-dynamic2inline/ns6/template.db.in
\ No newline at end of file
--- /dev/null
+#!/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
+
+cd "ns6"
+
+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 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
+done
--- /dev/null
+# 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.
+
+# pylint: disable=redefined-outer-name,unused-import
+
+import pytest
+
+import isctest
+from common import (
+ pytestmark,
+ alg,
+ size,
+ CDSS,
+ DURATION,
+ UNSIGNING_CONFIG,
+)
+
+
+@pytest.mark.parametrize(
+ "zone",
+ [
+ "going-insecure.kasp",
+ "going-insecure-dynamic.kasp",
+ ],
+)
+def test_going_insecure_initial(zone, servers, alg, size):
+ config = UNSIGNING_CONFIG
+ policy = "unsigning"
+ step = {
+ "zone": f"step1.{zone}",
+ "cdss": CDSS,
+ "keyprops": [
+ f"ksk 0 {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent offset:{-DURATION['P10D']}",
+ f"zsk {DURATION['P60D']} {alg} {size} goal:omnipresent dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}",
+ ],
+ "nextev": None,
+ }
+ isctest.kasp.check_rollover_step(servers["ns6"], config, policy, step)
--- /dev/null
+# 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.
+
+# pylint: disable=redefined-outer-name,unused-import
+
+import pytest
+
+import isctest
+from common import (
+ pytestmark,
+ alg,
+ size,
+ CDSS,
+ DEFAULT_CONFIG,
+ DURATION,
+ UNSIGNING_CONFIG,
+)
+
+
+@pytest.fixture(scope="module", autouse=True)
+def reconfigure_policy(servers, templates):
+ templates.render("ns6/named.conf", {"policy": "insecure"})
+ servers["ns6"].reconfigure()
+
+
+@pytest.mark.parametrize(
+ "zone",
+ [
+ "going-insecure.kasp",
+ "going-insecure-dynamic.kasp",
+ ],
+)
+def test_going_insecure_reconfig_step1(zone, alg, size, servers):
+ config = DEFAULT_CONFIG
+ policy = "insecure"
+
+ # Key goal states should be HIDDEN.
+ # The DS may be removed if we are going insecure.
+ step = {
+ "zone": f"step1.{zone}",
+ "cdss": CDSS,
+ "keyprops": [
+ f"ksk 0 {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{-DURATION['P10D']}",
+ f"zsk {DURATION['P60D']} {alg} {size} goal:hidden dnskey:omnipresent zrrsig:omnipresent offset:{-DURATION['P10D']}",
+ ],
+ # 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,
+ }
+ isctest.kasp.check_rollover_step(servers["ns6"], config, policy, step)
+
+
+@pytest.mark.parametrize(
+ "zone",
+ [
+ "going-insecure.kasp",
+ "going-insecure-dynamic.kasp",
+ ],
+)
+def test_going_insecure_reconfig_step2(zone, alg, size, servers):
+ config = DEFAULT_CONFIG
+ policy = "insecure"
+
+ # 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.{zone}",
+ "cdss": CDSS,
+ "keyprops": [
+ f"ksk 0 {alg} {size} goal:hidden dnskey:unretentive krrsig:unretentive ds:hidden offset:{-DURATION['P10D']}",
+ f"zsk {DURATION['P60D']} {alg} {size} goal:hidden dnskey:unretentive zrrsig:unretentive offset:{-DURATION['P10D']}",
+ ],
+ # Next key event is when the DNSKEY becomes HIDDEN.
+ # This happens after the propagation delay, plus DNSKEY TTL.
+ "nextev": UNSIGNING_CONFIG["dnskey-ttl"]
+ + DEFAULT_CONFIG["zone-propagation-delay"],
+ # Zone is no longer signed.
+ "zone-signed": False,
+ "check-keytimes": False,
+ }
+ isctest.kasp.check_rollover_step(servers["ns6"], config, policy, step)
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
+from datetime import timedelta
+import os
+
import pytest
pytestmark = pytest.mark.extra_artifacts(
"ns*/zones",
]
)
+
+
+TIMEDELTA = {
+ "PT5M": timedelta(minutes=5),
+ "PT1H": timedelta(hours=1),
+ "PT2H": timedelta(hours=2),
+ "P1D": timedelta(days=1),
+ "P5D": timedelta(days=5),
+ "P10D": timedelta(days=10),
+ "P14D": timedelta(days=14),
+ "P60D": timedelta(days=60),
+ "P90D": timedelta(days=90),
+ "P6M": timedelta(days=31 * 6),
+ "P1Y": timedelta(days=365),
+}
+DURATION = {isoname: int(delta.total_seconds()) for isoname, delta in TIMEDELTA.items()}
+CDSS = ["CDNSKEY", "CDS (SHA-256)"]
+DEFAULT_CONFIG = {
+ "dnskey-ttl": TIMEDELTA["PT1H"],
+ "ds-ttl": TIMEDELTA["P1D"],
+ "max-zone-ttl": TIMEDELTA["P1D"],
+ "parent-propagation-delay": TIMEDELTA["PT1H"],
+ "publish-safety": TIMEDELTA["PT1H"],
+ "purge-keys": TIMEDELTA["P90D"],
+ "retire-safety": TIMEDELTA["PT1H"],
+ "signatures-refresh": TIMEDELTA["P5D"],
+ "signatures-validity": TIMEDELTA["P14D"],
+ "zone-propagation-delay": TIMEDELTA["PT5M"],
+}
+UNSIGNING_CONFIG = DEFAULT_CONFIG.copy()
+UNSIGNING_CONFIG["dnskey-ttl"] = TIMEDELTA["PT2H"]
+
+
+@pytest.fixture
+def alg():
+ return os.environ["DEFAULT_ALGORITHM_NUMBER"]
+
+
+@pytest.fixture
+def size():
+ return os.environ["DEFAULT_BITS"]
dnssec-policy @_policy@;
};
-/* Zones for testing going insecure. */
-{% set _policy = "unsigning" if not csk_roll else "insecure" %}
-zone "step1.going-insecure.kasp" {
- type primary;
- file "step1.going-insecure.kasp.db";
- dnssec-policy @_policy@;
-};
-
-{% if csk_roll %} // TODO maybe omit?
-zone "step2.going-insecure.kasp" {
- type primary;
- file "step2.going-insecure.kasp.db";
- dnssec-policy "insecure";
-};
-{% endif %}
-
-{% set _policy = "unsigning" if not csk_roll else "insecure" %}
-zone "step1.going-insecure-dynamic.kasp" {
- type primary;
- file "step1.going-insecure-dynamic.kasp.db";
- dnssec-policy @_policy@;
- inline-signing no;
- allow-update { any; };
-};
-
-{% if csk_roll %} // TODO maybe omit?
-zone "step2.going-insecure-dynamic.kasp" {
- type primary;
- file "step2.going-insecure-dynamic.kasp.db";
- dnssec-policy insecure;
- inline-signing no;
- allow-update { any; };
-};
-{% endif %}
-
{% set _policy = "default" if not csk_roll else "none" %}
zone "step1.going-straight-to-none.kasp" {
type primary;
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"
}
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 = [
}
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 = [