Files
unkin-agent ff2dff7af2
ci/woodpecker/tag/release Pipeline was successful
Add optional methods attribute to the arrstack role resource (#3)
## Why

Engine plugin v0.2.0 added a `methods` field to arrstack roles, pinning a minted arrproxy key to a set of HTTP methods so a read-only integration can be handed a key that cannot write. The provider had no way to express it, so those roles could not be managed from `terraform-vault`.

## How

- Adds an optional `methods` set attribute to `arrstack_secret_backend_role`, validated at plan time against `GET/HEAD/POST/PUT/PATCH/DELETE/OPTIONS` (upper case only, since the engine stores them upper-cased and a lower-case value would drift on every plan).
- Always writes `methods`: the engine only clears an existing scope when the key is present, so an omitted key would leave a stale scope behind.
- Reads an unrestricted role back as null rather than an empty set, so a config that omits `methods` shows no drift; a scope cleared out of band still surfaces as a diff.
- Documents the attribute in the README and both example configs.
- Tests cover the write mapping (null and populated), the read-back cases (absent/empty/null/cleared), and the plan-time validator.

Dependency: engine plugin >= 0.2.0.
Reviewed-on: #3
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-08-30 17:05:47 +10:00

96 lines
3.4 KiB
Markdown

# terraform-provider-vault-secrets-arrstack
A Terraform/OpenTofu provider that manages the **arrstack dynamic secrets engine**
([`vault-plugin-secrets-arrstack`](https://git.unkin.net/unkin/vault-plugin-secrets-arrstack))
on HashiCorp Vault or OpenBao, so the engine's mount, config, and roles can be
driven declaratively (e.g. from `terraform-vault`). The engine mints short-lived
arrproxy API keys scoped to the arr apps (Sonarr, Radarr, Prowlarr).
Source address: `artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/vault-secrets-arrstack`
(declare it under the local name `arrstack`, so its resources are `arrstack_*`).
## Resources
| Resource | Manages |
|----------|---------|
| `arrstack_secret_backend` | Mounts the engine at a path and writes its `config` (arrproxy base URL, request timeout, seeded admin token, optional CA cert). |
| `arrstack_secret_backend_role` | A role: `apps` (subset of sonarr/radarr/prowlarr), optional `methods` (HTTP method scope), `ttl`, `max_ttl`. |
## Usage
```hcl
terraform {
required_providers {
arrstack = {
source = "artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/vault-secrets-arrstack"
version = "0.1.0"
}
}
}
provider "arrstack" {
# address / token fall back to VAULT_ADDR / VAULT_TOKEN.
}
resource "arrstack_secret_backend" "arrstack" {
path = "arrstack"
base_url = "https://arrstack.unkin.net"
admin_token = var.arrproxy_admin_token
}
resource "arrstack_secret_backend_role" "all" {
backend = arrstack_secret_backend.arrstack.path
name = "all"
apps = ["sonarr", "radarr", "prowlarr"]
ttl = 60
max_ttl = 86400
}
# Read-only role: keys minted from it may only issue GET/HEAD.
resource "arrstack_secret_backend_role" "sonarr_ro" {
backend = arrstack_secret_backend.arrstack.path
name = "sonarr-ro"
apps = ["sonarr"]
methods = ["GET", "HEAD"]
ttl = 60
max_ttl = 86400
}
```
### Notes
- `admin_token` is write-only: Vault never returns it, so it is preserved in
Terraform state and does not show drift. `ca_cert` is likewise write-only and
preserved; omit it to use the system trust store.
- Writing `config` makes the engine authenticate against arrproxy as an admin,
so a bad URL or token fails the apply.
- `apps` is required; entries must be a subset of `sonarr`, `radarr`, `prowlarr`.
- `methods` is optional and restricts a minted key to those HTTP methods;
omitting it (or setting `[]`) leaves the key unrestricted. Entries must be
upper case and a subset of `GET`, `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE`,
`OPTIONS` — the engine stores them upper-cased, so a lower-case value would
show permanent drift and is rejected at plan time. Requires engine plugin
`vault-plugin-secrets-arrstack` >= 0.2.0.
## Import
```sh
terraform import arrstack_secret_backend.arrstack arrstack
terraform import arrstack_secret_backend_role.all arrstack/roles/all
```
## Development
```sh
make build # build the provider binary
make install # install into ~/.terraform.d/plugins for local use
make test # unit tests (race)
make package # build the release zip
```
Releases are tag-driven (`make patch|minor|major`): a Woodpecker pipeline builds
`terraform-provider-vault-secrets-arrstack_<version>_linux_amd64.zip` and PUTs it
to the artifactapi terraform registry
(`.../api/v2/remotes/terraform-unkin/files/terraform-unkin/vault-secrets-arrstack/<file>`),
which signs it server-side. Install it via the bare `source` address above.