From 8ccc5f13938ea4a13d62185eabd3c2a8d7efb15e Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Tue, 11 Aug 2026 20:43:04 +1000 Subject: [PATCH] Add the netbox backend and terraform-infra role (#117) ## 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. --------- Co-authored-by: BenVincent Reviewed-on: https://git.unkin.net/unkin/terraform-vault/pulls/117 Co-authored-by: Ben Vincent Co-committed-by: Ben Vincent --- config/netbox_secret_backend/netbox.yaml | 16 ++++++++++++ .../netbox/terraform-infra.yaml | 25 +++++++++++++++++++ policies/netbox/creds/terraform-infra.yaml | 21 ++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 config/netbox_secret_backend/netbox.yaml create mode 100644 config/netbox_secret_backend_role/netbox/terraform-infra.yaml create mode 100644 policies/netbox/creds/terraform-infra.yaml diff --git a/config/netbox_secret_backend/netbox.yaml b/config/netbox_secret_backend/netbox.yaml new file mode 100644 index 0000000..4e22f42 --- /dev/null +++ b/config/netbox_secret_backend/netbox.yaml @@ -0,0 +1,16 @@ +# Mounts the netbox token secrets engine at "netbox" and writes its config. +# The seeded NetBox admin token is sensitive and read from KV, not stored here: +# kv/service/vault/au/syd1/secret_backend/netbox/config +# -> key: admin_token (required) +# Populate that KV path with a purpose-built NetBox service token that has +# add_token + grant_token (or superuser) BEFORE applying, then run +# `vault write -f netbox/config/rotate` after the first apply so only Vault +# holds the live admin token. +# +# token_version 2 is the NetBox 4.6.5 default and requires API_TOKEN_PEPPERS to +# be configured on the NetBox server; set token_version: 1 here if the server +# has no peppers. +description: "NetBox ephemeral scoped API token engine" +netbox_url: "https://netbox.k8s.syd1.au.unkin.net" +token_version: 2 +request_timeout_seconds: 30 diff --git a/config/netbox_secret_backend_role/netbox/terraform-infra.yaml b/config/netbox_secret_backend_role/netbox/terraform-infra.yaml new file mode 100644 index 0000000..ac390ac --- /dev/null +++ b/config/netbox_secret_backend_role/netbox/terraform-infra.yaml @@ -0,0 +1,25 @@ +# Single declarative source for the terraform-infra NetBox service identity. The +# filename stem is the engine role name AND the NetBox username (1:1); config.hcl +# derives both from it, so neither is repeated below. Creating this file creates +# the user: the netbox_user_management module synthesizes the NetBox user + object +# permissions from the permissions block, and the engine role mints ephemeral +# tokens for that same user. write_enabled true because terraform-infra manages +# NetBox IPAM/DCIM; very short TTLs because a token is minted per plan/apply and +# revoked when the run's lease ends. +--- +write_enabled: true +ttl: 120 # 2m +max_ttl: 300 # 5m +permissions: + - object_types: + - ipam.prefix + - ipam.ipaddress + - ipam.iprange + - dcim.device + - dcim.interface + - dcim.macaddress + actions: + - view + - add + - change + - delete diff --git a/policies/netbox/creds/terraform-infra.yaml b/policies/netbox/creds/terraform-infra.yaml new file mode 100644 index 0000000..d7ff814 --- /dev/null +++ b/policies/netbox/creds/terraform-infra.yaml @@ -0,0 +1,21 @@ +# Allow the terraform-infra runner to mint an ephemeral NetBox token from the +# terraform-infra role (netbox/creds/terraform-infra), replacing the static +# netbox_token it used to read from kv/service/terraform/*. The e-breuninger +# netbox provider authenticates with the minted token; the lease revokes it when +# the run ends. +# +# Bound to both the terraform-infra AppRole and its Woodpecker k8s auth role, +# mirroring the terraform-ipam pattern. Both principals are created by the +# terraform-infra Vault onboarding (separate from this netbox change); until +# that onboarding lands this policy exists but attaches to nothing. +--- +rules: + - path: "netbox/creds/terraform-infra" + capabilities: + - read + +auth: + approle: + - terraform_infra + k8s/au/syd1: + - woodpecker_terraform_infra