Parse DNSKEY into a dnspython type in isctest.kasp.Key.dnskey

Previously, a DNSKEY string from keyfile was returned. This made the
function brittle for further processing, as the string would have to be
split up, concatenated, and TTL could be missing, making string indices
context-dependent.

Parse the DNSKEY rrset into a proper dnspython object and return it.
This makes the output more predictable and reliable, as all the
neccessary parsing is done by dnspython.
This commit is contained in:
Nicki Křížek 2025-10-24 16:47:59 +02:00
parent 1ede6683cd
commit 0bf20f8d68
2 changed files with 24 additions and 12 deletions

View file

@ -20,8 +20,12 @@ import time
from typing import Dict, List, Optional, Tuple, Union from typing import Dict, List, Optional, Tuple, Union
import dns import dns
import dns.rdatatype
import dns.rrset
import dns.tsig import dns.tsig
import pytest
import isctest.log import isctest.log
import isctest.query import isctest.query
import isctest.util import isctest.util
@ -443,12 +447,22 @@ class Key:
return int(line.split()[1]) return int(line.split()[1])
return 0 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: with open(self.keyfile, "r", encoding="utf-8") as file:
for line in file: rrsets = dns.zonefile.read_rrsets(
if "DNSKEY" in line: file.read(),
return line.strip() rdclass=None, # read rdclass from the file
return "undefined" 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 is_ksk(self) -> bool: def is_ksk(self) -> bool:
return self.get_metadata("KSK") == "yes" return self.get_metadata("KSK") == "yes"

View file

@ -102,11 +102,10 @@ def test_rollover_multisigner(ns3, alg, size):
expected2[0].legacy = True # noqa expected2[0].legacy = True # noqa
expected = expected + expected2 expected = expected + expected2
dnskey = newkeys[0].dnskey().split() dnskey = newkeys[0].dnskey
rdata = " ".join(dnskey[4:])
update_msg = dns.update.UpdateMessage(zone) 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) ns3.nsupdate(update_msg)
isctest.kasp.check_dnssec_verify(ns3, zone) 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) isctest.kasp.check_subdomain(ns3, zone, ksks, zsks)
# Remove ZSKs from the other providers for zone. # Remove ZSKs from the other providers for zone.
dnskey2 = extkeys[0].dnskey().split() dnskey2 = extkeys[0].dnskey
rdata2 = " ".join(dnskey2[4:])
update_msg = dns.update.UpdateMessage(zone) update_msg = dns.update.UpdateMessage(zone)
update_msg.delete(f"{dnskey[0]}", "DNSKEY", rdata) update_msg.delete(dnskey.name, dnskey[0])
update_msg.delete(f"{dnskey2[0]}", "DNSKEY", rdata2) update_msg.delete(dnskey2.name, dnskey2[0])
ns3.nsupdate(update_msg) ns3.nsupdate(update_msg)
isctest.kasp.check_dnssec_verify(ns3, zone) isctest.kasp.check_dnssec_verify(ns3, zone)