Commit Graph
41 Commits
Author SHA1 Message Date
sven ad0397bf61 Add unique constraint to IntegerKeyValueSetting.key
IntegerKeyValueSetting is used as a singleton-style key/value store:
callers do get(key=...) and get_or_create(key=..., ...) and assume at
most one row per key. The model, however, did not enforce uniqueness on
the key field, so nothing prevented duplicate rows at the database
level.

This was a real race for _create_soa_rdataset in catalog_zone_manager,
which calls get_or_create without select_for_update (unlike
increment_soa_serial, which does take a lock). Two concurrent AXFR
queries for a catalog zone could both pass the get_or_create existence
check and both insert a row for key='catalog-zone-soa-serial'. Every
subsequent IntegerKeyValueSetting.objects.get(key=...) call would then
raise MultipleObjectsReturned, breaking catalog-zone SOA rendering and
serial increments.

Add unique=True to the key CharField and ship migration 0003 to enforce
the invariant at the database level. Existing deployments are assumed to
have clean state (no duplicate keys); if duplicates exist, the migration
should be preceded by manual deduplication.
2026-08-11 12:10:07 +02:00
sven 55c562d5a7 Fix fall-through after OperationalError in TSIG key loading
In _load_tsig_key_settings, the OperationalError handler for the
View.objects.get(name=view_name) lookup called close_old_connections()
but should have exited the script instead. This is the initial startup
and if loading of settings fails, the script should simply exit.

Also contains some code cleaning
2026-08-11 12:08:51 +02:00
sven 038ae07c32 Make catalog zone name matching case-insensitive
DNS names are case-insensitive (RFC 4343), but the catalog-zone
dispatch compared dname verbatim:

    if dname == "catz" or dname == f"{nb_view.name}.catz":

dname is derived from qname.to_text(), which preserves the casing the
client sent. A query for CATZ, Public.catz, or any other mixed-case
variant failed the comparison and fell through to _get_zone_from_nb,
which returned None, so the request was denied instead of being served
as a catalog zone.

Lowercase both sides before comparing. Pass the lowercased name to
create_zone so catalog zones always get a canonical lowercase origin,
and pass the original dname to _get_zone_from_nb to leave the regular
zone-lookup behavior unchanged.
2026-08-11 11:20:46 +02:00
sven c56e52098b Share zone-building logic between AXFR and zone-file export
export_bind_zone_file diverged from the AXFR path in four ways, each a
bug:

- It iterated nb_zone.records.all(), including inactive records, whereas
  the AXFR handler filtered Record.objects.filter(zone=nb_zone,
  active=True). Exported zone files could contain stale/withdrawn
  records.
- It passed record.ttl straight to rdataset.add(), crashing with a
  TypeError when the NetBox DNS Record had no TTL set. The AXFR path
  used 'ttl = record.ttl or nb_zone.default_ttl'.
- It had no TXT quoting logic, so TXT values containing spaces or
  semicolons were mis-tokenized by dns.rdata.from_text (a ';' was
  treated as the start of a comment). The AXFR path quotes and chunks
  TXT values for exactly this reason.
- It appended a fresh rdataset to the node for every record instead of
  merging records that share a name and type, producing duplicate
  rdatasets and malformed zone files.

Extract build_dns_zone(nb_zone) in utils.py containing the corrected,
AXFR-proven record-building logic (active filter, TTL fallback, TXT
quoting/chunking, rdataset merging via rdatasets_dict). Rewrite
export_bind_zone_file to build the zone through build_dns_zone and then
write it. Rewrite request_handler._get_zone_from_nb to look up the
NetBox DNS Zone and delegate to build_dns_zone, keeping only the
DoesNotExist/OperationalError handling that is specific to the query
path.

