Skip to content

Releases: krasotinpa/netbox-passwork-plugin

v1.7.2

Choose a tag to compare

@krasotinpa krasotinpa released this 07 Oct 13:16
v1.7.2
1e20c29

Removed

  • Two empty, unused files: static/netbox_passwork/styles.css (never loaded by any page) and templates/netbox_passwork/secret_detail.html (the secrets/<id>/detail/ endpoint returns JSON and renders no template). No behaviour change

v1.7.1

Choose a tag to compare

@krasotinpa krasotinpa released this 07 Oct 11:38
v1.7.1
20053bf

Changed

  • License hygiene per Apache Software Foundation guidance (license type unchanged, still Apache-2.0): new NOTICE file shipped in the sdist and wheel alongside LICENSE; LICENSE restored to the canonical Apache License 2.0 text; SPDX-License-Identifier: Apache-2.0 headers in the project's source files; a "License of contributions" section in CONTRIBUTING.md; a trademark disclaimer for NetBox and Passwork in the README

v1.7.0

Choose a tag to compare

@krasotinpa krasotinpa released this 30 Sep 10:31
v1.7.0
79abbc8

Added

  • Support for NetBox 4.7: the full test suite passes on NetBox 4.7.2 (Django 6.1) with no code changes, and the Passwork tabs on Device, Virtual Machine and Service were checked in a browser. CI now tests NetBox 4.5.10, 4.6.10 and 4.7.2 on Python 3.12 / 3.14
  • README: NetBox 4.7 needs PostgreSQL 15+; the compatibility table now covers 1.3–1.6 and 1.7

v1.6.0

Choose a tag to compare

@krasotinpa krasotinpa released this 23 Aug 18:25
v1.6.0
e355bcb

