modified: netbox_dns_bridge/catalog_zone_manager.py

modified:   netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/utils.py
Various little bug fixes. Analysed by AI but fixed by hand to ensure integrity.
This commit is contained in:
Sven Luthi committed 2026-04-09 18:28:05 +02:00
1 parent 646059bb07
commit eedc01303b
3 files changed
+26 -20

No files matched your search

+3 -5
View File
@@ -62,12 +62,10 @@ def _set_serial(new_serial: int) -> bool:
def _increment_serial() -> None: def _increment_serial() -> None:
if not _set_serial(_SERIAL_OBJ.value + 1): if not _set_serial(_SERIAL_OBJ.value + 1):
logger.warning( logger.warning(
f"Failed to incremenet catalog serial {_SERIAL_OBJ.value}. Will overflow serial back to 1" f"Catalog serial {_SERIAL_OBJ.value} reached max — wrapping back to 1"
) )
_set_serial(1) _set_serial(1)
logger.debug( logger.debug(f"Catalog zone SOA serial number is now {_SERIAL_OBJ.value}")
f"Catalog zone SOA serial number incremented to {_SERIAL_OBJ.value}"
)
# If a zone has no catz identifier yet, create it: # If a zone has no catz identifier yet, create it:
@@ -230,5 +228,5 @@ def _generate_member_identifier() -> None:
def update_member_identifier(zone: Zone) -> None: def update_member_identifier(zone: Zone) -> None:
CatalogZoneMemberIdentifier.objects.update_or_create( CatalogZoneMemberIdentifier.objects.update_or_create(
zone=zone, zone=zone,
defaults={"name": _generate_member_identifier}, defaults={"name": _generate_member_identifier()},
) )
+21 -13
View File
@@ -125,13 +125,13 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
response.set_rcode(dns.rcode.REFUSED) response.set_rcode(dns.rcode.REFUSED)
if query.had_tsig: if query.had_tsig:
# Add TSIG with BADKEY, but do not sign (no MAC) # Add TSIG with error code, but do not sign (no MAC, empty keyring)
response.use_tsig( response.use_tsig(
keyring={}, # empty; we're not signing keyring={}, # empty; we're not signing
keyname=query.keyname, keyname=query.keyname,
tsig_error=tsig_error, tsig_error=tsig_error,
) )
self._deny_request(query) self._send_response(response.to_wire())
def _send_response(self, data) -> None: def _send_response(self, data) -> None:
raise NotImplementedError raise NotImplementedError
@@ -164,14 +164,11 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
self.server.keyring, keyname=query.keyname, original_id=query.id self.server.keyring, keyname=query.keyname, original_id=query.id
) )
else: else:
# If key is unknown # unknown key — use an empty keyring so use_tsig() does not
# raise KeyError trying to look up a key that isn't present.
response.set_rcode(dns.rcode.REFUSED) response.set_rcode(dns.rcode.REFUSED)
# Generate new key for keyname provided
# keyname = query.keyname
# b64 = base64.b64encode(urandom(32)).decode("ascii")
# newkey = dns.tsigkeyring.from_text({ keyname: b64 })
response.use_tsig( response.use_tsig(
self.server.keyring, {}, # empty keyring; no signing
keyname=query.keyname, keyname=query.keyname,
tsig_error=dns.rcode.BADKEY, tsig_error=dns.rcode.BADKEY,
) )
@@ -181,6 +178,13 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
logger.debug(f"{peer} SOA {nb_view.name}/{dname}") logger.debug(f"{peer} SOA {nb_view.name}/{dname}")
def _handle_axfr_request(self, query, zone, peer, nb_view, dname) -> None: def _handle_axfr_request(self, query, zone, peer, nb_view, dname) -> None:
if query.keyname not in self.server.keyring:
logger.error(f"AXFR aborted: keyname {query.keyname} not in keyring")
self._deny_request(query)
return
tsig_key = self.server.keyring[query.keyname]
rrsets = [] rrsets = []
soa_rrset = None soa_rrset = None
for name, rdataset in zone.iterate_rdatasets(): for name, rdataset in zone.iterate_rdatasets():
@@ -209,12 +213,9 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
) )
# 3. Loop through RRsets # 3. Loop through RRsets
tsig_key = self.server.keyring[query.keyname]
tsig_ctx = None tsig_ctx = None
for rrset in rrsets: for rrset in rrsets:
# logger.debug(f"Iterating over rrset {rrset}. tsig_ctx: {tsig_ctx}")
try: try:
# logger.debug(f"Adding {rrset} to renderer object")
r.add_rrset(dns.renderer.ANSWER, rrset) r.add_rrset(dns.renderer.ANSWER, rrset)
if r.max_size - len(r.output.getvalue()) < self.RESERVED_TSIG: if r.max_size - len(r.output.getvalue()) < self.RESERVED_TSIG:
raise dns.exception.TooBig("TSIG wont fit") raise dns.exception.TooBig("TSIG wont fit")
@@ -247,7 +248,15 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
query.question[0].rdtype, query.question[0].rdtype,
query.question[0].rdclass, query.question[0].rdclass,
) )
r.add_rrset(dns.renderer.ANSWER, rrset)
try:
r.add_rrset(dns.renderer.ANSWER, rrset)
except dns.exception.TooBig:
logger.error(
f"RRset {rrset.name}/{dns.rdatatype.to_text(rrset.rdtype)} "
f"exceeds MAX_WIRE ({self.MAX_WIRE}) and cannot be sent; "
f"skipping."
)
# 4. Final message with terminating TSIG # 4. Final message with terminating TSIG
r.write_header() r.write_header()
@@ -262,7 +271,6 @@ class DNSBaseRequestHandler(socketserver.BaseRequestHandler):
other_data=b"", other_data=b"",
request_mac=r.mac if tsig_ctx else query.mac, request_mac=r.mac if tsig_ctx else query.mac,
) )
wire = r.get_wire() wire = r.get_wire()
self._send_response(wire) self._send_response(wire)
+2 -2
View File
@@ -20,8 +20,8 @@ def export_bind_zone_file(nb_zone: netbox_dns.models.Zone, file_path: str):
rdata = dns.rdata.from_text(rdclass, rdatatype, record.value) rdata = dns.rdata.from_text(rdclass, rdatatype, record.value)
# Create rdataset # Create rdataset
rdataset = dns.rdataset.Rdataset(rdclass, rdatatype, record.ttl) rdataset = dns.rdataset.Rdataset(rdclass, rdatatype)
rdataset.add(rdata) rdataset.add(rdata, record.ttl)
# Add to zone # Add to zone
node = dp_zone.find_node(rname, create=True) node = dp_zone.find_node(rname, create=True)