1 # Copyright (C) Internet Systems Consortium, Inc. ("ISC") 2 # 3 # SPDX-License-Identifier: MPL-2.0 4 # 5 # This Source Code Form is subject to the terms of the Mozilla Public 6 # License, v. 2.0. If a copy of the MPL was not distributed with this 7 # file, you can obtain one at https://mozilla.org/MPL/2.0/. 8 # 9 # See the COPYRIGHT file distributed with this work for additional 10 # information regarding copyright ownership. 11 12 # pylint: disable=redefined-outer-name,unused-import 13 14 import pytest 15 16 import isctest 17 from isctest.kasp import Ipub, IpubC, Iret 18 from isctest.util import param 19 from rollover.common import ( 20 pytestmark, 21 alg, 22 size, 23 CDSS, 24 TIMEDELTA, 25 ) 26 from rollover.setup import ( 27 configure_root, 28 configure_tld, 29 configure_enable_dnssec, 30 ) 31 32 CONFIG = { 33 "dnskey-ttl": TIMEDELTA["PT5M"], 34 "ds-ttl": TIMEDELTA["PT2H"], 35 "max-zone-ttl": TIMEDELTA["PT12H"], 36 "parent-propagation-delay": TIMEDELTA["PT1H"], 37 "publish-safety": TIMEDELTA["PT5M"], 38 "retire-safety": TIMEDELTA["PT20M"], 39 "signatures-refresh": TIMEDELTA["P7D"], 40 "signatures-validity": TIMEDELTA["P14D"], 41 "zone-propagation-delay": TIMEDELTA["PT5M"], 42 } 43 POLICY = "enable-dnssec" 44 IPUB = Ipub(CONFIG) 45 IPUBC = IpubC(CONFIG, rollover=False) 46 IRETZSK = Iret(CONFIG, rollover=False) 47 IRETKSK = Iret(CONFIG, zsk=False, ksk=True, rollover=False) 48 OFFSETS = {} 49 OFFSETS["step1"] = 0 50 OFFSETS["step2"] = -int(IPUB.total_seconds()) 51 OFFSETS["step3"] = -int(IRETZSK.total_seconds()) 52 OFFSETS["step4"] = -int(IPUBC.total_seconds() + IRETKSK.total_seconds()) 53 54 55 def bootstrap(): 56 data = { 57 "tlds": [], 58 "trust_anchors": [], 59 } 60 61 tlds = [] 62 for tld_name in [ 63 "autosign", 64 "manual", 65 ]: 66 delegations = configure_enable_dnssec(tld_name, f"{POLICY}-{tld_name}") 67 68 tld = configure_tld(tld_name, delegations) 69 tlds.append(tld) 70 71 data["tlds"].append(tld_name) 72 73 ta = configure_root(tlds) 74 data["trust_anchors"].append(ta) 75 76 return data 77 78 79 @pytest.mark.parametrize( 80 "tld", 81 [ 82 param("autosign"), 83 param("manual"), 84 ], 85 ) 86 def test_rollover_enable_dnssec_step1(tld, alg, size, ns3): 87 zone = f"step1.enable-dnssec.{tld}" 88 policy = f"{POLICY}-{tld}" 89 90 isctest.kasp.wait_keymgr_done(ns3, zone) 91 92 if tld == "manual": 93 # Same as insecure. 94 step = { 95 "zone": zone, 96 "cdss": CDSS, 97 "keyprops": [], 98 "manual-mode": True, 99 "zone-signed": False, 100 "nextev": None, 101 } 102 isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 103 104 # Check logs. 105 msg = f"keymgr-manual-mode: block new key generation for zone {zone} (policy {policy})" 106 assert msg in ns3.log 107 108 # Force step. 109 with ns3.watch_log_from_here() as watcher: 110 ns3.rndc(f"dnssec -step {zone}") 111 watcher.wait_for_line(f"keymgr: {zone} done") 112 113 step = { 114 "zone": zone, 115 "cdss": CDSS, 116 "keyprops": [ 117 f"csk unlimited {alg} {size} goal:omnipresent dnskey:rumoured krrsig:rumoured zrrsig:rumoured ds:hidden offset:{OFFSETS['step1']}", 118 ], 119 # Next key event is when the DNSKEY RRset becomes OMNIPRESENT, 120 # after the publication interval. 121 "nextev": IPUB, 122 } 123 isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 124 125 126 @pytest.mark.parametrize( 127 "tld", 128 [ 129 param("autosign"), 130 param("manual"), 131 ], 132 ) 133 def test_rollover_enable_dnssec_step2(tld, alg, size, ns3): 134 zone = f"step2.enable-dnssec.{tld}" 135 policy = f"{POLICY}-{tld}" 136 137 isctest.kasp.wait_keymgr_done(ns3, zone) 138 139 # manual-mode: Nothing changing in the zone, no 'dnssec -step' required. 140 141 step = { 142 "zone": zone, 143 "cdss": CDSS, 144 # The DNSKEY is omnipresent, but the zone signatures not yet. 145 # Thus, the DS remains hidden. 146 # dnskey: rumoured -> omnipresent 147 # krrsig: rumoured -> omnipresent 148 "keyprops": [ 149 f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:rumoured ds:hidden offset:{OFFSETS['step2']}", 150 ], 151 # Next key event is when the zone signatures become OMNIPRESENT, 152 # Minus the time already elapsed. 153 "nextev": IRETZSK - IPUB, 154 } 155 isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 156 157 158 @pytest.mark.parametrize( 159 "tld", 160 [ 161 param("autosign"), 162 param("manual"), 163 ], 164 ) 165 def test_rollover_enable_dnssec_step3(tld, alg, size, ns3): 166 zone = f"step3.enable-dnssec.{tld}" 167 policy = f"{POLICY}-{tld}" 168 169 isctest.kasp.wait_keymgr_done(ns3, zone) 170 171 if tld == "manual": 172 # Same as step 2, but zone signatures have become OMNIPRESENT. 173 step = { 174 "zone": zone, 175 "cdss": CDSS, 176 "keyprops": [ 177 f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:hidden offset:{OFFSETS['step3']}", 178 ], 179 "manual-mode": True, 180 "nextev": None, 181 } 182 keys = isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 183 184 # Check logs. 185 tag = keys[0].key.tag 186 msg = f"keymgr-manual-mode: block transition CSK {zone}/ECDSAP256SHA256/{tag} type DS state HIDDEN to state RUMOURED" 187 assert msg in ns3.log 188 189 # Force step. 190 with ns3.watch_log_from_here() as watcher: 191 ns3.rndc(f"dnssec -step {zone}") 192 watcher.wait_for_line( 193 f"zone {zone}/IN (signed): zone_rekey done: key {tag}/ECDSAP256SHA256" 194 ) 195 196 step = { 197 "zone": zone, 198 "cdss": CDSS, 199 # All signatures should be omnipresent, so the DS can be submitted. 200 # zrrsig: rumoured -> omnipresent 201 # ds: hidden -> rumoured 202 "keyprops": [ 203 f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:rumoured offset:{OFFSETS['step3']}", 204 ], 205 # Next key event is when the DS can move to the OMNIPRESENT state. 206 # This is after the retire interval. 207 "nextev": IRETKSK, 208 } 209 isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 210 211 212 @pytest.mark.parametrize( 213 "tld", 214 [ 215 param("autosign"), 216 param("manual"), 217 ], 218 ) 219 def test_rollover_enable_dnssec_step4(tld, alg, size, ns3): 220 zone = f"step4.enable-dnssec.{tld}" 221 policy = f"{POLICY}-{tld}" 222 223 isctest.kasp.wait_keymgr_done(ns3, zone) 224 225 # manual-mode: Nothing changing in the zone, no 'dnssec -step' required. 226 227 step = { 228 "zone": zone, 229 "cdss": CDSS, 230 # DS has been published long enough. 231 # ds: rumoured -> omnipresent 232 "keyprops": [ 233 f"csk unlimited {alg} {size} goal:omnipresent dnskey:omnipresent krrsig:omnipresent zrrsig:omnipresent ds:omnipresent offset:{OFFSETS['step4']}", 234 ], 235 # Next key event is never, the zone dnssec-policy has been 236 # established. So we fall back to the default loadkeys interval. 237 "nextev": TIMEDELTA["PT1H"], 238 } 239 isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step) 240