netbox-windows-dhcp-plugin 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. netbox_windows_dhcp_plugin-0.1.0/.gitignore +25 -0
  2. netbox_windows_dhcp_plugin-0.1.0/CHANGELOG.md +247 -0
  3. netbox_windows_dhcp_plugin-0.1.0/LICENSE +202 -0
  4. netbox_windows_dhcp_plugin-0.1.0/PKG-INFO +137 -0
  5. netbox_windows_dhcp_plugin-0.1.0/README.md +104 -0
  6. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/__init__.py +44 -0
  7. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/api/__init__.py +0 -0
  8. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/api/serializers.py +362 -0
  9. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/api/urls.py +25 -0
  10. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/api/views.py +196 -0
  11. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/choices.py +222 -0
  12. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/conf.py +171 -0
  13. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/connection.py +113 -0
  14. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/filtersets.py +348 -0
  15. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/forms.py +884 -0
  16. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/graphql/__init__.py +3 -0
  17. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/graphql/filters.py +133 -0
  18. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/graphql/schema.py +60 -0
  19. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/graphql/types.py +179 -0
  20. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/import_status.py +314 -0
  21. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/integrations/__init__.py +0 -0
  22. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/integrations/branching.py +571 -0
  23. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/jobs.py +603 -0
  24. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/leases.py +59 -0
  25. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0001_initial.py +837 -0
  26. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0002_import_fields.py +31 -0
  27. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0003_remaining_objects.py +193 -0
  28. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0004_reservation_iaid.py +18 -0
  29. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0005_syncrun_destination.py +15 -0
  30. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/0006_windowsserver_reported_names.py +18 -0
  31. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/migrations/__init__.py +0 -0
  32. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/models/__init__.py +36 -0
  33. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/models/dhcp.py +821 -0
  34. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/models/servers.py +254 -0
  35. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/models/sync.py +223 -0
  36. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/navigation.py +64 -0
  37. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/object_actions.py +142 -0
  38. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/review.py +58 -0
  39. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/search.py +56 -0
  40. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/signals.py +270 -0
  41. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/__init__.py +7 -0
  42. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/diff.py +134 -0
  43. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/importer.py +518 -0
  44. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/mapping.py +812 -0
  45. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/netbox_state.py +568 -0
  46. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/push.py +826 -0
  47. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/pusher.py +216 -0
  48. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/windows_state.py +855 -0
  49. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/sync/windows_writer.py +571 -0
  50. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/tables.py +430 -0
  51. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/buttons/bulk_post.html +3 -0
  52. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/buttons/import.html +56 -0
  53. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/buttons/post.html +6 -0
  54. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/import_main_confirm.html +26 -0
  55. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/inc/import_branch_outcome.html +27 -0
  56. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/inc/import_branch_rows.html +30 -0
  57. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/inc/import_status.html +165 -0
  58. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/inc/lease_panel.html +83 -0
  59. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/templates/netbox_windows_dhcp_plugin/subnet_leases.html +9 -0
  60. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/ui/__init__.py +0 -0
  61. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/ui/panels.py +201 -0
  62. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/urls.py +32 -0
  63. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/version.py +1 -0
  64. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/views.py +741 -0
  65. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/__init__.py +18 -0
  66. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/client.py +2105 -0
  67. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/fake.py +1307 -0
  68. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/normalize.py +251 -0
  69. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/psscript.py +316 -0
  70. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/runner.py +130 -0
  71. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/ssh.py +319 -0
  72. netbox_windows_dhcp_plugin-0.1.0/netbox_windows_dhcp_plugin/windows/winrm.py +148 -0
  73. netbox_windows_dhcp_plugin-0.1.0/pyproject.toml +80 -0
