mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-23 10:37:43 -04:00
This Class sets settime parameters and these can be called with key.settime() that runs dnssec-settime on the given key with the given parameters.
2339 lines
82 KiB
Python
2339 lines
82 KiB
Python
# 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.
|
||
|
||
import shutil
|
||
from typing import List
|
||
|
||
import isctest
|
||
from isctest.kasp import private_type_record, SettimeOptions
|
||
from isctest.template import Nameserver, TrustAnchor, Zone
|
||
from isctest.run import EnvCmd
|
||
from rollover.common import default_algorithm
|
||
|
||
|
||
def configure_tld(zonename: str, delegations: List[Zone]) -> Zone:
|
||
templates = isctest.template.TemplateEngine(".")
|
||
alg = default_algorithm()
|
||
keygen = EnvCmd("KEYGEN", f"-q -a {alg.number} -b {alg.bits} -L 3600")
|
||
signer = EnvCmd("SIGNER", "-S -g")
|
||
|
||
isctest.log.info(f"create {zonename} zone with delegations and sign")
|
||
|
||
for zone in delegations:
|
||
try:
|
||
shutil.copy(f"{zone.ns.name}/dsset-{zone.name}.", "ns2/")
|
||
except FileNotFoundError:
|
||
# Some delegations are unsigned.
|
||
pass
|
||
|
||
ksk_name = keygen(f"-f KSK {zonename}", cwd="ns2").out.strip()
|
||
zsk_name = keygen(f"{zonename}", cwd="ns2").out.strip()
|
||
ksk = isctest.kasp.Key(ksk_name, keydir="ns2")
|
||
zsk = isctest.kasp.Key(zsk_name, keydir="ns2")
|
||
dnskeys = [ksk.dnskey, zsk.dnskey]
|
||
|
||
template = "template.db.j2.manual"
|
||
outfile = f"{zonename}.db"
|
||
tdata = {
|
||
"fqdn": f"{zonename}.",
|
||
"delegations": delegations,
|
||
"dnskeys": dnskeys,
|
||
}
|
||
templates.render(f"ns2/{outfile}", tdata, template=f"ns2/{template}")
|
||
signer(f"-P -x -O full -o {zonename} -f {outfile}.signed {outfile}", cwd="ns2")
|
||
|
||
return Zone(zonename, f"{outfile}.signed", Nameserver("ns2", "10.53.0.2"))
|
||
|
||
|
||
def configure_root(delegations: List[Zone]) -> TrustAnchor:
|
||
templates = isctest.template.TemplateEngine(".")
|
||
alg = default_algorithm()
|
||
keygen = EnvCmd("KEYGEN", f"-q -a {alg.number} -b {alg.bits} -L 3600")
|
||
signer = EnvCmd("SIGNER", "-S -g")
|
||
|
||
zonename = "."
|
||
isctest.log.info("create root zone with delegations and sign")
|
||
|
||
for zone in delegations:
|
||
shutil.copy(f"{zone.ns.name}/dsset-{zone.name}.", "ns1/")
|
||
|
||
ksk_name = keygen(f"-f KSK {zonename}", cwd="ns1").out.strip()
|
||
zsk_name = keygen(f"{zonename}", cwd="ns1").out.strip()
|
||
ksk = isctest.kasp.Key(ksk_name, keydir="ns1")
|
||
zsk = isctest.kasp.Key(zsk_name, keydir="ns1")
|
||
dnskeys = [ksk.dnskey, zsk.dnskey]
|
||
|
||
template = "root.db.j2.manual"
|
||
infile = "root.db.in"
|
||
outfile = "root.db.signed"
|
||
tdata = {
|
||
"fdqn": f"{zonename}.",
|
||
"delegations": delegations,
|
||
"dnskeys": dnskeys,
|
||
}
|
||
templates.render(f"ns1/{infile}", tdata, template=f"ns1/{template}")
|
||
signer(f"-P -x -O full -o {zonename} -f {outfile} {infile}", cwd="ns1")
|
||
|
||
return ksk.into_ta("static-ds")
|
||
|
||
|
||
def fake_lifetime(key: str, lifetime: int):
|
||
"""
|
||
Fake lifetime of key.
|
||
"""
|
||
with open(f"ns3/{key}.state", "a", encoding="utf-8") as statefile:
|
||
statefile.write(f"Lifetime: {lifetime}\n")
|
||
|
||
|
||
def set_key_relationship(key1: str, key2: str):
|
||
"""
|
||
Set in the key state files the Predecessor/Successor fields.
|
||
"""
|
||
predecessor = isctest.kasp.Key(key1, keydir="ns3")
|
||
successor = isctest.kasp.Key(key2, keydir="ns3")
|
||
|
||
with open(f"ns3/{key1}.state", "a", encoding="utf-8") as statefile:
|
||
statefile.write(f"Successor: {successor.tag}\n")
|
||
|
||
with open(f"ns3/{key2}.state", "a", encoding="utf-8") as statefile:
|
||
statefile.write(f"Predecessor: {predecessor.tag}\n")
|
||
|
||
|
||
def setkeytimes(key_name: str, options: SettimeOptions):
|
||
key = isctest.kasp.Key(key_name, keydir="ns3")
|
||
key.settime(options)
|
||
|
||
|
||
def render_and_sign_zone(
|
||
zonename: str, keys: List[str], signing: bool = True, extra_options: str = ""
|
||
):
|
||
dnskeys = []
|
||
privaterrs = []
|
||
for key_name in keys:
|
||
key = isctest.kasp.Key(key_name, keydir="ns3")
|
||
privaterr = private_type_record(zonename, key)
|
||
dnskeys.append(key.dnskey)
|
||
privaterrs.append(privaterr)
|
||
|
||
outfile = f"{zonename}.db"
|
||
templates = isctest.template.TemplateEngine(".")
|
||
template = "template.db.j2.manual"
|
||
tdata = {
|
||
"fqdn": f"{zonename}.",
|
||
"dnskeys": dnskeys,
|
||
"privaterrs": privaterrs,
|
||
}
|
||
templates.render(f"ns3/{outfile}", tdata, template=f"ns3/{template}")
|
||
|
||
if signing:
|
||
signer = EnvCmd("SIGNER", "-S -g -x -s now-1h -e now+2w -O raw")
|
||
signer(
|
||
f"{extra_options} -o {zonename} -f {outfile}.signed {outfile}", cwd="ns3"
|
||
)
|
||
|
||
|
||
def configure_algo_csk(tld: str, policy: str, reconfig: bool = False) -> List[Zone]:
|
||
# The zones at csk-algorithm-roll.$tld represent the various steps
|
||
# of a CSK algorithm rollover.
|
||
zones = []
|
||
zone = f"csk-algorithm-roll.{tld}"
|
||
keygen = EnvCmd("KEYGEN", f"-k {policy}")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
TactN = "now-7d"
|
||
TsbmN = "now-161h"
|
||
csktimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z")
|
||
|
||
if reconfig:
|
||
# Step 2:
|
||
# After the publication interval has passed the DNSKEY is OMNIPRESENT.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the new algorithm keys have been introduced is 3 hours.
|
||
TpubN1 = "now-3h"
|
||
csktimes = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I now"
|
||
newtimes = f"-P {TpubN1} -A {TpubN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"-l csk2.conf {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options="-z")
|
||
|
||
# Step 3:
|
||
# The zone signatures are also OMNIPRESENT.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the new algorithm keys have been introduced is 7 hours.
|
||
TpubN1 = "now-7h"
|
||
TsbmN1 = "now"
|
||
csktimes = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
newtimes = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"-l csk2.conf {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options="-z")
|
||
|
||
# Step 4:
|
||
# The DS is swapped and can become OMNIPRESENT.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the DS has been swapped is 3 hours.
|
||
TpubN1 = "now-10h"
|
||
TsbmN1 = "now-3h"
|
||
csktimes = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
newtimes = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"-l csk2.conf {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TsbmN1}",
|
||
d=f"UNRETENTIVE {TsbmN1}",
|
||
D_ds=f"{TsbmN1}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
z=f"OMNIPRESENT {TsbmN1}",
|
||
d=f"RUMOURED {TsbmN1}",
|
||
P_ds=f"{TsbmN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options="-z")
|
||
|
||
# Step 5:
|
||
# The DNSKEY is removed long enough to be HIDDEN.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the DNSKEY has been removed is 2 hours.
|
||
TpubN1 = "now-12h"
|
||
TsbmN1 = "now-5h"
|
||
csktimes = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
newtimes = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"-l csk2.conf {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TactN}",
|
||
r=f"UNRETENTIVE {TactN}",
|
||
z=f"UNRETENTIVE {TsbmN1}",
|
||
d=f"HIDDEN {TsbmN1}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
z=f"OMNIPRESENT {TsbmN1}",
|
||
d=f"OMNIPRESENT {TsbmN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options="-z")
|
||
|
||
# Step 6:
|
||
# The RRSIGs have been removed long enough to be HIDDEN.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Additional time passed: 7h.
|
||
TpubN1 = "now-19h"
|
||
TsbmN1 = "now-12h"
|
||
csktimes = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
newtimes = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"-l csk1.conf {csktimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"-l csk2.conf {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TactN}",
|
||
r=f"UNRETENTIVE {TactN}",
|
||
z=f"UNRETENTIVE {TactN}",
|
||
d=f"HIDDEN {TsbmN1}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
z=f"OMNIPRESENT {TsbmN1}",
|
||
d=f"OMNIPRESENT {TsbmN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options="-z")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_algo_ksk_zsk(tld: str, reconfig: bool = False) -> List[Zone]:
|
||
# The zones at algorithm-roll.$tld represent the various steps of a ZSK/KSK
|
||
# algorithm rollover.
|
||
zones = []
|
||
zone = f"algorithm-roll.{tld}"
|
||
keygen = EnvCmd("KEYGEN", "-L 3600")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
TactN = "now-7d"
|
||
TsbmN = "now-161h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
ksk_name = keygen(
|
||
f"-a RSASHA256 -f KSK {keytimes} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk_name = keygen(f"-a RSASHA256 {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name])
|
||
|
||
if reconfig:
|
||
# Step 2:
|
||
# After the publication interval has passed the DNSKEY is OMNIPRESENT.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the new algorithm keys have been introduced is 3 hours.
|
||
# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = now - 3h + 6h + 1h = now + 4h
|
||
TpubN1 = "now-3h"
|
||
TsbmN1 = "now+4h"
|
||
ksk1times = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
zsk1times = f"-P {TactN} -A {TactN} -I {TsbmN1}"
|
||
ksk2times = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
zsk2times = f"-P {TpubN1} -A {TpubN1}"
|
||
# Key generation.
|
||
ksk1_name = keygen(
|
||
f"-a RSASHA256 -f KSK {ksk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk1_name = keygen(
|
||
f"-a RSASHA256 {zsk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
ksk2_name = keygen(
|
||
f"-a ECDSA256 -f KSK {ksk2times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk2_name = keygen(f"-a ECDSA256 {zsk2times} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Signing.
|
||
fake_lifetime(ksk1_name, 0)
|
||
fake_lifetime(zsk1_name, 0)
|
||
render_and_sign_zone(zonename, [ksk1_name, zsk1_name, ksk2_name, zsk2_name])
|
||
|
||
# Step 3:
|
||
# The zone signatures are also OMNIPRESENT.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the new algorithm keys have been introduced is 7 hours.
|
||
TpubN1 = "now-7h"
|
||
TsbmN1 = "now"
|
||
ksk1times = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
zsk1times = f"-P {TactN} -A {TactN} -I {TsbmN1}"
|
||
ksk2times = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
zsk2times = f"-P {TpubN1} -A {TpubN1}"
|
||
# Key generation.
|
||
ksk1_name = keygen(
|
||
f"-a RSASHA256 -f KSK {ksk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk1_name = keygen(
|
||
f"-a RSASHA256 {zsk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
ksk2_name = keygen(
|
||
f"-a ECDSA256 -f KSK {ksk2times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk2_name = keygen(f"-a ECDSA256 {zsk2times} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Signing.
|
||
fake_lifetime(ksk1_name, 0)
|
||
fake_lifetime(zsk1_name, 0)
|
||
render_and_sign_zone(zonename, [ksk1_name, zsk1_name, ksk2_name, zsk2_name])
|
||
|
||
# Step 4:
|
||
# The DS is swapped and can become OMNIPRESENT.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the DS has been swapped is 3 hours.
|
||
TpubN1 = "now-10h"
|
||
TsbmN1 = "now-3h"
|
||
ksk1times = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
zsk1times = f"-P {TactN} -A {TactN} -I {TsbmN1}"
|
||
ksk2times = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
zsk2times = f"-P {TpubN1} -A {TpubN1}"
|
||
# Key generation.
|
||
ksk1_name = keygen(
|
||
f"-a RSASHA256 -f KSK {ksk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk1_name = keygen(
|
||
f"-a RSASHA256 {zsk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
ksk2_name = keygen(
|
||
f"-a ECDSA256 -f KSK {ksk2times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk2_name = keygen(f"-a ECDSA256 {zsk2times} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"UNRETENTIVE {TsbmN1}",
|
||
D_ds=f"{TsbmN1}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
d=f"RUMOURED {TsbmN1}",
|
||
P_ds=f"{TsbmN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Signing.
|
||
fake_lifetime(ksk1_name, 0)
|
||
fake_lifetime(zsk1_name, 0)
|
||
render_and_sign_zone(zonename, [ksk1_name, zsk1_name, ksk2_name, zsk2_name])
|
||
|
||
# Step 5:
|
||
# The DNSKEY is removed long enough to be HIDDEN.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The time passed since the DNSKEY has been removed is 2 hours.
|
||
TpubN1 = "now-12h"
|
||
TsbmN1 = "now-5h"
|
||
ksk1times = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
zsk1times = f"-P {TactN} -A {TactN} -I {TsbmN1}"
|
||
ksk2times = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
zsk2times = f"-P {TpubN1} -A {TpubN1}"
|
||
# Key generation.
|
||
ksk1_name = keygen(
|
||
f"-a RSASHA256 -f KSK {ksk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk1_name = keygen(
|
||
f"-a RSASHA256 {zsk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
ksk2_name = keygen(
|
||
f"-a ECDSA256 -f KSK {ksk2times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk2_name = keygen(f"-a ECDSA256 {zsk2times} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TsbmN1}",
|
||
r=f"UNRETENTIVE {TsbmN1}",
|
||
d=f"HIDDEN {TsbmN1}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TsbmN1}",
|
||
z=f"UNRETENTIVE {TsbmN1}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
d=f"OMNIPRESENT {TsbmN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Signing.
|
||
fake_lifetime(ksk1_name, 0)
|
||
fake_lifetime(zsk1_name, 0)
|
||
render_and_sign_zone(zonename, [ksk1_name, zsk1_name, ksk2_name, zsk2_name])
|
||
|
||
# Step 6:
|
||
# The RRSIGs have been removed long enough to be HIDDEN.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Additional time passed: 7h.
|
||
TpubN1 = "now-19h"
|
||
TsbmN1 = "now-12h"
|
||
ksk1times = f"-P {TactN} -A {TactN} -P sync {TsbmN} -I {TsbmN1}"
|
||
zsk1times = f"-P {TactN} -A {TactN} -I {TsbmN1}"
|
||
ksk2times = f"-P {TpubN1} -A {TpubN1} -P sync {TsbmN1}"
|
||
zsk2times = f"-P {TpubN1} -A {TpubN1}"
|
||
ksk1_name = keygen(
|
||
f"-a RSASHA256 -f KSK {ksk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk1_name = keygen(
|
||
f"-a RSASHA256 {zsk1times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
ksk2_name = keygen(
|
||
f"-a ECDSA256 -f KSK {ksk2times} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk2_name = keygen(f"-a ECDSA256 {zsk2times} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TsbmN1}",
|
||
r=f"UNRETENTIVE {TsbmN1}",
|
||
d=f"HIDDEN {TsbmN1}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TsbmN1}",
|
||
z=f"UNRETENTIVE {TsbmN1}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
r=f"OMNIPRESENT {TpubN1}",
|
||
d=f"OMNIPRESENT {TsbmN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN1}",
|
||
z=f"RUMOURED {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Signing.
|
||
fake_lifetime(ksk1_name, 0)
|
||
fake_lifetime(zsk1_name, 0)
|
||
render_and_sign_zone(zonename, [ksk1_name, zsk1_name, ksk2_name, zsk2_name])
|
||
|
||
return zones
|
||
|
||
|
||
def configure_cskroll1(tld: str, policy: str) -> List[Zone]:
|
||
# The zones at csk-roll1.$tld represent the various steps of a CSK rollover
|
||
# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover).
|
||
zones = []
|
||
zone = f"csk-roll1.{tld}"
|
||
cds = "cdnskey,cds:sha384"
|
||
keygen = EnvCmd("KEYGEN", f"-k {policy} -l kasp.conf")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
TactN = "now-7d"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 2:
|
||
# It is time to introduce the new CSK.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC
|
||
# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub
|
||
# IpubC = DprpC + TTLkey (+publish-safety)
|
||
# Ipub = IpubC
|
||
# Lcsk = Lksk = Lzsk
|
||
#
|
||
# Lcsk: 6mo (186d, 4464h)
|
||
# Dreg: N/A
|
||
# DprpC: 1h
|
||
# TTLkey: 1h
|
||
# publish-safety: 1h
|
||
# Ipub: 3h
|
||
#
|
||
# Tact(N) = now - Lcsk + Ipub = now - 186d + 3h
|
||
# = now - 4464h + 3h = now - 4461h
|
||
TactN = "now-4461h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 3:
|
||
# It is time to submit the DS and to roll signatures.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
#
|
||
# Tsbm(N+1) >= Trdy(N+1)
|
||
# KSK: Tact(N+1) = Tsbm(N+1)
|
||
# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1)
|
||
# KSK: Iret = DprpP + TTLds (+retire-safety)
|
||
# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety)
|
||
#
|
||
# Lcsk: 186d
|
||
# Dprp: 1h
|
||
# DprpP: 1h
|
||
# Dreg: N/A
|
||
# Dsgn: 25d
|
||
# TTLds: 1h
|
||
# TTLsig: 1d
|
||
# retire-safety: 2h
|
||
# Iret: 4h
|
||
# IretZ: 26d3h
|
||
# Ipub: 3h
|
||
#
|
||
# Tpub(N) = now - Lcsk = now - 186d
|
||
# Tact(N) = now - Lcsk + Dprp + TTLsig = now - 4439h
|
||
# Tret(N) = now
|
||
# Trem(N) = now + IretZ = now + 26d3h = now + 627h
|
||
# Tpub(N+1) = now - Ipub = now - 3h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + Lcsk = now + 186d = now + 186d
|
||
# Trem(N+1) = now + Lcsk + IretZ = now + 186d + 26d3h =
|
||
# = now + 5091h
|
||
TpubN = "now-186d"
|
||
TactN = "now-4439h"
|
||
TretN = "now"
|
||
TremN = "now+627h"
|
||
TpubN1 = "now-3h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+186d"
|
||
TremN1 = "now+5091h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
z=f"HIDDEN {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 4:
|
||
# Some time later all the ZRRSIG records should be from the new CSK, and the
|
||
# DS should be swapped. The ZRRSIG records are all replaced after IretZ
|
||
# (which is 26d3h). The DS is swapped after Iret (which is 4h).
|
||
# In other words, the DS is swapped before all zone signatures are replaced.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Trem(N) = Tret(N) - Iret + IretZ
|
||
# now = Tsbm(N+1) + Iret
|
||
#
|
||
# Lcsk: 186d
|
||
# Iret: 4h
|
||
# IretZ: 26d3h
|
||
#
|
||
# Tpub(N) = now - Iret - Lcsk = now - 4h - 186d = now - 4468h
|
||
# Tret(N) = now - Iret = now - 4h = now - 4h
|
||
# Trem(N) = now - Iret + IretZ = now - 4h + 26d3h
|
||
# = now + 623h
|
||
# Tpub(N+1) = now - Iret - IpubC = now - 4h - 3h = now - 7h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now - Iret + Lcsk = now - 4h + 186d = now + 4460h
|
||
# Trem(N+1) = now - Iret + Lcsk + IretZ = now - 4h + 186d + 26d3h
|
||
# = now + 5087h
|
||
TpubN = "now-4468h"
|
||
TactN = "now-4443h"
|
||
TretN = "now-4h"
|
||
TremN = "now+623h"
|
||
TpubN1 = "now-7h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+4460h"
|
||
TremN1 = "now+5087h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"UNRETENTIVE {TactN1}",
|
||
d=f"UNRETENTIVE {TactN1}",
|
||
D_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"RUMOURED {TactN1}",
|
||
d=f"RUMOURED {TactN1}",
|
||
P_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 5:
|
||
# After the DS is swapped in step 4, also the KRRSIG records can be removed.
|
||
# At this time these have all become hidden.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h).
|
||
TpubN = "now-4470h"
|
||
TactN = "now-4445h"
|
||
TretN = "now-6h"
|
||
TremN = "now+621h"
|
||
TpubN1 = "now-9h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+4458h"
|
||
TremN1 = "now+5085h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r="UNRETENTIVE now-2h",
|
||
z=f"UNRETENTIVE {TactN1}",
|
||
d="HIDDEN now-2h",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"RUMOURED {TactN1}",
|
||
d="OMNIPRESENT now-2h",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 6:
|
||
# After the retire interval has passed the predecessor DNSKEY can be
|
||
# removed from the zone.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Trem(N) = Tret(N) + IretZ
|
||
# Tret(N) = Tact(N) + Lcsk
|
||
#
|
||
# Lcsk: 186d
|
||
# Iret: 4h
|
||
# IretZ: 26d3h
|
||
#
|
||
# Tpub(N) = now - IretZ - Lcsk = now - 627h - 186d
|
||
# = now - 627h - 4464h = now - 5091h
|
||
# Tact(N) = now - 627h - 186d
|
||
# Tret(N) = now - IretZ = now - 627h
|
||
# Trem(N) = now
|
||
# Tpub(N+1) = now - IretZ - Ipub = now - 627h - 3h = now - 630h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now - IretZ + Lcsk = now - 627h + 186d = now + 3837h
|
||
# Trem(N+1) = now + Lcsk = now + 186d
|
||
TpubN = "now-5091h"
|
||
TactN = "now-5066h"
|
||
TretN = "now-627h"
|
||
TremN = "now"
|
||
TpubN1 = "now-630h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+3837h"
|
||
TremN1 = "now+186d"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"HIDDEN {TremN}",
|
||
z=f"UNRETENTIVE {TactN1}",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"RUMOURED {TactN1}",
|
||
d=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 7:
|
||
# Some time later the predecessor DNSKEY enters the HIDDEN state.
|
||
zonename = f"step7.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract DNSKEY TTL plus zone propagation delay from all the times (2h).
|
||
TpubN = "now-5093h"
|
||
TactN = "now-5068h"
|
||
TretN = "now-629h"
|
||
TremN = "now-2h"
|
||
TpubN1 = "now-632h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+3835h"
|
||
TremN1 = "now+4462h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TremN}",
|
||
r=f"HIDDEN {TremN}",
|
||
z=f"HIDDEN {TactN1}",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"OMNIPRESENT {TactN1}",
|
||
d=f"OMNIPRESENT {TactN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 8:
|
||
# The predecessor DNSKEY can be purged.
|
||
zonename = f"step8.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract purge-keys interval from all the times (1h).
|
||
TpubN = "now-5094h"
|
||
TactN = "now-5069h"
|
||
TretN = "now-630h"
|
||
TremN = "now-3h"
|
||
TpubN1 = "now-633h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+3834h"
|
||
TremN1 = "now+4461h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TremN}",
|
||
r=f"HIDDEN {TremN}",
|
||
z=f"HIDDEN {TactN1}",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"OMNIPRESENT {TactN1}",
|
||
d=f"OMNIPRESENT {TactN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_cskroll2(tld: str, policy: str) -> List[Zone]:
|
||
# The zones at csk-roll2.$tld represent the various steps of a CSK rollover
|
||
# (which is essentially a ZSK Pre-Publication / KSK Double-KSK rollover).
|
||
# This scenario differs from the csk-roll1 one because the zone signatures (ZRRSIG)
|
||
# are replaced with the new key sooner than the DS is swapped.
|
||
zones = []
|
||
zone = f"csk-roll2.{tld}"
|
||
cds = "cdnskey,cds:sha-256,cds:sha-384"
|
||
keygen = EnvCmd("KEYGEN", f"-k {policy} -l kasp.conf")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
TactN = "now-7d"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 2:
|
||
# It is time to introduce the new CSK.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# KSK: Tpub(N+1) <= Tact(N) + Lksk - IpubC
|
||
# ZSK: Tpub(N+1) <= Tact(N) + Lzsk - Ipub
|
||
# IpubC = DprpC + TTLkey (+publish-safety)
|
||
# Ipub = IpubC
|
||
# Lcsk = Lksk = Lzsk
|
||
#
|
||
# Lcsk: 6mo (186d, 4464h)
|
||
# Dreg: N/A
|
||
# DprpC: 1h
|
||
# TTLkey: 1h
|
||
# publish-safety: 1h
|
||
# Ipub: 3h
|
||
#
|
||
# Tact(N) = now - Lcsk + Ipub = now - 186d + 3h
|
||
# = now - 4464h + 3h = now - 4461h
|
||
TactN = "now-4461h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 3:
|
||
# It is time to submit the DS and to roll signatures.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
#
|
||
# Tsbm(N+1) >= Trdy(N+1)
|
||
# KSK: Tact(N+1) = Tsbm(N+1)
|
||
# ZSK: Tact(N+1) = Tpub(N+1) + Ipub = Tsbm(N+1)
|
||
# KSK: Iret = DprpP + TTLds (+retire-safety)
|
||
# ZSK: IretZ = Dsgn + Dprp + TTLsig (+retire-safety)
|
||
#
|
||
# Lcsk: 186d
|
||
# Dprp: 1h
|
||
# DprpP: 1w
|
||
# Dreg: N/A
|
||
# Dsgn: 12h
|
||
# TTLds: 1h
|
||
# TTLsig: 1d
|
||
# retire-safety: 1h
|
||
# Iret: 170h
|
||
# IretZ: 38h
|
||
# Ipub: 3h
|
||
#
|
||
# Tpub(N) = now - Lcsk = now - 186d
|
||
# Tact(N) = now - Lcsk + Dprp + TTLsig = now - 4439h
|
||
# Tret(N) = now
|
||
# Trem(N) = now + IretZ = now + 26d3h = now + 627h
|
||
# Tpub(N+1) = now - Ipub = now - 3h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + Lcsk = now + 186d = now + 186d
|
||
# Trem(N+1) = now + Lcsk + IretZ = now + 186d + 26d3h =
|
||
# = now + 5091h
|
||
TpubN = "now-186d"
|
||
TactN = "now-4439h"
|
||
TretN = "now"
|
||
TremN = "now+170h"
|
||
TpubN1 = "now-3h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+186d"
|
||
TremN1 = "now+4634h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
z=f"HIDDEN {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 4:
|
||
# Some time later all the ZRRSIG records should be from the new CSK, and the
|
||
# DS should be swapped. The ZRRSIG records are all replaced after IretZ (38h).
|
||
# The DS is swapped after Dreg + Iret (1w3h). In other words, the zone
|
||
# signatures are replaced before the DS is swapped.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Trem(N) = Tret(N) + IretZ
|
||
#
|
||
# Lcsk: 186d
|
||
# Dreg: N/A
|
||
# Iret: 170h
|
||
# IretZ: 38h
|
||
#
|
||
# Tpub(N) = now - IretZ - Lcsk = now - 38h - 186d
|
||
# = now - 38h - 4464h = now - 4502h
|
||
# Tact(N) = now - Iret - Lcsk + TTLsig = now - 4502h + 25h = now - 4477h
|
||
# Tret(N) = now - IretZ = now - 38h
|
||
# Trem(N) = now - IretZ + Iret = now - 38h + 170h = now + 132h
|
||
# Tpub(N+1) = now - IretZ - IpubC = now - 38h - 3h = now - 41h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now - IretZ + Lcsk = now - 38h + 186d
|
||
# = now + 4426h
|
||
# Trem(N+1) = now - IretZ + Lcsk + Iret
|
||
# = now + 4426h + 3h = now + 4429h
|
||
TpubN = "now-4502h"
|
||
TactN = "now-4477h"
|
||
TretN = "now-38h"
|
||
TremN = "now+132h"
|
||
TpubN1 = "now-41h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+4426h"
|
||
TremN1 = "now+4429h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z=f"UNRETENTIVE {TretN}",
|
||
d=f"UNRETENTIVE {TretN}",
|
||
D_ds=f"{TretN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"RUMOURED {TactN1}",
|
||
d=f"RUMOURED {TactN1}",
|
||
P_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 5:
|
||
# Some time later the DS can be swapped and the old DNSKEY can be removed from
|
||
# the zone.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract Iret (170h) - IretZ (38h) = 132h.
|
||
#
|
||
# Tpub(N) = now - 4502h - 132h = now - 4634h
|
||
# Tact(N) = now - 4477h - 132h = now - 4609h
|
||
# Tret(N) = now - 38h - 132h = now - 170h
|
||
# Trem(N) = now + 132h - 132h = now
|
||
# Tpub(N+1) = now - 41h - 132h = now - 173h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + 4426h - 132h = now + 4294h
|
||
# Trem(N+1) = now + 4492h - 132h = now + 4360h
|
||
TpubN = "now-4634h"
|
||
TactN = "now-4609h"
|
||
TretN = "now-170h"
|
||
TremN = "now"
|
||
TpubN1 = "now-173h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+4294h"
|
||
TremN1 = "now+4360h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
z="HIDDEN now-133h",
|
||
d=f"UNRETENTIVE {TactN1}",
|
||
D_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z="OMNIPRESENT now-133h",
|
||
d=f"RUMOURED {TactN1}",
|
||
P_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 6:
|
||
# Some time later the predecessor DNSKEY enters the HIDDEN state.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract DNSKEY TTL plus zone propagation delay (2h).
|
||
#
|
||
# Tpub(N) = now - 4634h - 2h = now - 4636h
|
||
# Tact(N) = now - 4609h - 2h = now - 4611h
|
||
# Tret(N) = now - 170h - 2h = now - 172h
|
||
# Trem(N) = now - 2h
|
||
# Tpub(N+1) = now - 173h - 2h = now - 175h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + 4294h - 2h = now + 4292h
|
||
# Trem(N+1) = now + 4360h - 2h = now + 4358h
|
||
TpubN = "now-4636h"
|
||
TactN = "now-4611h"
|
||
TretN = "now-172h"
|
||
TremN = "now-2h"
|
||
TpubN1 = "now-175h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+4292h"
|
||
TremN1 = "now+4358h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TremN}",
|
||
r=f"UNRETENTIVE {TremN}",
|
||
z="HIDDEN now-135h",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z="OMNIPRESENT now-135h",
|
||
d=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 7:
|
||
# The predecessor DNSKEY can be purged, but purge-keys is disabled.
|
||
zonename = f"step7.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract 90 days (default, 2160h) from all the times.
|
||
#
|
||
# Tpub(N) = now - 4636h - 2160h = now - 6796h
|
||
# Tact(N) = now - 4611h - 2160h = now - 6771h
|
||
# Tret(N) = now - 172h - 2160h = now - 2332h
|
||
# Trem(N) = now - 2h - 2160h = now - 2162h
|
||
# Tpub(N+1) = now - 175h - 2160h = now - 2335h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + 4292h - 2160h = now + 2132h
|
||
# Trem(N+1) = now + 4358h - 2160h = now + 2198h
|
||
TpubN = "now-6796h"
|
||
TactN = "now-6771h"
|
||
TretN = "now-2332h"
|
||
TremN = "now-2162h"
|
||
TpubN1 = "now-2335h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+2132h"
|
||
TremN1 = "now+2198h"
|
||
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TremN}",
|
||
r=f"HIDDEN {TremN}",
|
||
z=f"HIDDEN {TactN1}",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z=f"OMNIPRESENT {TactN1}",
|
||
d=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
# Step 8:
|
||
# The predecessor DNSKEY can be purged.
|
||
zonename = f"step8.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract purge-keys interval from all the times (1h).
|
||
TpubN = "now-5094h"
|
||
TactN = "now-5069h"
|
||
TretN = "now-630h"
|
||
TremN = "now-3h"
|
||
TpubN1 = "now-633h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+3834h"
|
||
TremN1 = "now+4461h"
|
||
keytimes = (
|
||
f"-P {TpubN} -P sync {TactN} -A {TpubN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -P sync {TactN1} -A {TactN1} -I {TretN1} -D {TremN1}"
|
||
# Key generation.
|
||
csk1_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
csk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TremN}",
|
||
r=f"UNRETENTIVE {TremN}",
|
||
z="HIDDEN now-2295h",
|
||
d=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(csk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
z="OMNIPRESENT now-2295h",
|
||
d=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(csk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(csk1_name, csk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk1_name, csk2_name], extra_options=f"-z -G {cds}")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_enable_dnssec(tld: str, policy: str) -> List[Zone]:
|
||
# The zones at enable-dnssec.$tld represent the various steps of the
|
||
# initial signing of a zone.
|
||
zones = []
|
||
zone = f"enable-dnssec.{tld}"
|
||
keygen = EnvCmd("KEYGEN", f"-k {policy} -l kasp.conf")
|
||
|
||
# Step 1:
|
||
# This is an unsigned zone and named should perform the initial steps of
|
||
# introducing the DNSSEC records in the right order.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
render_and_sign_zone(zonename, [], signing=False)
|
||
|
||
# Step 2:
|
||
# The DNSKEY has been published long enough to become OMNIPRESENT.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# DNSKEY TTL: 300 seconds
|
||
# zone-propagation-delay: 5 minutes (300 seconds)
|
||
# publish-safety: 5 minutes (300 seconds)
|
||
# Total: 900 seconds
|
||
TpubN = "now-900s"
|
||
keytimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN}",
|
||
r=f"RUMOURED {TpubN}",
|
||
z=f"RUMOURED {TpubN}",
|
||
d=f"HIDDEN {TpubN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z")
|
||
|
||
# Step 3:
|
||
# The zone signatures have been published long enough to become OMNIPRESENT.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Passed time since publication:
|
||
# max-zone-ttl: 12 hours (43200 seconds)
|
||
# zone-propagation-delay: 5 minutes (300 seconds)
|
||
# We can submit the DS now.
|
||
TpubN = "now-43500s"
|
||
keytimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
z=f"RUMOURED {TpubN}",
|
||
d=f"HIDDEN {TpubN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z")
|
||
|
||
# Step 4:
|
||
# The DS has been submitted long enough ago to become OMNIPRESENT.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# DS TTL: 2 hour (7200 seconds)
|
||
# parent-propagation-delay: 1 hour (3600 seconds)
|
||
# Total aditional time: 10800 seconds
|
||
# 43500 + 10800 = 54300
|
||
TpubN = "now-54300s"
|
||
TsbmN = "now-10800s"
|
||
keytimes = f"-P {TpubN} -A {TpubN} -P sync {TsbmN}"
|
||
# Key generation.
|
||
csk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TsbmN}",
|
||
d=f"RUMOURED {TpubN}",
|
||
P_ds=f"{TsbmN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_going_insecure(tld: str, reconfig: bool = False) -> List[Zone]:
|
||
zones = []
|
||
keygen = EnvCmd("KEYGEN", "-a ECDSA256 -L 7200")
|
||
|
||
# The child zones (step1, step2) beneath these zones represent the various
|
||
# steps of unsigning a zone.
|
||
for zone in [f"going-insecure.{tld}", f"going-insecure-dynamic.{tld}"]:
|
||
# Set up a zone with dnssec-policy that is going insecure.
|
||
|
||
# Step 1:
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Timing metadata.
|
||
TpubN = "now-10d"
|
||
TsbmN = "now-12955mi"
|
||
keytimes = f"-P {TpubN} -A {TpubN}"
|
||
cdstimes = f"-P sync {TsbmN}"
|
||
# Key generation.
|
||
ksk_name = keygen(
|
||
f"-f KSK {keytimes} {cdstimes} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
d=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name])
|
||
|
||
if reconfig:
|
||
# Step 2:
|
||
zonename = f"step2.{zone}"
|
||
zones.append(
|
||
Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3"))
|
||
)
|
||
isctest.log.info(f"setup {zonename}")
|
||
# The DS was withdrawn from the parent zone 26 hours ago.
|
||
TremN = "now-26h"
|
||
keytimes = f"-P {TpubN} -A {TpubN} -I {TremN} -D now"
|
||
cdstimes = f"-P sync {TsbmN} -D sync {TremN}"
|
||
# Key generation.
|
||
ksk_name = keygen(
|
||
f"-f KSK {keytimes} {cdstimes} {zonename}", cwd="ns3"
|
||
).out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
d=f"UNRETENTIVE {TremN}",
|
||
D_ds=f"{TremN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Fake lifetime of old algorithm keys.
|
||
fake_lifetime(ksk_name, 0)
|
||
fake_lifetime(zsk_name, 5184000)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name], extra_options="-P")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_straight2none(tld: str) -> List[Zone]:
|
||
# These zones are going straight to "none" policy. This is undefined behavior.
|
||
zones = []
|
||
keygen = EnvCmd("KEYGEN", "-k default")
|
||
|
||
TpubN = "now-10d"
|
||
TsbmN = "now-12955mi"
|
||
keytimes = f"-P {TpubN} -A {TpubN} -P sync {TsbmN}"
|
||
|
||
zonename = f"going-straight-to-none.{tld}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Key generation.
|
||
csk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
d=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z")
|
||
|
||
zonename = f"going-straight-to-none-dynamic.{tld}"
|
||
zones.append(
|
||
Zone(zonename, f"{zonename}.db.signed", Nameserver("ns3", "10.53.0.3"))
|
||
)
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Key generation.
|
||
csk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
r=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
d=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(csk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [csk_name], extra_options="-z -O full")
|
||
|
||
return zones
|
||
|
||
|
||
def configure_ksk_doubleksk(tld: str) -> List[Zone]:
|
||
# The zones at ksk-doubleksk.$tld represent the various steps of a KSK
|
||
# Double-KSK rollover.
|
||
zones = []
|
||
zone = f"ksk-doubleksk.{tld}"
|
||
cds = "cds:sha-256"
|
||
keygen = EnvCmd("KEYGEN", "-a ECDSAP256SHA256 -L 7200")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Timing metadata.
|
||
TactN = "now-7d"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name], extra_options=f"-G {cds}")
|
||
|
||
# Step 2:
|
||
# It is time to introduce the new KSK.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Lksk: 60d
|
||
# Dreg: n/a
|
||
# DprpC: 1h
|
||
# TTLds: 1d
|
||
# TTLkey: 2h
|
||
# publish-safety: 1d
|
||
# retire-safety: 2d
|
||
#
|
||
# According to RFC 7583:
|
||
# Tpub(N+1) <= Tact(N) + Lksk - Dreg - IpubC
|
||
# IpubC = DprpC + TTLkey (+publish-safety)
|
||
#
|
||
# IpubC = 27h
|
||
# Tact(N) = now - Lksk + Dreg + IpubC = now - 60d + 27h
|
||
# = now - 1440h + 27h = now - 1413h
|
||
TactN = "now-1413h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name], extra_options=f"-G {cds}")
|
||
|
||
# Step 3:
|
||
# It is time to submit the DS.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Iret = DprpP + TTLds (+retire-safety)
|
||
#
|
||
# Iret = 50h
|
||
# Tpub(N) = now - Lksk = now - 60d = now - 60d
|
||
# Tact(N) = now - 1413h
|
||
# Tret(N) = now
|
||
# Trem(N) = now + Iret = now + 50h
|
||
# Tpub(N+1) = now - IpubC = now - 27h
|
||
# Tact(N+1) = now
|
||
# Tret(N+1) = now + Lksk = now + 60d
|
||
# Trem(N+1) = now + Lksk + Iret = now + 60d + 50h
|
||
# = now + 1440h + 50h = 1490h
|
||
TpubN = "now-60d"
|
||
TactN = "now-1413h"
|
||
TretN = "now"
|
||
TremN = "now+50h"
|
||
TpubN1 = "now-27h"
|
||
TactN1 = "now"
|
||
TretN1 = "now+60d"
|
||
TremN1 = "now+1490h"
|
||
ksktimes = (
|
||
f"-P {TpubN} -A {TpubN} -P sync {TactN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -A {TactN1} -P sync {TactN1} -I {TretN1} -D {TremN1}"
|
||
zsktimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
ksk1_name = keygen(f"-f KSK {ksktimes} {zonename}", cwd="ns3").out.strip()
|
||
ksk2_name = keygen(f"-f KSK {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{zsktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(ksk1_name, ksk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(
|
||
zonename, [ksk1_name, ksk2_name, zsk_name], extra_options=f"-G {cds}"
|
||
)
|
||
|
||
# Step 4:
|
||
# The DS should be swapped now.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Tpub(N) = now - Lksk - Iret = now - 60d - 50h
|
||
# = now - 1440h - 50h = now - 1490h
|
||
# Tact(N) = now - 1490h + 27h = now - 1463h
|
||
# Tret(N) = now - Iret = now - 50h
|
||
# Trem(N) = now
|
||
# Tpub(N+1) = now - Iret - IpubC = now - 50h - 27h
|
||
# = now - 77h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + Lksk - Iret = now + 60d - 50h = now + 1390h
|
||
# Trem(N+1) = now + Lksk = now + 60d
|
||
TpubN = "now-1490h"
|
||
TactN = "now-1463h"
|
||
TretN = "now-50h"
|
||
TremN = "now"
|
||
TpubN1 = "now-77h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+1390h"
|
||
TremN1 = "now+60d"
|
||
ksktimes = (
|
||
f"-P {TpubN} -A {TpubN} -P sync {TactN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -A {TactN1} -P sync {TactN1} -I {TretN1} -D {TremN1}"
|
||
zsktimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
ksk1_name = keygen(f"-f KSK {ksktimes} {zonename}", cwd="ns3").out.strip()
|
||
ksk2_name = keygen(f"-f KSK {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{zsktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"UNRETENTIVE {TretN}",
|
||
D_ds=f"{TretN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
d=f"RUMOURED {TactN1}",
|
||
P_ds=f"{TactN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(ksk1_name, ksk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(
|
||
zonename, [ksk1_name, ksk2_name, zsk_name], extra_options=f"-G {cds}"
|
||
)
|
||
|
||
# Step 5:
|
||
# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract DNSKEY TTL + zone-propagation-delay from all the times (3h).
|
||
# Tpub(N) = now - 1490h - 3h = now - 1493h
|
||
# Tact(N) = now - 1463h - 3h = now - 1466h
|
||
# Tret(N) = now - 50h - 3h = now - 53h
|
||
# Trem(N) = now - 3h
|
||
# Tpub(N+1) = now - 77h - 3h = now - 80h
|
||
# Tact(N+1) = Tret(N)
|
||
# Tret(N+1) = now + 1390h - 3h = now + 1387h
|
||
# Trem(N+1) = now + 60d - 3h = now + 1441h
|
||
TpubN = "now-1493h"
|
||
TactN = "now-1466h"
|
||
TretN = "now-53h"
|
||
TremN = "now-3h"
|
||
TpubN1 = "now-80h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+1387h"
|
||
TremN1 = "now+1441h"
|
||
ksktimes = (
|
||
f"-P {TpubN} -A {TpubN} -P sync {TactN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -A {TactN1} -P sync {TactN1} -I {TretN1} -D {TremN1}"
|
||
zsktimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
ksk1_name = keygen(f"-f KSK {ksktimes} {zonename}", cwd="ns3").out.strip()
|
||
ksk2_name = keygen(f"-f KSK {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{zsktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TretN}",
|
||
r=f"UNRETENTIVE {TretN}",
|
||
d=f"HIDDEN {TretN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
d=f"OMNIPRESENT {TactN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(ksk1_name, ksk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(
|
||
zonename, [ksk1_name, ksk2_name, zsk_name], extra_options=f"-G {cds}"
|
||
)
|
||
|
||
# Step 6:
|
||
# The predecessor DNSKEY can be purged.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract purge-keys interval from all the times (1h).
|
||
TpubN = "now-1494h"
|
||
TactN = "now-1467h"
|
||
TretN = "now-54h"
|
||
TremN = "now-4h"
|
||
TpubN1 = "now-81h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+1386h"
|
||
TremN1 = "now+1440h"
|
||
ksktimes = (
|
||
f"-P {TpubN} -A {TpubN} -P sync {TactN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -A {TactN1} -P sync {TactN1} -I {TretN1} -D {TremN1}"
|
||
zsktimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
ksk1_name = keygen(f"-f KSK {ksktimes} {zonename}", cwd="ns3").out.strip()
|
||
ksk2_name = keygen(f"-f KSK {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{zsktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TretN}",
|
||
r=f"HIDDEN {TretN}",
|
||
d=f"HIDDEN {TretN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
r=f"OMNIPRESENT {TactN1}",
|
||
d=f"OMNIPRESENT {TactN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(ksk1_name, ksk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(
|
||
zonename, [ksk1_name, ksk2_name, zsk_name], extra_options=f"-G {cds}"
|
||
)
|
||
|
||
return zones
|
||
|
||
|
||
def configure_ksk_3crowd(tld: str) -> List[Zone]:
|
||
# Test #2375, the "three is a crowd" bug, where a new key is introduced but the
|
||
# previous rollover has not finished yet. In other words, we have a key KEY2
|
||
# that is the successor of key KEY1, and we introduce a new key KEY3 that is
|
||
# the successor of key KEY2:
|
||
#
|
||
# KEY1 < KEY2 < KEY3.
|
||
#
|
||
# The expected behavior is that all three keys remain in the zone, and not
|
||
# the bug behavior where KEY2 is removed and immediately replaced with KEY3.
|
||
#
|
||
zones = []
|
||
cds = "cds:sha-256"
|
||
keygen = EnvCmd("KEYGEN", "-a ECDSAP256SHA256 -L 7200")
|
||
|
||
# Set up a zone that has a KSK (KEY1) and have the successor key (KEY2)
|
||
# published as well.
|
||
zonename = f"three-is-a-crowd.{tld}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# These times are the same as step3.ksk-doubleksk.autosign.
|
||
TpubN = "now-60d"
|
||
TactN = "now-1413h"
|
||
TretN = "now"
|
||
TremN = "now+50h"
|
||
TpubN1 = "now-27h"
|
||
TactN1 = TretN
|
||
TretN1 = "now+60d"
|
||
TremN1 = "now+1490h"
|
||
ksktimes = (
|
||
f"-P {TpubN} -A {TpubN} -P sync {TactN} -I {TretN} -D {TremN} -D sync {TactN1}"
|
||
)
|
||
newtimes = f"-P {TpubN1} -A {TactN1} -P sync {TactN1} -I {TretN1} -D {TremN1}"
|
||
zsktimes = f"-P {TpubN} -A {TpubN}"
|
||
# Key generation.
|
||
ksk1_name = keygen(f"-f KSK {ksktimes} {zonename}", cwd="ns3").out.strip()
|
||
ksk2_name = keygen(f"-f KSK {newtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{zsktimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
r=f"RUMOURED {TpubN1}",
|
||
d=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(ksk2_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TpubN}",
|
||
z=f"OMNIPRESENT {TpubN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(ksk1_name, ksk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(
|
||
zonename, [ksk1_name, ksk2_name, zsk_name], extra_options=f"-G {cds}"
|
||
)
|
||
|
||
return zones
|
||
|
||
|
||
def configure_zsk_prepub(tld: str) -> List[Zone]:
|
||
# The zones at zsk-prepub.$tld represent the various steps of a ZSK
|
||
# Pre-Publication rollover.
|
||
zones = []
|
||
zone = f"zsk-prepub.{tld}"
|
||
keygen = EnvCmd("KEYGEN", "-a ECDSAP256SHA256 -L 3600")
|
||
|
||
# Step 1:
|
||
# Introduce the first key. This will immediately be active.
|
||
zonename = f"step1.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Timing metadata.
|
||
TactN = "now-7d"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name])
|
||
|
||
# Step 2:
|
||
# It is time to pre-publish the successor ZSK.
|
||
zonename = f"step2.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Tact(N) = now + Ipub - Lzsk = now + 26h - 30d
|
||
# = now + 26h - 30d = now − 694h
|
||
TactN = "now-694h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk_name = keygen(f"{keytimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk_name, timings)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk_name])
|
||
|
||
# Step 3:
|
||
# After the publication interval has passed the DNSKEY of the successor ZSK
|
||
# is OMNIPRESENT and the zone can thus be signed with the successor ZSK.
|
||
zonename = f"step3.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# According to RFC 7583:
|
||
# Tpub(N+1) <= Tact(N) + Lzsk - Ipub
|
||
# Tact(N+1) = Tact(N) + Lzsk
|
||
#
|
||
# Tact(N) = now - Lzsk = now - 30d
|
||
# Tpub(N+1) = now - Ipub = now - 26h
|
||
# Tact(N+1) = now
|
||
# Tret(N) = now
|
||
# Trem(N) = now + Iret = now + Dsign + Dprp + TTLsig + retire-safety = 8d1h = now + 241h
|
||
TactN = "now-30d"
|
||
TpubN1 = "now-26h"
|
||
TactN1 = "now"
|
||
TremN = "now+241h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
oldtimes = f"-P {TactN} -A {TactN} -I {TactN1} -D {TremN}"
|
||
newtimes = f"-P {TpubN1} -A {TactN1}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk1_name = keygen(f"{oldtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"RUMOURED {TpubN1}",
|
||
z=f"HIDDEN {TpubN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(zsk1_name, zsk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk1_name, zsk2_name])
|
||
|
||
# Step 4:
|
||
# After the retire interval has passed the predecessor DNSKEY can be
|
||
# removed from the zone.
|
||
zonename = f"step4.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Lzsk: 30d
|
||
# Ipub: 26h
|
||
# Dsgn: 1w
|
||
# Dprp: 1h
|
||
# TTLsig: 1d
|
||
# retire-safety: 2d
|
||
#
|
||
# According to RFC 7583:
|
||
# Iret = Dsgn + Dprp + TTLsig (+retire-safety)
|
||
# Iret = 1w + 1h + 1d + 2d = 10d1h = 241h
|
||
#
|
||
# Tact(N) = now - Iret - Lzsk
|
||
# = now - 241h - 30d = now - 241h - 720h
|
||
# = now - 961h
|
||
# Tpub(N+1) = now - Iret - Ipub
|
||
# = now - 241h - 26h
|
||
# = now - 267h
|
||
# Tact(N+1) = now - Iret = now - 241h
|
||
TactN = "now-961h"
|
||
TpubN1 = "now-267h"
|
||
TactN1 = "now-241h"
|
||
TremN = "now"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
oldtimes = f"-P {TactN} -A {TactN} -I {TactN1} -D {TremN}"
|
||
newtimes = f"-P {TpubN1} -A {TactN1}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk1_name = keygen(f"{oldtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
z=f"UNRETENTIVE {TactN1}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
z=f"RUMOURED {TactN1}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(zsk1_name, zsk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk1_name, zsk2_name])
|
||
|
||
# Step 5:
|
||
# The predecessor DNSKEY is removed long enough that is has become HIDDEN.
|
||
zonename = f"step5.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract DNSKEY TTL + zone-propagation-delay from all the times (2h).
|
||
# Tact(N) = now - 961h - 2h = now - 963h
|
||
# Tpub(N+1) = now - 267h - 2h = now - 269h
|
||
# Tact(N+1) = now - 241h - 2h = now - 243h
|
||
# Trem(N) = Tact(N+1) + Iret = now -2h
|
||
TactN = "now-963h"
|
||
TremN = "now-2h"
|
||
TpubN1 = "now-269h"
|
||
TactN1 = "now-243h"
|
||
TremN = "now-2h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
oldtimes = f"-P {TactN} -A {TactN} -I {TactN1} -D {TremN}"
|
||
newtimes = f"-P {TpubN1} -A {TactN1}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk1_name = keygen(f"{oldtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"UNRETENTIVE {TremN}",
|
||
z=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
z=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(zsk1_name, zsk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk1_name, zsk2_name])
|
||
|
||
# Step 6:
|
||
# The predecessor DNSKEY can be purged.
|
||
zonename = f"step6.{zone}"
|
||
zones.append(Zone(zonename, f"{zonename}.db", Nameserver("ns3", "10.53.0.3")))
|
||
isctest.log.info(f"setup {zonename}")
|
||
# Subtract purge-keys interval from all the times (1h).
|
||
TactN = "now-964h"
|
||
TremN = "now-3h"
|
||
TpubN1 = "now-270h"
|
||
TactN1 = "now-244h"
|
||
TremN = "now-3h"
|
||
keytimes = f"-P {TactN} -A {TactN}"
|
||
oldtimes = f"-P {TactN} -A {TactN} -I {TactN1} -D {TremN}"
|
||
newtimes = f"-P {TpubN1} -A {TactN1}"
|
||
# Key generation.
|
||
ksk_name = keygen(f"-f KSK {keytimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk1_name = keygen(f"{oldtimes} {zonename}", cwd="ns3").out.strip()
|
||
zsk2_name = keygen(f"{newtimes} {zonename}", cwd="ns3").out.strip()
|
||
# Key state timing metadata.
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN}",
|
||
r=f"OMNIPRESENT {TactN}",
|
||
d=f"OMNIPRESENT {TactN}",
|
||
)
|
||
setkeytimes(ksk_name, timings)
|
||
timings = SettimeOptions(
|
||
g="HIDDEN",
|
||
k=f"HIDDEN {TremN}",
|
||
z=f"HIDDEN {TremN}",
|
||
)
|
||
setkeytimes(zsk1_name, timings)
|
||
timings = SettimeOptions(
|
||
g="OMNIPRESENT",
|
||
k=f"OMNIPRESENT {TactN1}",
|
||
z=f"OMNIPRESENT {TremN}",
|
||
)
|
||
setkeytimes(zsk2_name, timings)
|
||
# Set key rollover relationship.
|
||
set_key_relationship(zsk1_name, zsk2_name)
|
||
# Signing.
|
||
render_and_sign_zone(zonename, [ksk_name, zsk1_name, zsk2_name])
|
||
|
||
return zones
|