Manage NetBox service users declaratively for the netbox engine
ci/woodpecker/pr/plan Pipeline failed
ci/woodpecker/pr/pre-commit Pipeline was successful

Why:
- The netbox secrets engine can only mint tokens for NetBox users that already
  exist, so today those service users must be hand-created before a role works.
  Consul already solves the equivalent problem declaratively, and NetBox should
  be managed the same way so Ben seeds only the engine admin token.

How:
- Add a netbox_user_management module mirroring consul_acl_management: it reads
  each backend's seeded admin token from KV, configures one e-breuninger/netbox
  provider per backend, and creates netbox_user + netbox_permission resources
  from a config-driven map (random unknown passwords, since these users
  authenticate only via Vault-minted tokens).
- Drive it from config/netbox_user/<username>.yaml, scanned in config.hcl and
  wired through terragrunt inputs and the vault_cluster module, reusing the
  sanitized backend-alias pattern the Consul providers use.
- Define the terraform-infra user 1:1 with the engine role, granting write on
  the IPAM/DCIM objects terraform-infra manages (prefixes, ip-addresses,
  ip-ranges, devices, interfaces, mac addresses, and the supporting
  role/tag/type objects).
- Flip the terraform-infra role's netbox_username from svc-terraform-infra to
  terraform-infra so the engine role and NetBox username match exactly.
This commit is contained in:
2026-08-09 12:18:13 +10:00
parent 73a2d7b175
commit bd1bcc2db9
11 changed files with 248 additions and 2 deletions
+25
View File
@@ -445,6 +445,31 @@ variable "netbox_secret_backend_role" {
default = {}
}
variable "netbox_user" {
description = "Map of NetBox service users to create declaratively (keyed by username; 1:1 with the engine role name)"
type = map(object({
backend = string
active = optional(bool, true)
staff = optional(bool, false)
email = optional(string)
permissions = optional(list(object({
name = string
object_types = list(string)
actions = optional(list(string), ["view", "add", "change", "delete"])
constraints = optional(string)
description = optional(string)
enabled = optional(bool, true)
})), [])
}))
default = {}
}
variable "netbox_backend_aliases" {
description = "Map of netbox backend names to sanitized provider aliases"
type = map(string)
default = {}
}
variable "policy_auth_map" {
description = "Map of auth mounts -> auth roles -> policy names"
type = map(map(list(string)))