Changed

  • Breaking / security (#1): every object-scoped operation (secrets list, secret detail, reveal, copy, binding create, binding delete) now also requires view access to the bound NetBox object (dcim.view_device / virtualization.view_virtualmachine / ipam.view_service), evaluated against the user's ObjectPermission constraints (ADR-0002). Users relying on plugin permissions alone, without a view permission on the object type, lose access to those secrets — grant the object view permission (constrained or not) alongside the plugin permissions. An object outside the user's constraints now answers 404 object_not_found (matching NetBox core behaviour; binding_not_found on binding deletion), checked before the binding lookup so binding existence is not disclosed. Bindings whose object was deleted are unreadable but remain deletable with delete_binding alone
  • POST bindings/ now validates the target: a non-integer object_id returns 400 invalid_object_id, and a missing (or hidden) object returns 404 object_not_found instead of creating a dangling binding

Fixed

  • Secret custom fields (and the Password row of the detail card) now re-mask automatically after SECRET_REVEAL_TIMEOUT, the same way the main password does — previously a revealed value stayed on screen until the eye icon was clicked again (#30). Hiding a field no longer sends an extra reveal request, so it no longer writes a spurious audit entry

v1.5.0

Choose a tag to compare

@krasotinpa krasotinpa released this 23 Aug 13:55
v1.5.0
e2cf17e

Changed

  • The Bind Passwork secret modal is now an Explorer-style browser (spec #26): a folder tree on the left (vaults are roots; a vault's folders load as one flat list per vault), the selected node's direct children on the right as a Name/Login table with clickable breadcrumbs, and a single click on a folder in the right pane opening it with the tree kept in sync. A vault node now shows only its top-level folders and root passwords instead of every password in the vault
  • Picker search: starts from 3 characters as you type (debounced, stale responses are discarded), results are a flat table with each secret's path, clicking a result jumps to its folder with the tree expanded ("show in folder"), clearing the box returns to the folder you were in, and a "This vault only" checkbox scopes the search to the selected vault (new vault_id parameter of GET picker/search/; the Passwork request now uses the documented POST search variant)
  • Picker errors: a vault that answers 403 stays in the tree marked "no access" while other vaults keep working, and a Passwork timeout shows a retryable message naming the PASSWORK_REQUEST_TIMEOUT setting

Added

  • GET picker/folders/<vault_id>/folders/ — the vault's flat folder list backing the picker tree (gateway operation list_vault_folders())

v1.4.0

Choose a tag to compare

@krasotinpa krasotinpa released this 21 Aug 19:00
v1.4.0
cc1bcb7

Added

  • CI runs the Python test suite against a real NetBox (PostgreSQL + Redis service containers, matrix of NetBox 4.5/4.6 × Python 3.12/3.14), plus makemigrations --check and manage.py check
  • testing/configuration.py — a ready-made NetBox configuration for running the test suite, used by CI and usable locally
  • README: a compatibility matrix (plugin ↔ NetBox ↔ Python), the runtime dependency list, a Support section (where to report bugs, how to report a vulnerability privately) and a plugin icon (docs/img/icon.svg, CC BY 4.0)
  • README: a Screenshots section walking through the plugin — the Passwork tab, the secret picker asking for a login, the login and two-factor modals, and the secrets of a bound object

Changed

  • Breaking: requires-python is now >=3.12, matching NetBox 4.5+, which does not run on Python 3.11

Fixed

  • README: the minimum PostgreSQL version is 14, as required by NetBox 4.5 (13 was stated)
  • Secrets tab: with no active Passwork session the header button now reads "Authenticate" and opens the login modal directly, instead of "Bind secret" leading into a picker that can only fail with 401; after a successful login (including TOTP) it switches back to "Bind secret"
  • Picker: clicking a vault in the Bind Passwork secret modal now shows its contents in the right pane — subfolders (with drill-down) and passwords — instead of sending the folder ID to the text search and always showing "No secrets found" (new endpoint GET picker/folders/<vault_id>/items/, backed by Passwork's /api/v1/folders and /api/v1/items listing endpoints)

v1.3.1

Choose a tag to compare

@krasotinpa krasotinpa released this 19 Aug 10:11
v1.3.1
46dabac

Fixed

  • The wheel no longer ships netbox_passwork/tests (it was pulled in as package data despite the packages.find exclusion, which also produced a setuptools warning during the build)

v1.3.0

Choose a tag to compare

@krasotinpa krasotinpa released this 19 Aug 08:50
v1.3.0
7fa4528

Changed

  • All plugin API errors now share one body format {"code", "detail"} — the remaining endpoints (GET secrets/, POST bindings/, DELETE bindings/<id>/, GET audit/) and the NetBox permission checks (not_authenticated / netbox_permission_denied) were aligned with the Passwork-facing ones: detail is always present, the extra param field of invalid_param (audit filters/pagination) is folded into detail, status: "error" is gone. Values of code, routes and successful bodies are unchanged
  • Passwork-facing endpoints (login/TOTP/detail/copy/picker) answer 405 Method Not Allowed for an unsupported HTTP method before touching the Passwork session (previously 401 without a session), and OPTIONS no longer requires a Passwork session
  • Picker endpoints (GET picker/folders/, GET picker/search/) now go through the Passwork gateway like the other Passwork-facing views: a Passwork 401 in the picker returns HTTP 401 pw_session_expired and a Passwork 403 returns HTTP 403 pw_access_denied instead of HTTP 200 with an empty list; error bodies are uniform {"code", "detail"} (missing_query gained a detail), successful bodies (arrays of vaults / items) are unchanged
  • Secret detail (GET secrets/<pw_id>/detail/) and copy (POST secrets/<pw_id>/copy/) endpoints now go through the Passwork gateway (like login/TOTP): the order of checks is unchanged (NetBox permission → reveal_secret for reveal=true → Passwork session → parameters → binding → Passwork → audit), error bodies are uniform {"code", "detail"} (invalid_object_id and binding_not_found gained a detail), successful bodies are unchanged
  • Package metadata (pyproject.toml): author, PEP 639 license expression, project URLs; tests are no longer shipped in the wheel
  • First public release. The project is now open source under Apache-2.0; the documentation in docs/, the code comments and the helper scripts are in English

Added

  • LICENSE (Apache-2.0) and a License section in README
  • Published on PyPI: pip install netbox-passwork; update.sh now upgrades from PyPI by default
  • GitHub Actions CI (.github/workflows/ci.yml): ruff, the JS tests and a package build/twine check on every push to main and every pull request (the Python tests still run locally — they need a NetBox installation)
  • Issue and pull request templates (.github/ISSUE_TEMPLATE/, .github/PULL_REQUEST_TEMPLATE.md) and CI/license badges in the README
  • scripts/test.sh — single entry point for lint / Python tests / JS tests with a markdown summary for PRs; scripts/release.sh — release preparation (release PR) and publishing (signed tag, sdist/wheel, GitHub Release)

Fixed

  • Changing SESSION_ENCRYPT_KEY no longer leaves users with a permanent 401: a Passwork session record that cannot be decrypted is dropped (with a warning in the log) and the user is asked to log in to Passwork again (401 pw_not_authenticated); unexpected exceptions while reading the Passwork session are no longer masked as 401
  • A 403 from Passwork on token refresh (/sessions/refresh) is treated like 401 — the Passwork session is dropped and the client gets 401 pw_session_expired — instead of being silently accepted as a successful refresh

Removed

  • Unused passwork-python dependency (the plugin uses its own requests-based client; requests is now declared explicitly) and the stale requirements.txt — dev dependencies live only in [project.optional-dependencies].dev
  • Internal modules/helpers superseded by the Passwork gateway: netbox_passwork/middleware.py (PassworkSessionMiddleware mixin), the Fernet helpers in utils.py (fernet_encrypt/fernet_decrypt), and PassworkAuthClient.encrypt_session/decrypt_session together with its session_encrypt_key constructor argument. No configuration change is required (MIDDLEWARE was never touched); existing Passwork sessions stay valid after the upgrade — the session record format is unchanged

Internal

  • Passwork gateway (netbox_passwork/gateway.py, see ADR-0001): one deep module owns the Passwork session (reading/decrypting/refreshing/encrypting/writing it in the Django session, the only place that reads the plugin config and the only Fernet implementation) and exposes six operations (login, confirm_totp, get_item, list_vaults, search_items, require_session); Passwork refusals are raised as PassworkError subclasses carrying code/http_status/detail. All Passwork-facing views inherit one base PassworkView (NetBox permission → 405 → gateway → Passwork session → method → PassworkError/ApiError → JSON error). The HTTP client (passwork_client.py) no longer depends on Django (everything via the constructor) and gained public list_vaults/search_items; urllib3.disable_warnings() is called only when SSL verification is off. Within one request the Passwork session record is read and decrypted once. This also removed the duplicated Fernet implementation, the repeated local import json calls and the unconditional urllib3.disable_warnings() at import time
  • Tests: the gateway is swapped in views through one explicit seam (as_view(gateway_factory=...), FakeGateway in conftest.py); no unittest.mock left in the plugin tests (only responses for HTTP); new end-to-end release scenario on the real gateway (login → TOTP → list → reveal → copy → picker → binding) and a compatibility test for session records written by ≤ 1.2.x