mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
new: test: Create trust anchors from isctest.kasp.Key
Add isctest.kasp.Key.into_ta() method which convert the key into DS / DNSKEY trust anchor for BIND config. Add a shared template trusted.conf.j2 which can be linked to in tests to create the trust anchor configuration from trust anchor data returned from bootstrap() function. This is basically a python replacement for the keyfile_to_static_ds (and friends) from the conf.sh shell framework. Merge branch 'nicki/pytest-add-trust-anchor-template' into 'main' See merge request isc-projects/bind9!11201
This commit is contained in:
commit
d2777a6e78
5 changed files with 80 additions and 12 deletions
18
bin/tests/system/_common/trusted.conf.j2
Normal file
18
bin/tests/system/_common/trusted.conf.j2
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
trust-anchors {
|
||||
{% for ta in trust_anchors %}
|
||||
"@ta.domain@" @ta.type@ @ta.contents@;
|
||||
{% endfor %}
|
||||
};
|
||||
|
|
@ -54,3 +54,17 @@ else:
|
|||
class EDEOption:
|
||||
def __new__(cls, *args, **kwargs):
|
||||
raise RuntimeError("Using EDEOption requires dnspython>=2.2.0")
|
||||
|
||||
|
||||
# pylint: disable=unused-import
|
||||
try:
|
||||
from dns.dnssec import DSDigest
|
||||
except ImportError: # dnspython<2.0.0
|
||||
import enum
|
||||
|
||||
class DSDigest(enum.IntEnum): # type: ignore
|
||||
"""DNSSEC Delgation Signer Digest Algorithm"""
|
||||
|
||||
SHA1 = 1
|
||||
SHA256 = 2
|
||||
SHA384 = 4
|
||||
|
|
|
|||
|
|
@ -20,12 +20,19 @@ import time
|
|||
from typing import Dict, List, Optional, Tuple, Union
|
||||
|
||||
import dns
|
||||
import dns.dnssec
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
import dns.tsig
|
||||
|
||||
import pytest
|
||||
|
||||
import isctest.log
|
||||
import isctest.query
|
||||
import isctest.util
|
||||
from isctest.compat import DSDigest
|
||||
from isctest.instance import NamedInstance
|
||||
from isctest.template import TrustAnchor
|
||||
from isctest.vars.algorithms import Algorithm, ALL_ALGORITHMS_BY_NUM
|
||||
|
||||
DEFAULT_TTL = 300
|
||||
|
|
@ -443,12 +450,35 @@ class Key:
|
|||
return int(line.split()[1])
|
||||
return 0
|
||||
|
||||
def dnskey(self):
|
||||
@property
|
||||
def dnskey(self) -> dns.rrset.RRset:
|
||||
pytest.importorskip("dns", minversion="2.2.0") # dns.zonefile.read_rrsets
|
||||
with open(self.keyfile, "r", encoding="utf-8") as file:
|
||||
for line in file:
|
||||
if "DNSKEY" in line:
|
||||
return line.strip()
|
||||
return "undefined"
|
||||
rrsets = dns.zonefile.read_rrsets(
|
||||
file.read(),
|
||||
rdclass=None, # read rdclass from the file
|
||||
default_ttl=DEFAULT_TTL, # use this TTL if not present
|
||||
)
|
||||
assert len(rrsets) == 1, f"{self.keyfile} has multiple RRsets"
|
||||
dnskey_rr = rrsets[0]
|
||||
assert len(dnskey_rr) == 1, f"{self.keyfile} has multiple RRs"
|
||||
assert (
|
||||
dnskey_rr.rdtype == dns.rdatatype.DNSKEY
|
||||
), f"DNSKEY not found in {self.keyfile}"
|
||||
return dnskey_rr
|
||||
|
||||
def into_ta(self, ta_type: str, dsdigest=DSDigest.SHA256) -> TrustAnchor:
|
||||
dnskey = self.dnskey
|
||||
if ta_type in ["static-ds", "initial-ds"]:
|
||||
ds = dns.dnssec.make_ds(dnskey.name, dnskey[0], dsdigest)
|
||||
parts = str(ds).split()
|
||||
contents = " ".join(parts[:3]) + f' "{parts[3]}"'
|
||||
elif ta_type in ["static-key", "initial-key"]:
|
||||
parts = str(dnskey).split()
|
||||
contents = " ".join(parts[4:7]) + f' "{"".join(parts[7:])}"'
|
||||
else:
|
||||
raise ValueError(f"invalid trust anchor type: {ta_type}")
|
||||
return TrustAnchor(str(dnskey.name), ta_type, contents)
|
||||
|
||||
def is_ksk(self) -> bool:
|
||||
return self.get_metadata("KSK") == "yes"
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional, Union
|
||||
|
||||
|
|
@ -79,3 +80,10 @@ class TemplateEngine:
|
|||
]
|
||||
for template in templates:
|
||||
self.render(template[:-3], data)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TrustAnchor:
|
||||
domain: str
|
||||
type: str
|
||||
contents: str
|
||||
|
|
|
|||
|
|
@ -102,11 +102,10 @@ def test_rollover_multisigner(ns3, alg, size):
|
|||
expected2[0].legacy = True # noqa
|
||||
expected = expected + expected2
|
||||
|
||||
dnskey = newkeys[0].dnskey().split()
|
||||
rdata = " ".join(dnskey[4:])
|
||||
dnskey = newkeys[0].dnskey
|
||||
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
update_msg.add(f"{dnskey[0]}", 3600, "DNSKEY", rdata)
|
||||
update_msg.add(dnskey.name, dnskey.ttl, dnskey[0])
|
||||
ns3.nsupdate(update_msg)
|
||||
|
||||
isctest.kasp.check_dnssec_verify(ns3, zone)
|
||||
|
|
@ -118,11 +117,10 @@ def test_rollover_multisigner(ns3, alg, size):
|
|||
isctest.kasp.check_subdomain(ns3, zone, ksks, zsks)
|
||||
|
||||
# Remove ZSKs from the other providers for zone.
|
||||
dnskey2 = extkeys[0].dnskey().split()
|
||||
rdata2 = " ".join(dnskey2[4:])
|
||||
dnskey2 = extkeys[0].dnskey
|
||||
update_msg = dns.update.UpdateMessage(zone)
|
||||
update_msg.delete(f"{dnskey[0]}", "DNSKEY", rdata)
|
||||
update_msg.delete(f"{dnskey2[0]}", "DNSKEY", rdata2)
|
||||
update_msg.delete(dnskey.name, dnskey[0])
|
||||
update_msg.delete(dnskey2.name, dnskey2[0])
|
||||
ns3.nsupdate(update_msg)
|
||||
|
||||
isctest.kasp.check_dnssec_verify(ns3, zone)
|
||||
|
|
|
|||
Loading…
Reference in a new issue