From 403e66556ce9449fb550f9e84fe53a1b5dc6d564 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sat, 1 Aug 2026 20:33:21 -0400 Subject: [PATCH] feat: grant sso-broker OpenBao access to secret/plugins/* (v1.30.1) Prerequisite for the SSO Manager plugin system (shipped in sso-manager-node v1.17.0). Adds secret/data/plugins/* (CRUD+list) + secret/metadata/plugins/* (list/read/delete) to the sso-broker policy HCL so the SSO can store per-instance plugin secrets in OpenBao instead of sso-secrets.js. ensure_policy is idempotent, so re-running ./setup.sh grants the existing SSO_VAULT_TOKEN live. Docs: secrets.md (Plugin secrets section + policy row), architecture.md. Co-Authored-By: Claude --- CHANGELOG.md | 22 ++++++++++++++++++++++ docs/architecture.md | 2 +- docs/secrets.md | 30 ++++++++++++++++++++++++++++-- setup.sh | 6 +++++- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5ff23..4154604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ orchestration code; see each submodule's own `CHANGELOG.md` [sso-manager-node](https://github.com/theta42/sso-manager-node/blob/master/CHANGELOG.md)) for what changed inside the apps it composes. +## [v1.30.1] - 2026-08-01 + +Prerequisite release for the SSO Manager plugin system (shipped in +sso-manager-node v1.17.0). Grants the `sso-broker` OpenBao policy access to the +new per-instance plugin secrets namespace so the SSO can store plugin secrets in +OpenBao instead of `sso-secrets.js`. + +### Changed (theta-suite orchestration) +- **`setup.sh`**: added `secret/data/plugins/*` (CRUD+list) and + `secret/metadata/plugins/*` (list/read/delete) to the `sso-broker` policy + HCL. `ensure_policy sso-broker` is idempotent, so re-running `./setup.sh` + immediately grants the existing `SSO_VAULT_TOKEN` access to `secret/plugins/*` + (policies are evaluated live; the token keeps its id). The SSO side fails-soft + with a clear error if this grant is absent. +- **Docs**: `docs/secrets.md` (new "Plugin secrets" section + `sso-broker` + policy row) and `docs/architecture.md` (sso-manager access row) now list + `secret/plugins/*`. + +> The plugin system itself (configurable plugin instances, load/unload, UI/API, +> multi-copy, secrets in OpenBao) is in sso-manager-node v1.17.0; theta-suite +> will bump its submodule gitlink to that release next. + ## [v1.30.0] - 2026-08-01 The project is renamed **theta-env → theta-suite** — it has grown from a diff --git a/docs/architecture.md b/docs/architecture.md index c627972..cfc4392 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -99,7 +99,7 @@ the paths it needs: | Service | env var | Policy | Access | |---------|---------|--------|--------| -| sso-manager | `SSO_VAULT_TOKEN` | `sso-broker` | `secret/sso-manager/conf`, `secret/users/*`, `secret/apps/*`; also mints per-user + per-app tokens | +| sso-manager | `SSO_VAULT_TOKEN` | `sso-broker` | `secret/sso-manager/conf`, `secret/users/*`, `secret/apps/*`, `secret/plugins/*`; also mints per-user + per-app tokens | | proxy | `PROXY_VAULT_TOKEN` | `proxy` | `secret/proxy/conf` (read) | | jump-host | `JUMP_VAULT_TOKEN` | `jump-host` | `secret/jump-host/conf` (read) | diff --git a/docs/secrets.md b/docs/secrets.md index 4993a2b..697a32c 100644 --- a/docs/secrets.md +++ b/docs/secrets.md @@ -60,7 +60,7 @@ never passed to a service container. | Policy | Capabilities | Held by | |---|---|---| -| `sso-broker` | read/write `secret/sso-manager/conf`, `secret/users/*`, `secret/apps/*`; `update` on `auth/token/create/sso-broker`; `update` on `sys/policies/acl/user-*`, `app-*`, `sso-admin` | SSO (`SSO_VAULT_TOKEN`) | +| `sso-broker` | read/write `secret/sso-manager/conf`, `secret/users/*`, `secret/apps/*`, `secret/plugins/*`; `update` on `auth/token/create/sso-broker`; `update` on `sys/policies/acl/user-*`, `app-*`, `sso-admin` | SSO (`SSO_VAULT_TOKEN`) | | `sso-admin` | read/write/list all of `secret/*` | admin UI sessions (minted by the broker) | | `proxy` | read `secret/proxy/conf` | proxy (`PROXY_VAULT_TOKEN`) | | `jump-host` | read `secret/jump-host/conf` | jump host (`JUMP_VAULT_TOKEN`) | @@ -150,6 +150,31 @@ const data = await baoConf.get('apps/my-service/conf'); // secret/data/apps/my-s await baoConf.set('apps/my-service/conf', { db_password: '...' }); ``` +## Plugin secrets + +The SSO Manager's plugin system (configurable plugin instances you create, +edit, load/unload, and run from the **Plugins** page) stores each instance's +secrets in its own OpenBao namespace, `secret/plugins//conf`, +rather than in the static `sso-secrets.js` `discovery.plugins` block. The +SSO reads and writes these server-side through the `sso-broker` token (the +plugin runs in-process as a BullMQ worker, so it needs no token of its own), +and the admin UI only ever sees masked (`********`) values. + +- A **plugin type** is a module under `nodejs/plugins//.js` + exporting a manifest (`configSchema` declares which fields are `secret`). +- A **plugin instance** is a configured, loadable/unloadable copy of a type, + tracked in the `PluginInstance` table; you can have multiple instances of the + same type (e.g. two Proxmox endpoints with their own tokens). +- Non-secret config lives in the DB row; only the `secret:true` field values + live in `secret/plugins//conf`. + +Deleting an instance removes both the DB row and its `secret/plugins//*` +namespace. Legacy `discovery.plugins` entries in `sso-secrets.js` are migrated +to instances automatically on the first boot of SSO Manager ≥ v1.17.0 (the +secret fields are copied into OpenBao at that point). See the SSO Manager +[plugins docs](https://theta42.github.io/sso-manager-node/plugins.html) for the +UI/API reference. + ## Operator rotation If a secret is exposed (or just on a routine schedule), rotate it at the @@ -192,4 +217,5 @@ re-mint the per-app tokens. git-destructive operation you can opt into. - **Per-app secrets beyond boot config** (e.g. the proxy's DNS-provider creds, the jump host's per-user LDAP SSH keys) moving into OpenBao — only the - boot-critical `*-secrets.js` contents moved in this phase. \ No newline at end of file + boot-critical `*-secrets.js` contents moved in this phase. (Plugin instance + secrets *are* in OpenBao, at `secret/plugins//conf` — see above.) \ No newline at end of file diff --git a/setup.sh b/setup.sh index b4d7f7e..3e96648 100755 --- a/setup.sh +++ b/setup.sh @@ -769,7 +769,9 @@ seed_app_conf() { info "Configuring OpenBao policies..." # sso-broker — sso's authority to read/write its own conf, mint per-user and # per-app tokens (auth/token/create/sso-broker), and create the matching -# user- / app- / sso-admin policies. +# user- / app- / sso-admin policies. secret/plugins/* holds per-instance +# plugin secrets managed by the SSO plugin system (configurable plugin copies, +# loaded/unloaded at runtime — see sso-manager-node docs/plugins.md). ensure_policy sso-broker <<'HCL' path "secret/data/sso-manager/conf" { capabilities = ["create", "read", "update", "delete", "list"] } path "secret/metadata/sso-manager/conf" { capabilities = ["list", "read", "delete"] } @@ -777,6 +779,8 @@ path "secret/data/users/*" { capabilities = ["create", "read", "update", "delete path "secret/metadata/users/*" { capabilities = ["list", "read", "delete"] } path "secret/data/apps/*" { capabilities = ["create", "read", "update", "delete", "list"] } path "secret/metadata/apps/*" { capabilities = ["list", "read", "delete"] } +path "secret/data/plugins/*" { capabilities = ["create", "read", "update", "delete", "list"] } +path "secret/metadata/plugins/*" { capabilities = ["list", "read", "delete"] } path "auth/token/create/sso-broker" { capabilities = ["update"] } path "sys/policies/acl/user-*" { capabilities = ["create", "read", "update", "delete", "list"] } path "sys/policies/acl/app-*" { capabilities = ["create", "read", "update", "delete", "list"] }