Both code paths now produce identical zone data.
2026-08-11 11:11:57 +02:00
sven ba1b03106b Rename _getZoneFromNB to _get_zone_from_nb
_getZoneFromNB was the only camelCase function in the codebase,
inconsistent with the snake_case convention used everywhere else.
Rename it and update its callers and the adjacent comment.

Pure rename, no behavior change.
2026-08-11 11:11:07 +02:00
sven c6c7cf70ec Fix swallowed query-parse errors in request handler
The logging call passed the exception as a positional argument with no
%s placeholder in the format string:

    LOGGER.error("Error parsing query: ", e)

Python's logging applies msg % args, which raised TypeError (not all
arguments converted during string formatting) inside logging.handleError.
The logging framework swallows that secondary error, so neither the
intended message nor the exception was ever recorded.

Use an f-string so the exception is actually rendered and logged.
2026-08-11 11:10:20 +02:00
Sven Luthi cfb4633006 modified: netbox_dns_bridge/__init__.py
Bump version
2026-07-20 15:21:36 +02:00
Sven Luthi b4ab5596d6 modified: netbox_dns_bridge/notify_handler.py
modified:   netbox_dns_bridge/signals/netbox_dns_zones.py
Some code cleanup
2026-07-20 15:21:14 +02:00
Sven Luthi 11ea9a6f1a modified: README.md
modified:   netbox_dns_bridge/notify_handler.py
Remove hardcoded client notify port and connect to plugin setting
instead.
2026-07-20 15:07:21 +02:00
Sven Luethi c054a00039 Bump to v1.5.7 2026-07-16 14:27:49 +02:00
Sven Luethi 4eb018d8ca Merge pull request #25 from dmitriev-e/feature/force-notify-ns
Feature/force notify ns
2026-07-16 14:24:31 +02:00
d_ev 4ad41360de Address review: rename settings to notify_ns_* and add global toggle
Per PR review feedback:
- Rename settings: custom_field_force_notify -> notify_ns_custom_field_name,
  force_notify_port -> notify_ns_port.
- Add notify_ns_all_zones (bool, default False) to enable the feature globally
  for every zone; it coexists with the per-zone custom field — a NOTIFY is sent
  if the global switch is on OR the zone's custom field is set.
- Rename the internal job/scheduler/log strings to the notify_ns naming for
  consistency (SendZoneNSNotify, schedule_notify_ns).
- Update README and CHANGELOG.
2026-07-16 14:57:14 +03:00
d_ev db09fd70be Fix get_or_create tuple unpacking in catalog_zone_manager
v1.5.6 fixed the wrong RelatedObjectDoesNotExist import and the catz
member-identifier creation, but two get_or_create() calls still used the
returned value directly instead of unpacking the (obj, created) tuple:

- increment_soa_serial(): `soa_serial_obj.value` on a tuple
- _create_soa_rdataset(): `.get_or_create(...).value` on a tuple

