Add the netbox backend and terraform-infra role #117

Merged
benvin merged 4 commits from benvin/netbox-user-management into master 2026-08-11 20:43:05 +10:00
Owner

Why

  • The netbox engine modules stand ready but mount nothing and create no identity until backend and role data exist, so terraform-infra still reads a static NetBox token instead of minting ephemeral scoped tokens.

How

  • Add config/netbox_secret_backend/netbox.yaml to mount the engine at netbox and point it at the syd1 NetBox URL; the admin token is read from KV, not stored here.
  • Add config/netbox_secret_backend_role/netbox/terraform-infra.yaml as the single declarative source for the terraform-infra identity: filename-derived role name and NetBox username, write access, short TTLs, and an inline permissions block. Nothing in the file repeats the filename.
  • Scope terraform-infra to view/add/change/delete on the IPAM/DCIM objects it manages: prefixes, ip-addresses, ip-ranges, devices, interfaces, mac addresses.
  • Add policies/netbox/creds/terraform-infra.yaml letting the terraform-infra AppRole and its Woodpecker k8s role read netbox/creds/terraform-infra; it attaches to nothing until the separate terraform-infra Vault onboarding lands.

Dependency order

  • Stacked on the modules PR (#115), which stacks on the plugin registration PR. Merge order: plugin -> #115 -> this.

CI note

  • The plan step is red only on the external admin_token KV seed at kv/data/service/vault/au/syd1/secret_backend/netbox/config (a NetBox token with add_token + grant_token / superuser). Seeding that path is an environmental prerequisite, not a code defect; everything else validates.
## Why - The netbox engine modules stand ready but mount nothing and create no identity until backend and role data exist, so terraform-infra still reads a static NetBox token instead of minting ephemeral scoped tokens. ## How - Add `config/netbox_secret_backend/netbox.yaml` to mount the engine at `netbox` and point it at the syd1 NetBox URL; the admin token is read from KV, not stored here. - Add `config/netbox_secret_backend_role/netbox/terraform-infra.yaml` as the single declarative source for the terraform-infra identity: filename-derived role name and NetBox username, write access, short TTLs, and an inline permissions block. Nothing in the file repeats the filename. - Scope terraform-infra to view/add/change/delete on the IPAM/DCIM objects it manages: prefixes, ip-addresses, ip-ranges, devices, interfaces, mac addresses. - Add `policies/netbox/creds/terraform-infra.yaml` letting the terraform-infra AppRole and its Woodpecker k8s role read `netbox/creds/terraform-infra`; it attaches to nothing until the separate terraform-infra Vault onboarding lands. ## Dependency order - Stacked on the modules PR (#115), which stacks on the plugin registration PR. Merge order: plugin -> #115 -> this. ## CI note - The plan step is red only on the external admin_token KV seed at `kv/data/service/vault/au/syd1/secret_backend/netbox/config` (a NetBox token with add_token + grant_token / superuser). Seeding that path is an environmental prerequisite, not a code defect; everything else validates.
Author
Owner

CI status: pre-commit green (tofu fmt/validate, tflint, terragrunt hcl fmt, yamllint). plan red with:

Error: no secret found at "kv/data/service/vault/au/syd1/secret_backend/netbox/config"
  with module.netbox_user_management.data.vault_kv_secret_v2.netbox_backend_configs["netbox"]

This is the seeded NetBox admin token being absent from KV at plan time, not a code defect:

  • It reads the exact path #115's engine data source reads (.../secret_backend/netbox/config, key admin_token).
  • #115's plan (pipeline 147, 01:30Z) read that path fine and planned netbox_secret_backend.this; this PR's plan (pipeline 150, 02:19Z) hit "no secret found" for the same path, so the seed was present earlier and is not present now.
  • An isolated tofu plan of the module is green, and the e-breuninger/netbox provider is lazy (no NetBox call at plan with skip_version_check = true).

Unblock: seed kv/service/vault/au/syd1/secret_backend/netbox/config with key admin_token (a NetBox token carrying add_token + grant_token / superuser) before this plans/applies - the same seed #115 needs to apply. Rotation caveat: after vault write -f netbox/config/rotate the live engine token diverges from the KV seed, so keep a valid management token at that KV path for this module's provider to keep managing users.

CI status: `pre-commit` green (tofu fmt/validate, tflint, terragrunt hcl fmt, yamllint). `plan` red with: ``` Error: no secret found at "kv/data/service/vault/au/syd1/secret_backend/netbox/config" with module.netbox_user_management.data.vault_kv_secret_v2.netbox_backend_configs["netbox"] ``` This is the seeded NetBox admin token being absent from KV at plan time, not a code defect: - It reads the exact path #115's engine data source reads (`.../secret_backend/netbox/config`, key `admin_token`). - #115's plan (pipeline 147, 01:30Z) read that path fine and planned `netbox_secret_backend.this`; this PR's plan (pipeline 150, 02:19Z) hit "no secret found" for the same path, so the seed was present earlier and is not present now. - An isolated `tofu plan` of the module is green, and the `e-breuninger/netbox` provider is lazy (no NetBox call at plan with `skip_version_check = true`). Unblock: seed `kv/service/vault/au/syd1/secret_backend/netbox/config` with key `admin_token` (a NetBox token carrying add_token + grant_token / superuser) before this plans/applies - the same seed #115 needs to apply. Rotation caveat: after `vault write -f netbox/config/rotate` the live engine token diverges from the KV seed, so keep a valid management token at that KV path for this module's provider to keep managing users.
Author
Owner

Refactored to infer the NetBox user from the engine role config: config/netbox_secret_backend_role/netbox/.yaml is now the single source per identity (filename = engine role name = NetBox username; body = write_enabled/ttl/max_ttl + inline permissions). config.hcl derives netbox_username from the filename, the netbox_username field is dropped from the yaml, and config/netbox_user is deleted. Both the engine-role module and netbox_user_management consume the same map keyed by config path.

CI on 702dc6c: pre-commit green (tofu fmt/validate, tflint, terragrunt hcl fmt, yamllint). plan red with the same pre-existing environmental blocker as before - no secret found at kv/data/service/vault/au/syd1/secret_backend/netbox/config. This refactor does not touch that data source (it reads the same admin_token path the engine reads), so the failure is the unseeded KV admin token at plan time, not a code defect. Seed that KV path (NetBox token with add_token + grant_token / superuser) - the same seed #115 needs - to turn plan green.

Refactored to infer the NetBox user from the engine role config: config/netbox_secret_backend_role/netbox/<name>.yaml is now the single source per identity (filename = engine role name = NetBox username; body = write_enabled/ttl/max_ttl + inline permissions). config.hcl derives netbox_username from the filename, the netbox_username field is dropped from the yaml, and config/netbox_user is deleted. Both the engine-role module and netbox_user_management consume the same map keyed by config path. CI on 702dc6c: pre-commit green (tofu fmt/validate, tflint, terragrunt hcl fmt, yamllint). plan red with the same pre-existing environmental blocker as before - `no secret found at kv/data/service/vault/au/syd1/secret_backend/netbox/config`. This refactor does not touch that data source (it reads the same admin_token path the engine reads), so the failure is the unseeded KV admin token at plan time, not a code defect. Seed that KV path (NetBox token with add_token + grant_token / superuser) - the same seed #115 needs - to turn plan green.
unkinben changed title from Manage NetBox service users declaratively for the netbox engine to Add the netbox backend and terraform-infra role 2026-08-09 13:14:14 +10:00
benvin changed target branch from benvin/netbox-secrets-engine to master 2026-08-09 16:36:37 +10:00
benvin added 3 commits 2026-08-09 16:36:37 +10:00
Register the netbox secrets plugin in the catalog
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
f1b6751257
Why:
- The netbox secrets engine cannot be mounted until its plugin binary is
  registered in the OpenBao catalog, so the catalog entry must land before any
  engine mount or role config references it.

How:
- Add config/plugins/vault-plugin-secrets-netbox.yaml registering the plugin as
  a secret plugin, pinned to the released v0.1.0 binary sha256 that Puppet
  installs on the OpenBao nodes. Bump the sha in lockstep with any RPM upgrade.
Add the netbox secrets engine modules and wiring
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
e2cd80e222
Why:
- Managing NetBox from Vault needs three capabilities the repo does not yet
  have: mounting the netbox engine, minting scoped tokens through roles, and
  creating the NetBox service users those roles mint tokens for. Landing the
  modules and config scaffolding before any backend or role data lets each
  concrete identity be added as pure data later.

How:
- Add three modules under modules/vault_cluster/modules: netbox_secret_backend
  (mount + engine config, admin token read from KV), netbox_secret_backend_role
  (mint ephemeral scoped tokens for a filename-derived NetBox username), and
  netbox_user_management (mirror consul_acl_management: read the seeded admin
  token, drive one e-breuninger/netbox provider per backend, and synthesize the
  NetBox user + object permissions from the role map's inline permissions).
- Derive the netbox_secret_backend and netbox_secret_backend_role maps in
  config.hcl, deriving each role's name and netbox_username from its filename so
  the engine role and NetBox username match by construction.
- Wire the three module blocks and their variables through vault_cluster and the
  syd1 terragrunt inputs, reusing the sanitized backend-alias pattern the Consul
  providers use.
- Leave the backend and role maps empty: the modules stand ready and create
  nothing until backend and role config data are added.
Add the netbox backend and terraform-infra role
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful
df3e8b017c
Why:
- The netbox engine modules stand ready but mount nothing and create no
  identity until backend and role data exist, so terraform-infra still reads a
  static NetBox token instead of minting ephemeral scoped tokens.

How:
- Add config/netbox_secret_backend/netbox.yaml to mount the engine at netbox and
  point it at the syd1 NetBox URL; the admin token is read from KV, not stored
  here.
- Add config/netbox_secret_backend_role/netbox/terraform-infra.yaml as the
  single declarative source for the terraform-infra identity: filename-derived
  role name and NetBox username, write access, short TTLs, and an inline
  permissions block. Nothing in the file repeats the filename.
- Scope terraform-infra to view/add/change/delete on the IPAM/DCIM objects it
  manages: prefixes, ip-addresses, ip-ranges, devices, interfaces, mac
  addresses.
- Add policies/netbox/creds/terraform-infra.yaml letting the terraform-infra
  AppRole and its Woodpecker k8s role read netbox/creds/terraform-infra; it
  attaches to nothing until the separate terraform-infra Vault onboarding lands.
benvin added 1 commit 2026-08-09 19:06:29 +10:00
Merge branch 'master' into benvin/netbox-user-management
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
22e68fef20
benvin merged commit 8ccc5f1393 into master 2026-08-11 20:43:05 +10:00
benvin deleted branch benvin/netbox-user-management 2026-08-11 20:43:05 +10:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/terraform-vault#117