2025-06-11 16:26:37 +02:00
|
|
|
# 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
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
import pytest
|
|
|
|
|
2025-06-11 16:26:37 +02:00
|
|
|
import isctest
|
|
|
|
from isctest.kasp import Ipub, IpubC, Iret
|
2025-07-24 14:57:35 +02:00
|
|
|
from isctest.util import param
|
2025-08-04 16:30:41 +02:00
|
|
|
from rollover.common import (
|
2025-06-11 16:26:37 +02:00
|
|
|
pytestmark,
|
|
|
|
alg,
|
|
|
|
size,
|
|
|
|
CDSS,
|
|
|
|
TIMEDELTA,
|
|
|
|
)
|
|
|
|
|
|
|
|
CONFIG = {
|
|
|
|
"dnskey-ttl": TIMEDELTA["PT5M"],
|
|
|
|
"ds-ttl": TIMEDELTA["PT2H"],
|
|
|
|
"max-zone-ttl": TIMEDELTA["PT12H"],
|
|
|
|
"parent-propagation-delay": TIMEDELTA["PT1H"],
|
|
|
|
"publish-safety": TIMEDELTA["PT5M"],
|
|
|
|
"retire-safety": TIMEDELTA["PT20M"],
|
|
|
|
"signatures-refresh": TIMEDELTA["P7D"],
|
|
|
|
"signatures-validity": TIMEDELTA["P14D"],
|
|
|
|
"zone-propagation-delay": TIMEDELTA["PT5M"],
|
|
|
|
}
|
|
|
|
POLICY = "enable-dnssec"
|
|
|
|
IPUB = Ipub(CONFIG)
|
|
|
|
IPUBC = IpubC(CONFIG, rollover=False)
|
|
|
|
IRETZSK = Iret(CONFIG, rollover=False)
|
|
|
|
IRETKSK = Iret(CONFIG, zsk=False, ksk=True, rollover=False)
|
|
|
|
OFFSETS = {}
|
|
|
|
OFFSETS["step1"] = 0
|
|
|
|
OFFSETS["step2"] = -int(IPUB.total_seconds())
|
|
|
|
OFFSETS["step3"] = -int(IRETZSK.total_seconds())
|
|
|
|
OFFSETS["step4"] = -int(IPUBC.total_seconds() + IRETKSK.total_seconds())
|
|
|
|
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"tld",
|
|
|
|
[
|
|
|
|
param("autosign"),
|
|
|
|
param("manual"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_rollover_enable_dnssec_step1(tld, alg, size, ns3):
|
|
|
|
zone = f"step1.enable-dnssec.{tld}"
|
|
|
|
policy = f"{POLICY}-{tld}"
|
2025-07-08 13:46:01 +02:00
|
|
|
|
|
|
|
isctest.kasp.wait_keymgr_done(ns3, zone)
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
if tld == "manual":
|
|
|
|
# Same as insecure.
|
|
|
|
step = {
|
|
|
|
"zone": zone,
|
|
|
|
"cdss": CDSS,
|
|
|
|
"keyprops": [],
|
|
|
|
"manual-mode": True,
|
|
|
|
"zone-signed": False,
|
|
|
|
"nextev": None,
|
|
|
|
}
|
|
|
|
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|
|
|
|
|
|
|
|
# Check logs.
|
|
|
|
msg = f"keymgr-manual-mode: block new key generation for zone {zone} (policy {policy})"
|
|
|
|
ns3.log.expect(msg)
|
|
|
|
|
|
|
|
# Force step.
|
|
|
|
with ns3.watch_log_from_here() as watcher:
|
|
|
|
ns3.rndc(f"dnssec -step {zone}")
|
|
|
|
watcher.wait_for_line(f"keymgr: {zone} done")
|
|
|
|
|
2025-06-11 16:26:37 +02:00
|
|
|
step = {
|
2025-07-08 13:46:01 +02:00
|
|
|
"zone": zone,
|
2025-06-11 16:26:37 +02:00
|
|
|
"cdss": CDSS,
|
|
|
|
"keyprops": [
|
|
|
|
f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{OFFSETS['step1']}",
|
|
|
|
],
|
|
|
|
# Next key event is when the DNSKEY RRset becomes OMNIPRESENT,
|
|
|
|
# after the publication interval.
|
|
|
|
"nextev": IPUB,
|
|
|
|
}
|
2025-07-24 14:57:35 +02:00
|
|
|
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|
2025-06-11 16:26:37 +02:00
|
|
|
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"tld",
|
|
|
|
[
|
|
|
|
param("autosign"),
|
|
|
|
param("manual"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_rollover_enable_dnssec_step2(tld, alg, size, ns3):
|
|
|
|
zone = f"step2.enable-dnssec.{tld}"
|
|
|
|
policy = f"{POLICY}-{tld}"
|
2025-07-08 13:46:01 +02:00
|
|
|
|
|
|
|
isctest.kasp.wait_keymgr_done(ns3, zone)
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
# manual-mode: Nothing changing in the zone, no 'dnssec -step' required.
|
|
|
|
|
2025-06-11 16:26:37 +02:00
|
|
|
step = {
|
2025-07-08 13:46:01 +02:00
|
|
|
"zone": zone,
|
2025-06-11 16:26:37 +02:00
|
|
|
"cdss": CDSS,
|
|
|
|
# The DNSKEY is omnipresent, but the zone signatures not yet.
|
|
|
|
# Thus, the DS remains hidden.
|
|
|
|
# dnskey: rumoured -> omnipresent
|
|
|
|
# krrsig: rumoured -> omnipresent
|
|
|
|
"keyprops": [
|
|
|
|
f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{OFFSETS['step2']}",
|
|
|
|
],
|
|
|
|
# Next key event is when the zone signatures become OMNIPRESENT,
|
|
|
|
# Minus the time already elapsed.
|
|
|
|
"nextev": IRETZSK - IPUB,
|
|
|
|
}
|
2025-07-24 14:57:35 +02:00
|
|
|
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|
2025-06-11 16:26:37 +02:00
|
|
|
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"tld",
|
|
|
|
[
|
|
|
|
param("autosign"),
|
|
|
|
param("manual"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_rollover_enable_dnssec_step3(tld, alg, size, ns3):
|
|
|
|
zone = f"step3.enable-dnssec.{tld}"
|
|
|
|
policy = f"{POLICY}-{tld}"
|
2025-07-08 13:46:01 +02:00
|
|
|
|
|
|
|
isctest.kasp.wait_keymgr_done(ns3, zone)
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
if tld == "manual":
|
|
|
|
# Same as step 2, but zone signatures have become OMNIPRESENT.
|
|
|
|
step = {
|
|
|
|
"zone": zone,
|
|
|
|
"cdss": CDSS,
|
|
|
|
"keyprops": [
|
|
|
|
f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{OFFSETS['step3']}",
|
|
|
|
],
|
|
|
|
"manual-mode": True,
|
|
|
|
"nextev": None,
|
|
|
|
}
|
|
|
|
keys = isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|
|
|
|
|
|
|
|
# Check logs.
|
|
|
|
tag = keys[0].key.tag
|
|
|
|
msg = f"keymgr-manual-mode: block transition CSK {zone}/ECDSAP256SHA256/{tag} type DS state HIDDEN to state RUMOURED"
|
|
|
|
ns3.log.expect(msg)
|
|
|
|
|
|
|
|
# Force step.
|
|
|
|
with ns3.watch_log_from_here() as watcher:
|
|
|
|
ns3.rndc(f"dnssec -step {zone}")
|
|
|
|
watcher.wait_for_line(f"keymgr: {zone} done")
|
|
|
|
|
2025-06-11 16:26:37 +02:00
|
|
|
step = {
|
2025-07-08 13:46:01 +02:00
|
|
|
"zone": zone,
|
2025-06-11 16:26:37 +02:00
|
|
|
"cdss": CDSS,
|
|
|
|
# All signatures should be omnipresent, so the DS can be submitted.
|
|
|
|
# zrrsig: rumoured -> omnipresent
|
|
|
|
# ds: hidden -> rumoured
|
|
|
|
"keyprops": [
|
|
|
|
f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step3']}",
|
|
|
|
],
|
|
|
|
# Next key event is when the DS can move to the OMNIPRESENT state.
|
|
|
|
# This is after the retire interval.
|
|
|
|
"nextev": IRETKSK,
|
|
|
|
}
|
2025-07-24 14:57:35 +02:00
|
|
|
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|
2025-06-11 16:26:37 +02:00
|
|
|
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
"tld",
|
|
|
|
[
|
|
|
|
param("autosign"),
|
|
|
|
param("manual"),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
def test_rollover_enable_dnssec_step4(tld, alg, size, ns3):
|
|
|
|
zone = f"step4.enable-dnssec.{tld}"
|
|
|
|
policy = f"{POLICY}-{tld}"
|
2025-07-08 13:46:01 +02:00
|
|
|
|
|
|
|
isctest.kasp.wait_keymgr_done(ns3, zone)
|
|
|
|
|
2025-07-24 14:57:35 +02:00
|
|
|
# manual-mode: Nothing changing in the zone, no 'dnssec -step' required.
|
|
|
|
|
2025-06-11 16:26:37 +02:00
|
|
|
step = {
|
2025-07-08 13:46:01 +02:00
|
|
|
"zone": zone,
|
2025-06-11 16:26:37 +02:00
|
|
|
"cdss": CDSS,
|
|
|
|
# DS has been published long enough.
|
|
|
|
# ds: rumoured -> omnipresent
|
|
|
|
"keyprops": [
|
|
|
|
f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4']}",
|
|
|
|
],
|
|
|
|
# Next key event is never, the zone dnssec-policy has been
|
|
|
|
# established. So we fall back to the default loadkeys interval.
|
|
|
|
"nextev": TIMEDELTA["PT1H"],
|
|
|
|
}
|
2025-07-24 14:57:35 +02:00
|
|
|
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
|