Both raised `'tuple' object has no attribute 'value'` at runtime — the
first on every zone save, the second on every catalog-zone (catz) query.
Unpack the tuple in both places.
2026-07-15 22:44:53 +03:00
d_ev dc1c223400 Add forced NOTIFY feature for DNS zones
- Introduced `custom_field_force_notify` setting to trigger immediate NOTIFY to a zone's nameservers when its SOA serial number changes and the custom field is set to True.
- Updated README to document the new feature and its configuration.
- Refactored notify handler to include a new job for sending forced NOTIFY messages directly to zone nameservers.
- Enhanced zone signal handling to check for SOA serial changes and trigger forced NOTIFY accordingly.
2026-07-15 22:34:41 +03:00
Sven Luthi 41d48f2807 modified: netbox_dns_bridge/__init__.py
modified:   netbox_dns_bridge/catalog_zone_manager.py
Fix wrong import in previous version and slight change to
meachanism to create catz member identifier.
2026-07-15 17:48:49 +02:00
Sven Luthi e50cfd7cb6 modified: netbox_dns_bridge/__init__.py
Bump version
2026-07-14 17:51:37 +02:00
Sven Luethi fd8a5a0d9d modified: netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/management/commands/dns-transfer-endpoint.py
modified:   netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/signals/netbox_dns_zones.py
Range of bug fixes and improvements
2026-07-13 13:41:29 +02:00
Sven Luethi b72fa9b664 modified: README.md
modified:   netbox_dns_bridge/notify_handler.py
2026-07-11 02:46:17 +02:00
Sven Luethi a5d163b4af modified: netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/notify_handler.py
2026-07-11 01:44:21 +02:00
Sven Luethi f5791e94d5 modified: ../README.md
modified:   __init__.py
modified:   catalog_zone_manager.py
modified:   dns_server.py
modified:   notify_handler.py
Adding serial to notify messages to allow client to determine state.
2026-07-11 00:04:45 +02:00
Sven Luethi 3eb17187b4 modified: netbox_dns_bridge/__init__.py
modified:   netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/notify_handler.py
2026-07-10 22:05:51 +02:00
Sven Luethi 5747b044b6 modified: catalog_zone_manager.py
modified:   management/commands/dns-export-zone.py
modified:   management/commands/dns-export-zones.py
modified:   management/commands/dns-transfer-endpoint.py
modified:   notify_handler.py
modified:   request_handler.py
Guard all db requests against broken database connections.
2026-07-10 17:10:19 +02:00
Sven Luethi 2a89f4ae75 modified: netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/signals/netbox_dns_zones.py

1. On zone deletion the catalog zone serial was not incremented, causing clients
   not to delete the zone until another zone is created/modified. Fixed using
   post_delete signal.

2. Even with the notify_clients feature disabled, the client IPs were still
   being tracked. This disables the unnecessary behavior.

3. _track_seen_client function in DNSBaseRequestHandler did not have the 'self'
   reference parameter, causing calls to fail. Fixed.
2026-06-13 00:19:45 +02:00
Sven Luethi 73544a4335 modified: README.md
modified:   netbox_dns_bridge/notify_handler.py
modified:   netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/signals/netbox_dns_zones.py
Disable NOTIFY feature by default and add setting to enable it.
2026-06-11 16:33:47 +02:00
Sven Luethi e5808b4a57 Merge branch 'main' into dev 2026-06-11 14:07:44 +02:00
Peter Eckel 3f3426886e Replace explicit checks for STATUS_ACTIVE with the annotated "active" value 2026-06-11 10:11:19 +02:00
Sven Luethi 3eef3b4d7b modified: netbox_dns_bridge/__init__.py
modified:   netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/dns_server.py
modified:   netbox_dns_bridge/logger.py
new file:   netbox_dns_bridge/migrations/0002_alter_integerkeyvaluesetting_options_and_more.py
modified:   netbox_dns_bridge/models.py
new file:   netbox_dns_bridge/notify_handler.py
modified:   netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/signals/__init__.py
new file:   netbox_dns_bridge/signals/netbox_dns_zones.py
deleted:    netbox_dns_bridge/signals/transfer_endpoint.py
modified:   netbox_dns_bridge/utils.py

Implement notify mechanism
2026-06-11 00:32:26 +02:00
Sven Luethi a4036c285c modified: netbox_dns_bridge/catalog_zone_manager.py
Move state to DB
2026-05-23 14:58:24 +02:00
sven ea1b5ee2b4 renamed: signals.py -> signals/transfer_endpoint.py
new file:   signals/__init__.py
2026-04-10 15:31:19 +02:00
sven 67ccf83b1c modified: netbox_dns_bridge/__init__.py
modified:   netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/dns_server.py
new file:   netbox_dns_bridge/logger.py
modified:   netbox_dns_bridge/management/commands/dns-transfer-endpoint.py
modified:   netbox_dns_bridge/request_handler.py
Clean up logging
2026-04-10 15:08:10 +02:00
sven da6a5e09a5 modified: netbox_dns_bridge/__init__.py
Remove unneeded definition.

