Skip to content

v1.3.0

Choose a tag to compare

@krasotinpa krasotinpa released this 19 Aug 08:50
· 20 commits to main since this release
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