@@ -0,0 +1,25 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .coverage
10
+ htmlcov/
11
+ site/
12
+ dev/data/
13
+ .env
14
+
15
+ # Local Claude Code notes, kept out of the repo
16
+ CLAUDE.md
17
+ .claude/
18
+
19
+ # Lab server settings and credentials for the dev stack
20
+ dev/env/lab.env
21
+ # Lab test output (raw envelopes and property dumps): may identify the lab, never commit
22
+ .lab/
23
+
24
+ # Browser automation scratch output
25
+ .playwright-mcp/
@@ -0,0 +1,247 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.1.0] - 2026-10-27
9
+
10
+ Release candidates 0.1.0rc1 to 0.1.0rc5 (2026-10-21 to 2026-10-23) went to PyPI for testing; what testing them found
11
+ is listed under Fixed.
12
+
13
+ First release. Every v1 feature is in place and tested against the fake server and PowerShell stubs. The lab tests
14
+ against real Windows servers (`make test-lab`, `make lab-e2e`) ran in full on two Windows Server 2022 DHCP servers,
15
+ failover included; what they found is listed under Fixed, and the few details they could not reach are listed in
16
+ the documentation's limitations page.
17
+
18
+ ### Added
19
+
20
+ Connections and security
21
+
22
+ - Windows server connection settings linked to netbox-plugin-dhcp servers: WinRM (NTLM, Basic, Kerberos or CredSSP, HTTPS by
23
+ default; CredSSP is what failover writes need) or SSH, with an optional `computer_name` for a management host.
24
+ - Credential profiles in `PLUGINS_CONFIG`, each secret inline, from an environment variable or a file. Nothing secret
25
+ is stored in the database, the change log or job logs.
26
+ - `allowed_hosts` on credential profiles limits which hosts their credentials can be sent to, checked when a Windows
27
+ server is saved and before every connection. Basic authentication requires HTTPS with certificate checks. SSH
28
+ always verifies the host key (pinned key or the worker's known_hosts).
29
+ - "Test connection" button and REST action, run as a background job.
30
+
31
+ Models and API
32
+
33
+ - Models for what netbox-plugin-dhcp does not hold: Windows scope and reservation settings (including the DHCPv6
34
+ IAID), exclusion ranges, user and vendor classes, option definitions (Windows data type and default value),
35
+ option qualifiers, vendor class option definitions and values, policies, failover relationships, MAC filters and
36
+ the allow and deny list switches.
37
+ - Sync bookkeeping: sync state, sync runs and import proposals.
38
+ - REST API and GraphQL for every model. Names of classes, policies, superscopes and failover relationships compare
39
+ without case, as on Windows.
40
+
41
+ Import (Windows to NetBox)
42
+
43
+ - IPv4 scopes, superscopes, exclusion ranges, reservations, user and vendor classes, option definitions, vendor class
44
+ options, policies (conditions, IP ranges, processing order, lease time), failover relationships, MAC filters and
45
+ option values at server, scope, reservation, user class and policy level. They become netbox-plugin-dhcp objects
46
+ plus the prefixes, IP ranges, IP addresses and MAC addresses they need, in the server's import VRF. Objects missing
47
+ on Windows are proposed for deletion.
48
+ - DHCPv6 scopes (lifetimes, T1 and T2, state, preference), reservations (DUID, IAID), user classes and option values
49
+ against netbox-plugin-dhcp's standard DHCPv6 definitions. DHCPv6 vendor classes and values, other option codes and
50
+ exclusion ranges are noted and left alone.
51
+ - Option values containing a comma, stored as `\,` (Kea's escape).
52
+ - With netbox-branching, the **Import** button is a menu: **Import into branch** (an import branch, the default),
53
+ **Import into this branch** (the branch you work in, no new branch) and **Import directly** (into main, after a
54
+ confirmation page, with your permissions checked object by object and change control's `protect_main` respected;
55
+ the new `import_direct` setting turns it off). The REST import action takes the same choice as `destination`. Sync
56
+ runs record where each import wrote (new **Destination** column and filter), and the Import panel says so while
57
+ the import is queued, running and done (#36).
58
+ - With netbox-branching, each import writes into a branch `dhcp-import/<server>/<timestamp>` (reused while open) and,
59
+ with netbox-change-control, opens a change request submitted for review.
60
+ - Without branching, each import fills an import proposal whose items are applied or dismissed one by one, in bulk
61
+ or for the whole proposal, from the UI or the REST API. Applying writes as the reviewing user, checks their
62
+ permissions, and refuses items whose NetBox object changed since the import.
63
+ - "Import now" button and REST action, and scheduled imports every `import_interval` minutes (`import_user` for
64
+ scheduled imports with branching).
65
+
66
+ Push (NetBox to Windows)
67
+
68
+ - A reconcile per server that creates, updates and deletes every kind above, in dependency order, so Windows matches
69
+ NetBox.
70
+ - Only objects recorded in sync state are deleted. Objects created by hand on Windows are left alone, and so are
71
+ managed objects changed on Windows since the last push and objects whose removal would take unmanaged ones with
72
+ them. Identical objects are adopted as managed; applying an import item adopts it straight away.
73
+ - NetBox data Windows cannot hold (a scope without a pool, a reservation without a MAC address, options 1 and 51,
74
+ values of codes Windows does not define) is reported in the sync run instead of pushed. A scope subnet mask or an
75
+ option definition type is never changed in place, and a scope with leases is never force-removed.
76
+ - With netbox-branching, merging or reverting a branch queues a push for each Windows server it touched. Other saves
77
+ (all of them without branching, direct edits of main with it) queue one push per server after commit,
78
+ `push_debounce` seconds later. `sync_enabled = False` stops pushes.
79
+ - "Sync now" and "Dry run" buttons and REST actions. A dry run records the planned changes in its sync run.
80
+ - Failover: relationships are written on the primary, with the shared secret read from the credential profile named
81
+ in `shared_secret_profile`; the changed scopes are then replicated to the partner. A scope leaving a relationship
82
+ leaves it before it is deleted, and a scope with leases is refused before anything changes.
83
+ - One import or push per server at a time across all workers (a PostgreSQL advisory lock); a busy push retries a
84
+ minute later.
85
+
86
+ Leases
87
+
88
+ - A Leases tab on the subnet page of Windows scopes (IPv4 and DHCPv6) reads the live leases in a background job.
89
+ Viewing needs the subnet and its Windows server, loading needs permission to change the server, and is refused
90
+ inside a branch. Leases are not stored.
91
+
92
+ Documentation
93
+
94
+ - A documentation site (https://thomaschristory.github.io/netbox-windows-dhcp-plugin/): installation, preparing
95
+ Windows, configuration, a first-sync walkthrough, how objects map, import, push, DHCPv6, failover, leases,
96
+ permissions, REST API and GraphQL, security, workers and jobs, troubleshooting and limitations.
97
+ - Screenshots from a lab run on real Windows servers: the first-sync walkthrough step by step, import proposals and
98
+ import branches with change requests, a new scope built in NetBox and pushed, a failover relationship, the Leases
99
+ tab and a failed push.
100
+ - Installation: netbox-change-control needs at least one policy, or change requests (an import's included) can never be
101
+ approved. How objects map: netbox-plugin-dhcp 0.2.0 does not save comments from its edit forms
102
+ (sys4/netbox-plugin-dhcp#68).
103
+ - `SECURITY.md`: report vulnerabilities through GitHub's private vulnerability reporting.
104
+
105
+ Development
106
+
107
+ - `dev/scripts/lab-server-setup.ps1` prepares a Windows Server VM as the lab server (DHCP role, a least-privilege
108
+ account, WinRM over HTTPS).
109
+ - Opt-in lab tests against a real Windows DHCP server: `make test-lab` (the client over WinRM, one round trip per
110
+ unverified cmdlet) and `make lab-e2e` (import, push and leases on the dev stack). They only touch `nbwd-test-`
111
+ objects in `198.18.0.0/15` and `2001:db8:4e42::/64`.
112
+
113
+ ### Fixed
114
+
115
+ - The Windows servers list links each server's name to its Windows server page (actions, Import panel, sync runs),
116
+ as the sync run pages do, saved table layouts included; the generic netbox-plugin-dhcp server stays linked in a
117
+ new **Generic DHCP server** column (#38).
118
+ - The plugin's buttons (Test connection, Sync now, Dry run, Import now, and Apply all, Dismiss all, Apply and Dismiss
119
+ on the review queue) were rendered without a CSRF token, so clicking them failed with "CSRF verification failed"
120
+ (403). They now carry the token (#19).
121
+ - Read-only pages (sync runs, import proposals and their items) showed Edit, Clone, Add, Import or Edit Selected
122
+ buttons that led to a "None" address and a 404. Pages now show only the buttons whose views exist; Delete and the
123
+ review actions stay. Lists without CSV import or bulk edit no longer offer those buttons either (#23).
124
+
125
+ Found by a first, partial lab run against Windows Server 2025:
126
+
127
+ - A Windows object that does not exist is reported as missing again, instead of as an object with every field empty.
128
+ Windows PowerShell 5.1 printed "nothing found" as `{}`; the script envelope now turns it into `null`, and the
129
+ client also reads `{}` as missing. This affected MAC filters, superscopes, policies, DHCPv6 scopes, classes,
130
+ option values and every other lookup (#15).
131
+ - Renaming a superscope uses the cmdlet's real `-Name` parameter instead of `-SuperscopeName`, which Windows rejected
132
+ (#14).
133
+ - Option values on an IPv4 reservation are written and removed with `-ReservedIP` alone: Windows refuses `-ScopeId`
134
+ next to it, so a push of a reservation option failed (#20).
135
+ - Option values on a DHCPv6 reservation are written and removed with `-ReservedIP` alone, for the same reason with
136
+ `-Prefix` (#17).
137
+ - DHCPv6 leases no longer read an `AddressState` property Windows does not have; the Leases tab shows their state as
138
+ n/a, since Windows reports none for DHCPv6 (#22).
139
+ - The policy lab test uses a condition Windows accepts (`*.Example.Test`), checks FQDN policies apart from policy IP
140
+ ranges and option values (which Windows refuses on FQDN policies, DHCP 20135 and 20136), and the fake server now
141
+ refuses a wildcard in the middle of a condition, as Windows does (#18).
142
+ - A new DHCPv6 scope pushed without renewal and rebinding times now gets Windows' own default rebinding time (T2),
143
+ 6.4 days (6 days 9:36), instead of 6 days 10 hours, so it matches a scope made on Windows without them (#16).
144
+ Renewal and rebinding times left empty in NetBox now follow the scope's preferred lifetime (half and 80 % of it,
145
+ which gives Windows' 4 and 6.4 days for the default 8 days), so a scope with a preferred lifetime shorter than
146
+ 6.4 days no longer gets timers past it, which Windows documents as invalid. An existing scope keeps its Windows
147
+ timers while they still fit below the preferred lifetime. When only one of T1 and T2 is set in NetBox, the empty
148
+ one is now worked out against it (T1 at 5/8 of T2, or T2 halfway between T1 and the preferred lifetime, when the
149
+ default would not fit), instead of a default that could land on the wrong side and be refused by Windows.
150
+ - Policy conditions Windows stores in its own spelling no longer show as changed after every push or import: a MAC
151
+ prefix such as `02-4e-42-ab*` (read back as `02-4e-42-ab-*`) and a host name in mixed case (read back in
152
+ lowercase) now compare equal, so a second push is a no-op (#21). Upgrading from 0.1.0rc1: a policy whose condition
153
+ NetBox spells differently from Windows was recorded under its old spelling, so until the next push records it
154
+ again, deleting it in NetBox is reported as changed on Windows and not deleted. Push once after upgrading.
155
+ - A push now creates and updates the policies of each level in ascending processing order instead of by name, so
156
+ recreating policies whose names sort the other way no longer fails with DHCP 20110. Policies Windows moves down
157
+ when another takes their number are set back in the same push, and a processing order that would leave a gap is
158
+ reported in the plan instead of failing on Windows (#24). After a policy is deleted in NetBox without renumbering
159
+ the ones after it, the push no longer moves the others into the wrong order: it leaves that level as Windows holds
160
+ it and asks for the renumbering. Policies Windows renumbers by itself (after a delete, for example) are no longer taken for
161
+ policies changed on Windows when NetBox later deletes them: the processing order is no longer part of what the
162
+ push compares to notice hand edits.
163
+
164
+ Found by testing 0.1.0rc2:
165
+ - The Windows server page has an **Import** panel saying whether the latest import is queued, running or finished
166
+ and where it went. With branching it names and links the import branch and its change request and says main has
167
+ not changed; without branching it links the import proposal and does not mention branches. It refreshes itself
168
+ while the job runs, and the sync run page shows the same for its own run. The message after **Import now** also
169
+ says where the import will go (#32).
170
+ - Changing a scope's pool so that one end grows and the other shrinks (for example `.10-.200` to `.11-.210`) no
171
+ longer fails with DHCP 20023, which Windows returns for that change in one call. The push changes the range in
172
+ two steps: it first narrows to the addresses both pools share (or, when they do not overlap, widens over both),
173
+ then sets the final range. If the second step fails, it tries to put the old range back (#30).
174
+ - Updating a hot standby failover relationship no longer fails with "A parameter cannot be found that matches
175
+ parameter name 'ServerRole'": `Set-DhcpServerv4Failover` has no such parameter, so the push no longer sends it.
176
+ Windows cannot change the role (active or standby) in place, so a push that changes it is refused with a message
177
+ saying to recreate the relationship. After switching a relationship to hot standby, the push checks the role
178
+ Windows chose against NetBox. Mode changes no longer wait for a confirmation nobody can answer (#33).
179
+ - The policy lab test allows the lease time option (51) Windows lists next to a policy's own option values (#29).
180
+ - The missing-module unit test no longer fails on a host with the Windows DHCP management tools (RSAT) installed: it
181
+ runs PowerShell with an empty module path (#31).
182
+
183
+ Found by testing 0.1.0rc3:
184
+ - A reservation description or name change no longer drops its option values on Windows (IPv4 and DHCPv6, #42).
185
+ The push only sends the client ID, type, DUID or IAID when they change, and puts back any reservation option value
186
+ Windows removed during the update. The dry run is unchanged: it still lists only the reservation update. If a value
187
+ cannot be put back, the reservation change is reported as failed, naming each lost option and saying whether it
188
+ comes back by itself: the next push recreates a value NetBox holds, but values NetBox does not hold (DHCPv6 vendor
189
+ class values, option codes the plugin does not sync, values added on Windows since the last import) must be put
190
+ back by hand.
191
+ - Without branching, an import that finds only differences a reviewer already dismissed no longer reports "No
192
+ differences found." The Import panel and the sync run now say that nothing new waits for review and how many
193
+ dismissed differences stay ignored while Windows shows the same values. The count of differences waiting for review
194
+ no longer includes dismissed ones, a proposal you may not view is no longer read as "no differences", and the sync
195
+ run summary and job log record how many differences were dismissed earlier (#43). An earlier run whose proposal a
196
+ later import took over (or that was deleted) says so and links the server's open proposal instead of claiming a
197
+ proposal you may not view, and a run recorded before this fix with no proposal linked says only how many
198
+ differences it found.
199
+ - The Windows scopes list shows each scope's prefix in its own column, next to the subnet name, as the
200
+ netbox-plugin-dhcp subnet list does, so scopes with similar or repeated names are told apart without opening them.
201
+ The column links to the prefix and sorts by network (#47).
202
+ - With branching, the Import panel no longer calls a merged or deleted branch "the open import branch", on the
203
+ Windows server page or on the sync run of an earlier import. It says what became of the branch: being merged,
204
+ merged into main (with the time), merged and since deleted, or deleted without being merged, read from the branch
205
+ or from its deletion in the change log. With no record you may view, it says the outcome is not known rather than
206
+ guessing a merge. A merged import no longer reads as "main matches Windows", the deleted branch row links its
207
+ deletion record, and the server panel links the server's import history (#44).
208
+
209
+ Found by testing 0.1.0rc4:
210
+ - Failover replication after a push to the primary no longer fails with `AmbiguousParameterSet`. The plugin passed
211
+ both `-Name` and `-ScopeId` to `Invoke-DhcpServerv4FailoverReplication`, which takes one or the other; it now
212
+ replicates the changed scopes with `-ScopeId` only, never widening the copy to the whole relationship (#51).
213
+ - A failed failover replication is retried by the next push to the primary, even one with nothing else to write, so
214
+ the partner no longer stays behind until the next change. The push's sync run lists the scopes still to replicate.
215
+ A scope that is not yet in the relationship on Windows waits for a later push instead of blocking the others.
216
+
217
+ Found by the full lab run (two Windows Server 2022 servers; earlier notes said 2025, which is what the rc testers
218
+ ran):
219
+ - Over SSH, about one PowerShell run in fifteen hung until the timeout: Windows OpenSSH sometimes loses the end of
220
+ stdin, and the script loader read stdin to its end. It now reads the one line the script is sent as. Each hung
221
+ run also kept its SSH session open, so after a few the server refused new ones (#56). Windows OpenSSH also stalls
222
+ on more than about 70 KB of input: the SSH transport refuses a script above 64 KB at once, saying to use WinRM, and
223
+ a run that stays silent past the command timeout now says so instead of giving an empty error.
224
+ - Failover relationships could not be created over WinRM: `Add-DhcpServerv4Failover` asked for a confirmation nobody
225
+ can answer ("PowerShell is in NonInteractive mode"). Add, Set and replication now send `-Force`. The removes never
226
+ do: they do not ask while the relationship is healthy, and with the partner unreachable `-Force` would remove the
227
+ relationship or scope on one server only. Such a push now fails with "not in NORMAL state" and changes nothing.
228
+ - Failover writes need the DHCP server to reach its partner as you, which NTLM and Kerberos cannot pass on
229
+ (`PermissionDenied`). The new **CredSSP** WinRM authentication makes them work; see the failover page. CredSSP
230
+ hands the password to the server, so it requires HTTPS with certificate verification, unless the credential
231
+ profile sets `allow_insecure_credssp` (for labs).
232
+ - An import or push no longer fails when a scope disappears while the server is being read (for example the partner's
233
+ copy, when a failover relationship is removed at that moment): that scope counts as gone, the rest is read. The
234
+ sync run's notes and the job log name each scope left out this way (#58).
235
+ - A failover relationship imported with message authentication on made every later push to that server fail: the
236
+ import cannot read the secret, so NetBox had no shared secret profile and each push tried to turn authentication
237
+ off, which Windows refuses. Without a profile NetBox now leaves authentication as Windows has it; a profile still
238
+ turns it on with that secret. Found while taking the documentation screenshots.
239
+ - A sync run's page listed every import proposal of every server instead of its own (the filter it used did not
240
+ exist).
241
+ - The Kerberos SPN help text read "Defaults to WSMAN/": the host placeholder was dropped as an HTML tag.
242
+ - A failover partner Windows names by its computer name now matches a server NetBox knows by IP address, and one it
243
+ names by address matches a server NetBox knows by name (#57). Windows names the partner by its computer name on one
244
+ side of a relationship, so that side's import failed and its pushes saw a partner change Windows cannot make. Test
245
+ connection, imports and pushes now record the DHCP server's computer name, DNS name and addresses (**Reported
246
+ names**, migration 0006, cleared when the host or computer name changes), and partners match on them as well as on
247
+ the host. A name two servers report matches neither, and the error says so.
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.5
2
+ Name: netbox-windows-dhcp-plugin
3
+ Version: 0.1.0
4
+ Summary: Sync netbox-plugin-dhcp data with Microsoft Windows DHCP servers over WinRM or SSH.
5
+ Project-URL: Homepage, https://github.com/thomaschristory/netbox-windows-dhcp-plugin
6
+ Project-URL: Documentation, https://thomaschristory.github.io/netbox-windows-dhcp-plugin/
7
+ Project-URL: Repository, https://github.com/thomaschristory/netbox-windows-dhcp-plugin
8
+ Project-URL: Changelog, https://github.com/thomaschristory/netbox-windows-dhcp-plugin/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/thomaschristory/netbox-windows-dhcp-plugin/issues
10
+ Author: Thomas Christory
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE
13
+ Keywords: ddi,dhcp,netbox,netbox-plugin,windows,winrm
14
+ Classifier: Development Status :: 2 - Pre-Alpha
15
+ Classifier: Framework :: Django
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: System :: Networking
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: netbox-plugin-dhcp<0.3,>=0.2
25
+ Requires-Dist: paramiko>=3.5
26
+ Requires-Dist: pypsrp[credssp]>=0.8
27
+ Provides-Extra: branching
28
+ Requires-Dist: netbox-change-control>=0.6; extra == 'branching'
29
+ Requires-Dist: netboxlabs-netbox-branching>=1.2.2; extra == 'branching'
30
+ Provides-Extra: kerberos
31
+ Requires-Dist: pypsrp[kerberos]>=0.8; extra == 'kerberos'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # netbox-windows-dhcp-plugin
35
+
36
+ A NetBox plugin that keeps Microsoft Windows DHCP servers in step with the data modelled by
37
+ [netbox-plugin-dhcp](https://github.com/sys4/netbox-plugin-dhcp), in both directions, over WinRM or SSH.
38
+
39
+ **Documentation: https://thomaschristory.github.io/netbox-windows-dhcp-plugin/**
40
+
41
+ > **Status: 0.1.0, the first release.** Every v1 feature is built and tested against an in-memory fake server and
42
+ > PowerShell stubs, and the lab tests have run in full against two Windows Server 2022 DHCP servers (import, push,
43
+ > leases and failover, over WinRM HTTP and HTTPS and over SSH). Kerberos and SSH key authentication have not been
44
+ > tried on a real server yet (see the
45
+ > [limitations](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/limitations/)). Try it on a lab server
46
+ > first.
47
+
48
+ ## Features
49
+
50
+ - **Import** from Windows, on demand or every `import_interval` minutes. With
51
+ [netbox-branching](https://github.com/netboxlabs/netbox-branching) each import lands in a branch (plus a change
52
+ request with [netbox-change-control](https://github.com/antoinekh/netbox-change-control)); without it, in an import
53
+ proposal whose items you apply or dismiss.
54
+ - **Push** to Windows: a reconcile per server when a branch is merged, or a few seconds after a save without
55
+ branching, plus "Sync now" and "Dry run". A push only deletes Windows objects NetBox manages; objects made by hand
56
+ on Windows are left alone until imported.
57
+ - IPv4 scopes, superscopes, exclusion ranges, reservations, option definitions and values, user and vendor classes,
58
+ vendor class options, policies, failover relationships (with replication to the partner) and MAC filters.
59
+ - DHCPv6 scopes, reservations (DUID and IAID), user classes and option values.
60
+ - A **Leases** tab on the subnet page, read live from Windows in a background job.
61
+ - WinRM (NTLM, Kerberos, Basic, CredSSP for failover; HTTPS by default) or SSH, as in
62
+ [terraform-provider-windowsddi](https://github.com/thomaschristory/terraform-provider-windowsddi). Credentials
63
+ live in named profiles in the plugin configuration, limited to `allowed_hosts`, never in the database.
64
+ - REST API and GraphQL for every model; all Windows I/O in background jobs.
65
+
66
+ ## Compatibility
67
+
68
+ | Plugin | NetBox | netbox-plugin-dhcp | netbox-branching | Python |
69
+ |---|---|---|---|---|
70
+ | 0.1.x | 4.7 | 0.2.x | 1.2.2+ (optional) | 3.12 to 3.14 |
71
+
72
+ Windows Server 2016 or later with the DHCP Server role.
73
+
74
+ ## Quick start
75
+
76
+ ```bash
77
+ pip install netbox-windows-dhcp-plugin
78
+ # extras: [kerberos] for Kerberos (needs system GSSAPI libraries), [branching] for branching and change control
79
+ ```
80
+
81
+ ```python
82
+ PLUGINS = ["netbox_dhcp", "netbox_windows_dhcp_plugin"]
83
+
84
+ PLUGINS_CONFIG = {
85
+ "netbox_windows_dhcp_plugin": {
86
+ "credentials": {
87
+ "dhcp-admin": {
88
+ "username": "CORP\\svc-netbox-dhcp",
89
+ "password_env": "DHCP_ADMIN_PASSWORD",
90
+ "allowed_hosts": ["dhcp*.corp.example"],
91
+ },
92
+ },
93
+ },
94
+ }
95
+ ```
96
+
97
+ Run `python manage.py migrate`, restart NetBox and its worker, then add a Windows server under **Windows DHCP >
98
+ Windows servers**, click **Test connection** and **Import now** (**Import** with netbox-branching). The
99
+ [first sync](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/quickstart/) walkthrough covers the rest.
100
+
101
+ ## Documentation
102
+
103
+ - [Installation](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/installation/) and
104
+ [preparing Windows](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/windows-setup/)
105
+ - [Configuration](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/configuration/) and
106
+ [security](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/security/)
107
+ - [How objects map](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/mapping/),
108
+ [import](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/import/) and
109
+ [push](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/push/)
110
+ - [Permissions](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/permissions/),
111
+ [REST API and GraphQL](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/api/),
112
+ [troubleshooting](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/troubleshooting/)
113
+ - [Design](https://github.com/thomaschristory/netbox-windows-dhcp-plugin/blob/main/docs/DESIGN.md) and
114
+ [changelog](https://github.com/thomaschristory/netbox-windows-dhcp-plugin/blob/main/CHANGELOG.md)
115
+
116
+ The same pages are in the [`docs/`](https://github.com/thomaschristory/netbox-windows-dhcp-plugin/tree/main/docs)
117
+ folder of the repository.
118
+
119
+ ## Development
120
+
121
+ Requires [uv](https://docs.astral.sh/uv/) and Docker.
122
+
123
+ ```bash
124
+ make lint # ruff check and format check
125
+ make test # unit tests, no NetBox needed
126
+ make dev # NetBox, netbox-plugin-dhcp, branching and change control in docker
127
+ make test-netbox # NetBox integration tests inside the dev stack
128
+ make docs # build the documentation site
129
+ make dist # build and check the wheel and sdist
130
+ ```
131
+
132
+ See [Development](https://thomaschristory.github.io/netbox-windows-dhcp-plugin/development/) for the lab tests
133
+ against a real Windows server.
134
+
135
+ ## License
136
+
137
+ Apache-2.0, see [LICENSE](https://github.com/thomaschristory/netbox-windows-dhcp-plugin/blob/main/LICENSE).