@@ -21,11 +21,17 @@ Today there is exactly **one human identity** (`admin`) and **one group**
2121 ` ansible/roles/headlamp/tasks/oidc_client.yml:252 ` ) but ** nothing consumes
2222 it** . ` doc/security.md:90 ` ("admin group maps to cluster-admin via
2323 ClusterRoleBinding") is therefore inaccurate.
24- 4 . OpenBao has ** no human auth method** — only ` kubernetes ` auth for workload
25- service accounts (` ansible/roles/openbao/tasks/consumer_wiring.yml ` ) and
26- token auth (root/provisioner). Human operators must use the root token.
27-
28- No viewer/operator tiers, no per-role users, no OpenBao operator login.
24+ No viewer/operator tiers, no per-role users.
25+
26+ ** Out of scope: OpenBao human access.** OpenBao has no human auth method
27+ (only ` kubernetes ` auth for workloads plus root/provisioner tokens), but its
28+ UI is not exposed either, so there is nothing for a human user to log into.
29+ Per-role OpenBao access belongs to the existing backlog item "Expose OpenBao
30+ web ui and tie into keycloak OIDC" and should reuse the Keycloak
31+ client-provisioning and group-mapping patterns this plan establishes. Do not
32+ add OpenBao auth methods, ACL policies for humans, or identity groups here.
33+ (OpenBao KV as * credential storage* for generated passwords stays — that is
34+ existing plumbing, not human auth.)
2935
3036## What already exists (inventory — do not rebuild)
3137
@@ -43,10 +49,10 @@ no `groups` claim, and touches neither k3s RBAC nor OpenBao. Leave it alone.
4349** Reusable patterns** for the pieces below:
4450- Generate-once-persist credential flow (read KV → keep existing or generate →
4551 write KV, all ` no_log ` ): ` keycloak/tasks/main.yml:118-155 ` — template for
46- Piece 3 user passwords and the Piece 4 client secret .
52+ Piece 3 user passwords.
4753- Idempotent Keycloak admin REST provisioning (token → lookup → create/update):
48- ` headlamp/tasks/oidc_client.yml ` — template for Piece 2 groups, Piece 3
49- users, Piece 4 client .
54+ ` headlamp/tasks/oidc_client.yml ` — template for Piece 2 groups and Piece 3
55+ users.
5056- Least-privilege Keycloak service client (realm-management ` manage-users `
5157 only): ` keycloak/tasks/rotator.yml ` — proof the realm-management role-scoping
5258 approach works.
@@ -68,9 +74,6 @@ existing miniature of this. File as its own ticket if wanted.
6874 (pattern to copy for any new client).
6975- Realm import is bootstrap-only; per-client config is done via REST
7076 post-import (see comment at top of ` realmimport.yaml.j2 ` ).
71- - Site ordering (` ansible/playbooks/site.yml ` ): ` openbao ` runs ** before**
72- ` keycloak ` . Anything wiring OpenBao→Keycloak OIDC must run after Keycloak is
73- ready (i.e., live in/after the ` keycloak ` role, not in ` openbao ` ).
7477- Secrets convention: generated credentials are written to OpenBao KV v2 at
7578 ` secret/<app>/... ` via the provisioner token
7679 (` common/tasks/load_openbao_provisioner_token.yml ` ), optionally mirrored to
@@ -79,7 +82,7 @@ existing miniature of this. File as its own ticket if wanted.
7982- Lint: ` ansible-lint -c .ansible-lint ` (production profile),
8083 ` yamllint -c .yamllint . ` (document-start always, 160-col max).
8184
82- ## Plan — 5 independent pieces, in order
85+ ## Plan — 4 independent pieces, in order
8386
8487### Piece 1 — Make the existing admin grant a real group mapping (small)
8588
@@ -148,34 +151,11 @@ keycloak role alongside the import.
1481514. Readiness check : each configured user exists in the realm and has the
149152 expected group memberships.
150153
151- # ## Piece 4 — OpenBao human login via Keycloak OIDC (medium/large)
152-
153- Gives "vault/openbao" per-role access from the backlog item.
154-
155- 1. New Keycloak confidential client `openbao` + groups protocol mapper —
156- copy the REST pattern from `headlamp/tasks/oidc_client.yml`. Persist the
157- client secret to OpenBao KV (`secret/openbao/oidc-client`).
158- 2. Enable OpenBao `oidc` auth method (`POST /v1/sys/auth/oidc`), configure
159- ` oidc_discovery_url` = Keycloak realm issuer, `oidc_client_id/secret`,
160- discovery CA = internal CA bundle. Create OIDC role `default` with
161- `groups_claim : groups`, redirect URIs for CLI (`http://localhost:8250/...`)
162- and UI callback.
163- 3. Write ACL policies : ` armory-admin` (full `secret/*` + sys read),
164- ` armory-operator` (CRUD on `secret/*` data), `armory-viewer` (read/list
165- only). Map via identity groups : external group per Keycloak group
166- (`/v1/identity/group` type=external + group-alias on the OIDC accessor)
167- → attach the policy.
168- 4. **Ordering** : implement as `ansible/roles/keycloak/tasks/openbao_oidc_auth.yml`
169- (or a new role after `keycloak` in site.yml) — Keycloak must be up.
170- Tag it (e.g. `openbao_oidc`).
171- 5. Readiness check : auth method enabled, role present, `vault login -method=oidc`
172- documented in `doc/operations.md` (manual verification — browser flow).
173-
174- # ## Piece 5 — Docs + validation sweep (small)
154+ # ## Piece 4 — Docs + validation sweep (small)
175155
176156- Update `doc/security.md` access-control table (remove the "Coarse RBAC —
177157 Backlog" row), `doc/configuration.md` (new vars), `doc/operations.md`
178- (how to log in as each role to Headlamp/kubectl/OpenBao ).
158+ (how to log in as each role to Headlamp/kubectl).
179159- Full run : ` ansible-playbook playbooks/site.yml` then
180160 ` playbooks/readiness_check.yml` green in the Vagrant VM.
181161
@@ -191,5 +171,4 @@ ansible-playbook playbooks/readiness_check.yml
191171` ` `
192172
193173Manual : log in to Headlamp as `viewer` → confirm read-only; as `operator`
194- → confirm edit but no RBAC changes; `vault login -method=oidc` as each user
195- → confirm policy attachment (`bao token lookup`).
174+ → confirm edit but no RBAC changes; as `admin` → confirm cluster-admin.
0 commit comments