Add NSEC3-to-NSEC rollover regression test

Before this commit, the NSEC3-to-NSEC transition was only tested by
test_nsec_case[nsec3-to-rsasha1-ds.kasp], which is gated by
RSASHA1_SUPPORTED.

Add another test that does not depend on RSASHA1_SUPPORTED, so this
coverage also runs when RSASHA1 signing is unavailable, such as with
newer OpenSSL configurations.
This commit is contained in:
Alessio Podda 2026-05-19 00:03:32 +02:00
parent f2562548c8
commit 0bb6cd432c
5 changed files with 68 additions and 5 deletions

View file

@ -25,6 +25,12 @@ dnssec-policy "nsec" {
// NSEC will be used;
};
dnssec-policy "nsec-altalg" {
keys {
csk lifetime unlimited algorithm @ALTERNATIVE_ALGORITHM@;
};
};
dnssec-policy "nsec3" {
nsec3param;
};
@ -36,4 +42,3 @@ dnssec-policy "optout" {
dnssec-policy "nsec3-other" {
nsec3param iterations 0 optout yes salt-length 8;
};

View file

@ -1,6 +1,7 @@
{% set reconfiged = reconfiged | default(False) %}
{% set nsec_to_nsec3 = "nsec" if not reconfiged else "nsec3" %}
{% set nsec3_to_nsec = "nsec3" if not reconfiged else "nsec" %}
{% set nsec3_to_nsec_altalg = "nsec3" if not reconfiged else "nsec-altalg" %}
{% set nsec3_change = "nsec3" if not reconfiged else "nsec3-other" %}
{% set nsec3_from_optout = "optout" if not reconfiged else "nsec3" %}
{% set nsec3_to_optout = "nsec3" if not reconfiged else "optout" %}
@ -87,6 +88,18 @@ zone "nsec3-to-nsec.kasp" {
};
{% endif %}{# nsec3-to-nsec.kasp #}
{% if "nsec3-to-nsec-altalg.kasp" in zones %}
/*
* The zone starts with NSEC3, but will be reconfigured to use NSEC while
* rolling to the alternative DNSSEC algorithm.
*/
zone "nsec3-to-nsec-altalg.kasp" {
type primary;
file "nsec3-to-nsec-altalg.kasp.db";
dnssec-policy "@nsec3_to_nsec_altalg@";
};
{% endif %}{# nsec3-to-nsec-altalg.kasp #}
{% if "nsec3-fails-to-load.kasp" in zones %}
/*
* The zone fails to load, this should not prevent shutdown.

View file

@ -30,11 +30,16 @@ for zn in nsec-to-nsec3 nsec3 nsec3-other nsec3-change nsec3-to-nsec \
setup "${zn}.kasp"
done
if [ $RSASHA1_SUPPORTED = 1 ]; then
longago="now-1y"
keytimes="-P ${longago} -A ${longago} -P sync ${longago}"
O="omnipresent"
longago="now-1y"
keytimes="-P ${longago} -A ${longago} -P sync ${longago}"
O="omnipresent"
setup "nsec3-to-nsec-altalg.kasp"
CSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone)
$SETTIME -s -g $O -k $O $longago -r $O $longago -z $O $longago -d $O $longago "$CSK" >settime.out.$zone 2>&1
cat $CSK.key >>$zonefile
if [ $RSASHA1_SUPPORTED = 1 ]; then
for zn in nsec3-to-rsasha1 nsec3-to-rsasha1-ds; do
setup "${zn}.kasp"
CSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -f KSK $keytimes $zone 2>keygen.out.$zone)

View file

@ -37,6 +37,7 @@ ZONES = {
"nsec3-dynamic-to-inline.kasp",
"nsec3-inline-to-dynamic.kasp",
"nsec3-to-nsec.kasp",
"nsec3-to-nsec-altalg.kasp",
"nsec3-to-optout.kasp",
"nsec3-from-optout.kasp",
"nsec3-other.kasp",
@ -245,6 +246,16 @@ def test_nsec_case(ns3, params):
},
id="nsec3-to-nsec.kasp",
),
pytest.param(
{
"zone": "nsec3-to-nsec-altalg.kasp",
"policy": "nsec3",
"key-properties": [
f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent",
],
},
id="nsec3-to-nsec-altalg.kasp",
),
pytest.param(
{
"zone": "nsec3-to-optout.kasp",

View file

@ -29,6 +29,7 @@ pytestmark = NSEC3_MARK
# include the following zones when rendering named configs
ZONES = {
"nsec3-to-nsec.kasp",
"nsec3-to-nsec-altalg.kasp",
"nsec-to-nsec3.kasp",
"nsec3.kasp",
"nsec3-dynamic.kasp",
@ -52,6 +53,18 @@ if os.environ["RSASHA1_SUPPORTED"] == "1":
)
def _algorithm_from_env(prefix):
return Algorithm(
os.environ[f"{prefix}_ALGORITHM"],
int(os.environ[f"{prefix}_ALGORITHM_NUMBER"]),
int(os.environ[f"{prefix}_ALGORITHM_DST_NUMBER"]),
int(os.environ[f"{prefix}_BITS"]),
)
ALTERNATIVE = _algorithm_from_env("ALTERNATIVE")
def bootstrap():
return {
"zones": ZONES,
@ -74,6 +87,10 @@ def after_servers_start(ns3, templates):
zone = "rsasha1-to-nsec3-wait.kasp"
isctest.kasp.check_dnssec_verify(ns3, zone)
# Ensure the old NSEC3 chain and default-algorithm signatures are fully
# established before the NSEC plus algorithm rollover begins.
isctest.kasp.check_dnssec_verify(ns3, "nsec3-to-nsec-altalg.kasp")
# Reconfigure.
data = {
"reconfiged": True,
@ -145,6 +162,18 @@ def after_servers_start(ns3, templates):
},
id="nsec3-to-nsec.kasp",
),
pytest.param(
{
"zone": "nsec3-to-nsec-altalg.kasp",
"policy": "nsec-altalg",
"key-properties": [
f"csk 0 {Algorithm.default().number} {Algorithm.default().bits} goal:hidden dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent",
f"csk 0 {ALTERNATIVE.number} {ALTERNATIVE.bits} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden",
],
},
id="nsec3-to-nsec-altalg.kasp",
marks=isctest.mark.with_algorithm(ALTERNATIVE.name),
),
],
)
def test_nsec_case(ns3, params):