modified:   MANIFEST.in
Correct path

new file:   netbox_dns_bridge/migrations/__init__.py
Fixes missing migration.

new file:   netbox_dns_bridge/management/__init__.py
new file:   netbox_dns_bridge/management/commands/__init__.py
Just in case
2026-04-10 13:23:37 +02:00
Sven Luthi fd16f7e701 modified: netbox_dns_bridge/__init__.py
Bump version to 1.5.2
2026-04-09 18:51:54 +02:00
Sven Luthi f926795d1b modified: netbox_dns_bridge/request_handler.py
Change query logging from debug to info. Seeing queries is very useful :)
2026-04-09 18:36:14 +02:00
Sven Luthi eedc01303b 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.
2026-04-09 18:28:05 +02:00
Sven Luthi 646059bb07 modified: netbox_dns_bridge/signals.py
Fix import path
2026-04-09 17:27:00 +02:00
Sven Luthi f41b4cea56 modified: netbox_dns_bridge/request_handler.py
Closes issue #15
2026-04-09 15:04:39 +02:00
Sven Luthi 53b12c9e15 modified: README.md - Improve post 1.0.7 upgrade guide.
modified:   pyproject.toml - Fix to licensing file reference.
2026-04-09 13:58:55 +02:00
Sven Luthi c32161b8a2 modified: netbox_dns_bridge/catalog_zone_manager.py
modified:   netbox_dns_bridge/dns_server.py
modified:   netbox_dns_bridge/management/commands/dns-export-zone.py
modified:   netbox_dns_bridge/management/commands/dns-export-zones.py
modified:   netbox_dns_bridge/management/commands/dns-settings.py
modified:   netbox_dns_bridge/management/commands/dns-transfer-endpoint.py
modified:   netbox_dns_bridge/migrations/0001_initial.py
modified:   netbox_dns_bridge/models.py
modified:   netbox_dns_bridge/request_handler.py
modified:   netbox_dns_bridge/signals.py
modified:   netbox_dns_bridge/utils.py
Black code formating corrected
2026-04-08 20:14:38 +02:00
sven f713719543 modified: pyproject.toml
Fix paths after restructuring

renamed:    netbox_dns_bridge/management/commands/export-dns-zone.py -> netbox_dns_bridge/management/commands/dns-export-zone.py
renamed:    netbox_dns_bridge/management/commands/export-all-dns-zones.py -> netbox_dns_bridge/management/commands/dns-export-zones.py
Unify command naming scheme

new file:   netbox_dns_bridge/migrations/0001_initial.py
Adds the missing migration. Since the plugin was renamed this is also an opportunity to merge all changes into a single migration.

renamed:    netbox_dns_bridge/service/transfer/catalog_zone_manager.py -> netbox_dns_bridge/catalog_zone_manager.py
renamed:    netbox_dns_bridge/service/transfer/dns_server.py -> netbox_dns_bridge/dns_server.py
new file:   netbox_dns_bridge/management/commands/dns-settings.py
modified:   netbox_dns_bridge/management/commands/dns-transfer-endpoint.py
renamed:    netbox_dns_bridge/service/transfer/request_handler.py -> netbox_dns_bridge/request_handler.py
deleted:    netbox_dns_bridge/service/transfer/__init__.py
Another restructure to simplify code re-use. New command dns-settings added to allow setting of catalog zone serial.
This will be needed to migrate from previous versions.
2026-04-08 20:09:13 +02:00
sven 79ae6c2068 modified: README.md
modified:   netbox_dns_bridge/__init__.py
modified:   CHANGELOG.md
Change versioning scheme to mach netbox-plugin-dns
2026-04-08 18:58:37 +02:00
Sven Luthi 756c491e28 Renaming Project and changing license 2026-04-08 10:24:24 +02:00