From df0510e33ba3618678a32a0b143e63db2ed8b83e Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Wed, 19 Aug 2026 21:50:55 +1000 Subject: [PATCH 1/3] vault: register vault-plugin-secrets-arrstack in the catalog (1/3) (#125) ## Why Splits the arrstack Vault engine work (was #124) into three independently-appliable PRs so registration, policy, and engine resources are never bundled. This is **PR 1 of 3 (register)**. ## Change - Registers the `vault-plugin-secrets-arrstack` plugin (v0.1.0) in the OpenBao plugin catalog via `config/plugins/vault-plugin-secrets-arrstack.yaml`. - `sha256` pins the released v0.1.0 binary. - No wiring changes needed: the `plugins` glob and `module.plugin` already exist on `master`. ## Apply order Apply this **after** the Puppet plugin-install PR (unkin/puppet-prod #521, merged) has placed the binary at `/opt/openbao-plugins/vault-plugin-secrets-arrstack` on the OpenBao nodes. Registration fails until the binary is present on-node. ## Stack 1. **register (this PR)** -> `benvin/arrstack-register` off `master` 2. policy -> `benvin/arrstack-policy` 3. resources -> `benvin/arrstack-resources` Supersedes #124. Reviewed-on: https://git.unkin.net/unkin/terraform-vault/pulls/125 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- config/plugins/vault-plugin-secrets-arrstack.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 config/plugins/vault-plugin-secrets-arrstack.yaml diff --git a/config/plugins/vault-plugin-secrets-arrstack.yaml b/config/plugins/vault-plugin-secrets-arrstack.yaml new file mode 100644 index 0000000..fc92851 --- /dev/null +++ b/config/plugins/vault-plugin-secrets-arrstack.yaml @@ -0,0 +1,13 @@ +# config/plugins/vault-plugin-secrets-arrstack.yaml +# Imports (registers) the arrstack secrets plugin in the catalog. Filename = +# catalog name = mount type. The binary is installed on the OpenBao nodes by +# Puppet (openbao-plugin-secrets-arrstack RPM -> +# /opt/openbao-plugins/vault-plugin-secrets-arrstack). +# +# sha256 pins the released v0.1.0 binary; bump it in lockstep with any RPM +# upgrade or OpenBao will refuse to launch the plugin. Registration only +# succeeds once the Puppet PR has installed the binary on the nodes. +type: secret +command: vault-plugin-secrets-arrstack +version: "0.1.0" +sha256: "f8ee60ca7ba14819976acb7dc4cfb6799e3e8da8f871d0bb2bd18d1d9e537972" From 2525bae1d76a7e7e5ca8698d4e9ec1033b31c826 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Wed, 19 Aug 2026 22:51:55 +1000 Subject: [PATCH 2/3] Temporarily remove ghp secret backend + roles (unblock apply) (#129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why The `terraform-vault` master apply aborts with: ``` Error: no secret found at "kv/data/service/vault/au/syd1/secret_backend/ghp/config" from module.ghp_secret_backend["ghp"].data.vault_kv_secret_v2.config ``` The ghp secret backend reads its admin token from a KV path that has not been seeded yet, so the apply fails and blocks every other change — including the arrstack plugin registration (#125). This PR **removes only the ghp backend + role config YAMLs (empties the `for_each` map)**. With no config YAMLs, `var.ghp_secret_backend` / `var.ghp_secret_backend_role` are empty maps, so zero ghp backend/role instances are created, the unseeded `ghp/config` KV is never read, and the apply passes. The ghp module wiring, plugin registration, and policies all stay in place. This is part 1 of a remove -> grant write policy -> seed KV -> re-add sequence, and the YAMLs will be restored once the ghp config KV is seeded. ## Changes - Delete `config/ghp_secret_backend/ghp.yaml`. - Delete `config/ghp_secret_backend_role/ghp/agent.yaml`. Net diff vs `master` is exactly those two file deletions. All ghp wiring is unchanged (identical to master): the `module.ghp_secret_backend` / `module.ghp_secret_backend_role` instantiations, their variables, the `config.hcl` parsing blocks, the `terragrunt.hcl` inputs, the `vault-plugin-secrets-ghp` plugin registration, and the `ghp/admin` + `ghp/creds/agent` policies all remain. Reviewed-on: https://git.unkin.net/unkin/terraform-vault/pulls/129 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- config/ghp_secret_backend/ghp.yaml | 15 --------------- config/ghp_secret_backend_role/ghp/agent.yaml | 15 --------------- 2 files changed, 30 deletions(-) delete mode 100644 config/ghp_secret_backend/ghp.yaml delete mode 100644 config/ghp_secret_backend_role/ghp/agent.yaml diff --git a/config/ghp_secret_backend/ghp.yaml b/config/ghp_secret_backend/ghp.yaml deleted file mode 100644 index ecff20b..0000000 --- a/config/ghp_secret_backend/ghp.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Mounts the ghp token secrets engine at "ghp" and writes its config. -# The seeded ghp service token is sensitive and read from KV, not stored here: -# kv/service/vault/au/syd1/secret_backend/ghp/config -# -> key: admin_token (required) the shared ghpsvc_... service token -# -# admin_token is a static shared secret provisioned into KV by an operator. The -# SAME token value must also be present in the running ghp deployment's accepted -# service tokens (GHP_AUTH_SERVICE_TOKENS) so ghp ACCEPTS what this engine -# PRESENTS. ghp has no rotate endpoint, so the engine never rotates it in place; -# the mount uses ignore_changes=[admin_token], making the KV seed create-only -# (re-reading a stale KV value never re-pushes it to a live mount). -description: "ghp ephemeral scoped agent token engine" -base_url: "https://ghp.unkin.net" -tls_skip_verify: false -request_timeout_seconds: 30 diff --git a/config/ghp_secret_backend_role/ghp/agent.yaml b/config/ghp_secret_backend_role/ghp/agent.yaml deleted file mode 100644 index b5653c7..0000000 --- a/config/ghp_secret_backend_role/ghp/agent.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Role minting ephemeral, scoped ghp agent tokens. Reading ghp/creds/agent mints -# a lease-bound token deleted from ghp on revoke/expiry. token_type "agent" binds -# the minted token to a ghp App installation, so installation_id is REQUIRED. -# -# installation_id below is a PLACEHOLDER (0) and MUST be set to the real ghp App -# installation id before this role can mint usable tokens. scopes are ghp -# permission:level pairs; contents:read is the least-privilege default. ---- -token_type: agent -installation_id: 0 # PLACEHOLDER - set to the real ghp App installation id -scopes: - - contents:read -session_prefix: vault -ttl: 3600 # 1h -max_ttl: 86400 # 24h From 31a7abec999ceb4ae46a5d4999d98143dd4ead9e Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Wed, 19 Aug 2026 22:54:13 +1000 Subject: [PATCH 3/3] vault: add arrstack policies (deployer + KV read + creds) (2/3) (#126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Why Grants the Vault access the arrstack engine needs, before any engine resources exist. **PR 2 of 3 (policy)**, stacked on #125 (register). Keeping policy separate from resources honours the never-bundle / sequential-apply rule. ## Change - Adds `policies/arrstack/admin.yaml`: the terraform-vault deployer (`tf_vault` approle + `woodpecker_terraform_vault` k8s role) may create/read/update/delete `arrstack/config` and manage `arrstack/roles/*`. - Adds `policies/kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token/read.yaml`: the deployer may read the KV-seeded arrproxy admin token (both `kv/data/...` and `kv/metadata/...`) that the engine config sources. The existing `secret_backends_read` policy does not cover this `kubernetes/namespace` KV path. - Adds `policies/arrstack/creds/{sonarr,radarr,prowlarr}.yaml`: each `terraform-` run may read its own `arrstack/creds/` to mint a scoped key. - Policy YAMLs are auto-discovered by `policies/policies.hcl`, so no wiring changes are needed. ## Apply order Apply **after PR #125 (register)**. Safe to apply before the engine exists — these only grant capabilities on paths. ## Stack 1. register -> #125 2. **policy (this PR)** -> `benvin/arrstack-policy` off `benvin/arrstack-register` 3. resources -> `benvin/arrstack-resources` Supersedes #124. Reviewed-on: https://git.unkin.net/unkin/terraform-vault/pulls/126 Co-authored-by: unkin-agent Co-committed-by: unkin-agent --- policies/arrstack/admin.yaml | 27 +++++++++++++++++++ policies/arrstack/creds/prowlarr.yaml | 12 +++++++++ policies/arrstack/creds/radarr.yaml | 12 +++++++++ policies/arrstack/creds/sonarr.yaml | 12 +++++++++ .../default/arrproxy-admin-token/read.yaml | 22 +++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 policies/arrstack/admin.yaml create mode 100644 policies/arrstack/creds/prowlarr.yaml create mode 100644 policies/arrstack/creds/radarr.yaml create mode 100644 policies/arrstack/creds/sonarr.yaml create mode 100644 policies/kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token/read.yaml diff --git a/policies/arrstack/admin.yaml b/policies/arrstack/admin.yaml new file mode 100644 index 0000000..96b86d8 --- /dev/null +++ b/policies/arrstack/admin.yaml @@ -0,0 +1,27 @@ +# Allow management of the arrstack secrets engine (config and roles) by the +# terraform-vault deployer. +--- +rules: + - path: "arrstack/config" + capabilities: + - create + - update + - read + - delete + - path: "arrstack/roles/*" + capabilities: + - create + - update + - delete + - read + - list + - path: "arrstack/roles" + capabilities: + - read + - list + +auth: + approle: + - tf_vault + k8s/au/syd1: + - woodpecker_terraform_vault diff --git a/policies/arrstack/creds/prowlarr.yaml b/policies/arrstack/creds/prowlarr.yaml new file mode 100644 index 0000000..5922685 --- /dev/null +++ b/policies/arrstack/creds/prowlarr.yaml @@ -0,0 +1,12 @@ +# Allow the terraform-prowlarr run to mint a Prowlarr-scoped arrproxy key. +--- +rules: + - path: "arrstack/creds/prowlarr" + capabilities: + - read + +auth: + approle: + - terraform_prowlarr + k8s/au/syd1: + - woodpecker_terraform_prowlarr diff --git a/policies/arrstack/creds/radarr.yaml b/policies/arrstack/creds/radarr.yaml new file mode 100644 index 0000000..7b79acf --- /dev/null +++ b/policies/arrstack/creds/radarr.yaml @@ -0,0 +1,12 @@ +# Allow the terraform-radarr run to mint a Radarr-scoped arrproxy key. +--- +rules: + - path: "arrstack/creds/radarr" + capabilities: + - read + +auth: + approle: + - terraform_radarr + k8s/au/syd1: + - woodpecker_terraform_radarr diff --git a/policies/arrstack/creds/sonarr.yaml b/policies/arrstack/creds/sonarr.yaml new file mode 100644 index 0000000..5e5ae54 --- /dev/null +++ b/policies/arrstack/creds/sonarr.yaml @@ -0,0 +1,12 @@ +# Allow the terraform-sonarr run to mint a Sonarr-scoped arrproxy key. +--- +rules: + - path: "arrstack/creds/sonarr" + capabilities: + - read + +auth: + approle: + - terraform_sonarr + k8s/au/syd1: + - woodpecker_terraform_sonarr diff --git a/policies/kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token/read.yaml b/policies/kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token/read.yaml new file mode 100644 index 0000000..66d1547 --- /dev/null +++ b/policies/kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token/read.yaml @@ -0,0 +1,22 @@ +# Allow the terraform-vault deployer to read the seeded arrproxy admin token so +# the arrstack engine config module can source it. The token is seeded by +# argocd-apps #384 at kv/kubernetes/namespace/arrstack/default/arrproxy-admin-token. +# The deployer's existing secret_backends_read policy only covers +# kv/data/service/vault/+/+/secret_backend/*, which does not match this +# kubernetes/namespace path, so this adds the minimal read grant rather than +# duplicating the secret into the litellm-style path. vault_kv_secret_v2 also +# reads the kv-v2 metadata path on every plan/apply, so grant that too. +--- +rules: + - path: "kv/data/kubernetes/namespace/arrstack/default/arrproxy-admin-token" + capabilities: + - read + - path: "kv/metadata/kubernetes/namespace/arrstack/default/arrproxy-admin-token" + capabilities: + - read + +auth: + approle: + - tf_vault + k8s/au/syd1: + - woodpecker_terraform_vault