From 7ff3d2a09bf044d3c1c53056f703c992de147713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Mon, 9 Feb 2026 19:44:06 +0100 Subject: [PATCH] docs: move openbao-kanidm-oidc plan to completed --- docs/plans/completed/openbao-kanidm-oidc.md | 87 ++++++++++++++++ docs/plans/openbao-kanidm-oidc.md | 108 -------------------- 2 files changed, 87 insertions(+), 108 deletions(-) create mode 100644 docs/plans/completed/openbao-kanidm-oidc.md delete mode 100644 docs/plans/openbao-kanidm-oidc.md diff --git a/docs/plans/completed/openbao-kanidm-oidc.md b/docs/plans/completed/openbao-kanidm-oidc.md new file mode 100644 index 0000000..0baa238 --- /dev/null +++ b/docs/plans/completed/openbao-kanidm-oidc.md @@ -0,0 +1,87 @@ +# OpenBao + Kanidm OIDC Integration + +## Status: Completed + +Implemented 2026-02-09. + +## Overview + +Enable Kanidm users to authenticate to OpenBao (Vault) using OIDC for Web UI access. Members of the `admins` group get full read/write access to secrets. + +## Implementation + +### Files Modified + +| File | Changes | +|------|---------| +| `terraform/vault/oidc.tf` | New - OIDC auth backend and roles | +| `terraform/vault/policies.tf` | Added oidc-admin and oidc-default policies | +| `terraform/vault/secrets.tf` | Added OAuth2 client secret | +| `terraform/vault/approle.tf` | Granted kanidm01 access to openbao secrets | +| `services/kanidm/default.nix` | Added openbao OAuth2 client, enabled imperative group membership | + +### Kanidm Configuration + +OAuth2 client `openbao` with: +- Confidential client (uses client secret) +- Web UI callback only: `https://vault.home.2rjus.net:8200/ui/vault/auth/oidc/oidc/callback` +- Legacy crypto enabled (RS256 for OpenBao compatibility) +- Scope maps for `admins` and `users` groups + +Group membership is now managed imperatively (`overwriteMembers = false`) to prevent provisioning from resetting group memberships on service restart. + +### OpenBao Configuration + +OIDC auth backend at `/oidc` with two roles: + +| Role | Bound Claims | Policy | Access | +|------|--------------|--------|--------| +| `admin` | `groups = admins@home.2rjus.net` | `oidc-admin` | Full read/write to secrets, system health/metrics | +| `default` | (none) | `oidc-default` | Token lookup-self, system health | + +Both roles request scopes: `openid`, `profile`, `email`, `groups` + +### Policies + +**oidc-admin:** +- `secret/*` - create, read, update, delete, list +- `sys/health` - read +- `sys/metrics` - read +- `sys/auth` - read +- `sys/mounts` - read + +**oidc-default:** +- `auth/token/lookup-self` - read +- `sys/health` - read + +## Usage + +### Web UI Login +1. Navigate to https://vault.home.2rjus.net:8200 +2. Select "OIDC" authentication method +3. Enter role: `admin` (for admins) or `default` (for any user) +4. Click "Sign in with OIDC" +5. Authenticate with Kanidm + +### Group Management +Add users to admins group for full access: +```bash +kanidm group add-members admins +``` + +## Limitations + +**CLI login not supported:** Kanidm requires HTTPS for all redirect URIs on confidential (non-public) OAuth2 clients. OpenBao CLI uses `http://localhost:8250/oidc/callback` which Kanidm rejects. Public clients would allow localhost redirects, but OpenBao requires a client secret for OIDC auth. + +## Lessons Learned + +1. **Kanidm group names:** Groups are returned as `groupname@domain` (e.g., `admins@home.2rjus.net`), not just the short name +2. **RS256 required:** OpenBao only supports RS256 for JWT signing; Kanidm defaults to ES256, requiring `enableLegacyCrypto = true` +3. **Scope request:** OIDC roles must explicitly request the `groups` scope via `oidc_scopes` +4. **Provisioning resets:** Kanidm provisioning with default `overwriteMembers = true` resets group memberships on restart +5. **Two-phase Terraform:** Secret must exist before OIDC backend can validate discovery URL + +## References + +- [OpenBao JWT/OIDC Auth Method](https://openbao.org/docs/auth/jwt/) +- [Kanidm OAuth2 Documentation](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html) diff --git a/docs/plans/openbao-kanidm-oidc.md b/docs/plans/openbao-kanidm-oidc.md deleted file mode 100644 index 67869af..0000000 --- a/docs/plans/openbao-kanidm-oidc.md +++ /dev/null @@ -1,108 +0,0 @@ -# OpenBao + Kanidm OIDC Integration - -## Overview - -Enable Kanidm users to authenticate to OpenBao (Vault) using OIDC, allowing access to secrets based on Kanidm group membership. - -## Current State - -**Kanidm:** -- Server: `auth.home.2rjus.net` (kanidm01) -- Domain: `home.2rjus.net` -- Groups: `admins`, `users`, `ssh-users` -- No OIDC clients configured yet - -**OpenBao:** -- Server: `vault.home.2rjus.net` (vault01) -- Auth: AppRole only (machine-to-machine) -- No human user authentication configured - -## OpenBao OIDC Auth Method - -OpenBao includes the JWT/OIDC auth method in the open-source version (unlike Vault Enterprise which gates some auth features). Key points: - -- Enable with: `bao auth enable oidc` -- Supports browser-based OIDC login flow -- Maps OIDC claims/groups to OpenBao policies -- Works with both CLI (`bao login`) and Web UI - -### Required Configuration - -```bash -bao write auth/oidc/config \ - oidc_discovery_url="https://auth.home.2rjus.net/oauth2/openid/" \ - oidc_client_id="" \ - oidc_client_secret="" \ - default_role="default" -``` - -### Callback URIs - -OpenBao requires specific callback URIs registered in Kanidm: - -- **CLI:** `http://localhost:8250/oidc/callback` -- **Web UI:** `https://vault.home.2rjus.net:8200/ui/vault/auth/oidc/oidc/callback` - -## Kanidm OAuth2 Configuration - -Kanidm supports declarative OAuth2 client provisioning via NixOS: - -```nix -services.kanidm.provision.systems.oauth2.openbao = { - displayName = "OpenBao Secrets"; - # originUrl - where the client lives - # originLanding - where to redirect after auth - # basicSecretFile - client secret - # scopeMaps - which scopes groups can request - # claimMaps - custom claims based on group membership -}; -``` - -The `basicSecretFile` should contain the client secret, fetched from Vault. - -## Implementation Approach - -### 1. Create OAuth2 Client in Kanidm - -Add to `services/kanidm/default.nix`: -- OAuth2 client `openbao` with callback URIs -- Scope maps for `admins` and `users` groups -- Claim maps to expose group membership - -### 2. Enable OIDC Auth in OpenBao - -Options: -- **Terraform:** Add `vault_jwt_auth_backend` resource in `terraform/vault/` -- **NixOS:** Configure in vault01 host config - -Terraform is probably cleaner since we already manage OpenBao config there. - -### 3. Create OpenBao Roles - -Map Kanidm groups to policies: - -| Kanidm Group | OpenBao Role | Policy | -|--------------|--------------|--------| -| `admins` | `admin` | Full read access to secrets | -| `users` | `user` | Limited read access | - -### 4. Chicken-and-Egg Problem - -The OAuth2 client secret needs to be stored in OpenBao, but OpenBao needs the secret to configure OIDC auth. Solutions: - -1. **Bootstrap manually:** Create initial secret via `bao` CLI -2. **Two-phase Terraform:** First create the secret, then configure OIDC -3. **Static secret:** Use a static secret for the OAuth2 client (less ideal) - -## Open Questions - -1. **Web UI access:** Do we want users logging into the OpenBao web UI, or just CLI? -2. **Policy granularity:** What secrets should `admins` vs `users` access? -3. **Token TTL:** How long should OIDC-issued tokens last? - -## References - -- [OpenBao JWT/OIDC Auth Method](https://openbao.org/docs/auth/jwt/) -- [OpenBao OIDC Provider Configuration](https://openbao.org/docs/auth/jwt/oidc-providers/) -- [Kanidm OAuth2 Documentation](https://kanidm.github.io/kanidm/stable/integrations/oauth2.html) -- [NixOS Kanidm OAuth2 Options](https://search.nixos.org/options?query=services.kanidm.provision.systems.oauth2)