From: Nicki Křížek Date: Thu, 5 Jun 2025 15:51:40 +0000 (+0200) Subject: Isolate rollover-going-insecure test case X-Git-Tag: v9.21.11~38^2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7001056eabdee147ab51d5a8ca99aa6904e17c7f;p=thirdparty%2Fbind9.git Isolate rollover-going-insecure test case --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 761abb77470..a06ae9b094e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -548,7 +548,7 @@ vulture: <<: *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 diff --git a/bin/tests/system/rollover-going-insecure/common.py b/bin/tests/system/rollover-going-insecure/common.py new file mode 120000 index 00000000000..64b8084c5ac --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/common.py @@ -0,0 +1 @@ +../rollover/common.py \ No newline at end of file diff --git a/bin/tests/system/rollover-going-insecure/ns6/kasp.conf.j2 b/bin/tests/system/rollover-going-insecure/ns6/kasp.conf.j2 new file mode 100644 index 00000000000..70a4323c7e2 --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/ns6/kasp.conf.j2 @@ -0,0 +1,21 @@ +/* + * 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@; + }; +}; diff --git a/bin/tests/system/rollover-going-insecure/ns6/named.common.conf.j2 b/bin/tests/system/rollover-going-insecure/ns6/named.common.conf.j2 new file mode 120000 index 00000000000..6b841ab2ad3 --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/ns6/named.common.conf.j2 @@ -0,0 +1 @@ +../../rollover-dynamic2inline/ns6/named.common.conf.j2 \ No newline at end of file diff --git a/bin/tests/system/rollover-going-insecure/ns6/named.conf.j2 b/bin/tests/system/rollover-going-insecure/ns6/named.conf.j2 new file mode 100644 index 00000000000..add98259130 --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/ns6/named.conf.j2 @@ -0,0 +1,49 @@ +/* + * 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 %} diff --git a/bin/tests/system/rollover-going-insecure/ns6/template.db.in b/bin/tests/system/rollover-going-insecure/ns6/template.db.in new file mode 120000 index 00000000000..21598660d1e --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/ns6/template.db.in @@ -0,0 +1 @@ +../../rollover-dynamic2inline/ns6/template.db.in \ No newline at end of file diff --git a/bin/tests/system/rollover-going-insecure/setup.sh b/bin/tests/system/rollover-going-insecure/setup.sh new file mode 100644 index 00000000000..f5d9da48a7e --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/setup.sh @@ -0,0 +1,71 @@ +#!/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 diff --git a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py new file mode 100644 index 00000000000..60119582095 --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_initial.py @@ -0,0 +1,46 @@ +# 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) diff --git a/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py new file mode 100644 index 00000000000..a783f4fb174 --- /dev/null +++ b/bin/tests/system/rollover-going-insecure/tests_rollover_going_insecure_reconfig.py @@ -0,0 +1,93 @@ +# 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) diff --git a/bin/tests/system/rollover/common.py b/bin/tests/system/rollover/common.py index aa51060c414..543359e3d8e 100644 --- a/bin/tests/system/rollover/common.py +++ b/bin/tests/system/rollover/common.py @@ -9,6 +9,9 @@ # 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( @@ -34,3 +37,44 @@ 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"] diff --git a/bin/tests/system/rollover/ns6/named.conf.j2 b/bin/tests/system/rollover/ns6/named.conf.j2 index 2e77a17d4f8..c626875354c 100644 --- a/bin/tests/system/rollover/ns6/named.conf.j2 +++ b/bin/tests/system/rollover/ns6/named.conf.j2 @@ -50,41 +50,6 @@ zone unlimit-lifetime { 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; diff --git a/bin/tests/system/rollover/ns6/setup.sh b/bin/tests/system/rollover/ns6/setup.sh index 5e059424ffe..31023687fa3 100644 --- a/bin/tests/system/rollover/ns6/setup.sh +++ b/bin/tests/system/rollover/ns6/setup.sh @@ -35,48 +35,6 @@ for zn in shorter-lifetime longer-lifetime limit-lifetime \ 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" diff --git a/bin/tests/system/rollover/tests_rollover.py b/bin/tests/system/rollover/tests_rollover.py index 5f72f06bf5b..6ac80d7247c 100644 --- a/bin/tests/system/rollover/tests_rollover.py +++ b/bin/tests/system/rollover/tests_rollover.py @@ -1203,28 +1203,6 @@ def test_rollover_policy_changes(servers, templates): } 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 = [ @@ -1322,57 +1300,6 @@ def test_rollover_policy_changes(servers, templates): } 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 = [