mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Create trust anchors from isctest.kasp.Key
Add isctest.kasp.Key and the minimal methods which are required tp 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. (manually picked from0bf20f8dandf6cb154b)
This commit is contained in:
parent
e1aff4b8eb
commit
4cca73b037
4 changed files with 118 additions and 0 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 %}
|
||||
};
|
||||
|
|
@ -13,6 +13,7 @@ from . import check
|
|||
from . import instance
|
||||
from . import hypothesis
|
||||
from . import query
|
||||
from . import kasp
|
||||
from . import run
|
||||
from . import template
|
||||
from . import log
|
||||
|
|
|
|||
91
bin/tests/system/isctest/kasp.py
Normal file
91
bin/tests/system/isctest/kasp.py
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# 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.
|
||||
|
||||
from functools import total_ordering
|
||||
from pathlib import Path
|
||||
|
||||
import dns.dnssec
|
||||
import dns.exception
|
||||
import dns.message
|
||||
import dns.name
|
||||
import dns.rcode
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
import dns.rrset
|
||||
import dns.tsig
|
||||
import dns.zone
|
||||
import dns.zonefile
|
||||
|
||||
from isctest.template import TrustAnchor
|
||||
|
||||
DEFAULT_TTL = 300
|
||||
|
||||
|
||||
@total_ordering
|
||||
class Key:
|
||||
"""
|
||||
Represent a key from a keyfile.
|
||||
|
||||
This object keeps track of its origin (keydir + name), can be used to
|
||||
retrieve metadata from the underlying files and supports convenience
|
||||
operations for KASP tests.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, keydir: str | Path | None = None):
|
||||
self.name = name
|
||||
if keydir is None:
|
||||
self.keydir = Path()
|
||||
else:
|
||||
self.keydir = Path(keydir)
|
||||
self.path = str(self.keydir / name)
|
||||
self.privatefile = f"{self.path}.private"
|
||||
self.keyfile = f"{self.path}.key"
|
||||
self.statefile = f"{self.path}.state"
|
||||
self.tag = int(self.name[-5:])
|
||||
self.external = False
|
||||
|
||||
@property
|
||||
def dnskey(self) -> dns.rrset.RRset:
|
||||
with open(self.keyfile, "r", encoding="utf-8") as file:
|
||||
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=dns.dnssec.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 __lt__(self, other: "Key"):
|
||||
return self.name < other.name
|
||||
|
||||
def __eq__(self, other: object):
|
||||
return isinstance(other, Key) and self.path == other.path
|
||||
|
||||
def __repr__(self):
|
||||
return self.path
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
# See the COPYRIGHT file distributed with this work for additional
|
||||
# information regarding copyright ownership.
|
||||
|
||||
from dataclasses import dataclass
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional, Union
|
||||
|
|
@ -98,3 +99,10 @@ class TemplateEngine:
|
|||
]
|
||||
for template in templates:
|
||||
self.render(template[:-3], data)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TrustAnchor:
|
||||
domain: str
|
||||
type: str
|
||||
contents: str
|
||||
|
|
|
|||
Loading…
Reference in a new issue