Project

General

Profile

Sub-Task #254

Updated by Bricklou 26 days ago

Support multi-provider OIDC configuration, config-file based, not DB-backed and not CRD-based (Kubestro is a standalone Postgres-backed server, no operator/controller infra exists, so a CRD would mean building watch/reconcile machinery just to read config at boot). 

 Pattern (used by Grafana, Loki, Gitea): unified structured config file (YAML) + environment variable overrides for secrets, loaded via `config-rs` or `figment`, following the existing `Config::from_env` pattern (apps/server/cli/src/config.rs). 

 Kubernetes/GitOps split: 
 - ConfigMap holds the full provider structure (issuer, client_id, scopes, icon) *except* `client_secret` — fully git-committed, plaintext, PR-reviewable. 
 - Secret holds each provider's `client_secret`, injected as an env var per provider (works as-is with SOPS, Sealed Secrets, External Secrets Operator, Vault, etc — no format changes needed on the secret side). 
 - One mechanism for overrides: `config-rs`'s `Environment::default().separator("__")`, e.g. `OIDC_PROVIDERS__GOOGLE__CLIENT_SECRET` overrides `oidc_providers.google.client_secret`. No `${VAR}` interpolation syntax in the file itself — one override mechanism, not two. 

 Format spec: 

 ```yaml <pre> 
 # config.yaml (ConfigMap, git-committed, no secrets) 
 oidc_providers: 
   google: 
     name: Google 
     issuer_url: https://accounts.google.com     # discovery doc = {issuer_url}/.well-known/openid-configuration 
     client_id: xxxxx.apps.googleusercontent.com 
     scopes: [openid, email, profile] 
     icon: google                                # slug into github.com/homarr-labs/dashboard-icons 

   keycloak: 
     name: Company SSO 
     issuer_url: https://sso.example.com/realms/kubestro 
     client_id: kubestro-dashboard 
     scopes: [openid, email] 
     icon_url: https://sso.example.com/icon.svg # override for providers not in the known icon set 
 ``` </pre> 

 Env vars (from Secret, per provider): 

 ```bash 
 <pre> 
 OIDC_PROVIDERS__GOOGLE__CLIENT_SECRET=GOCSPX-xxxxx 
 OIDC_PROVIDERS__KEYCLOAK__CLIENT_SECRET=s3cr3t 
 ``` </pre> 

 Deployment mounts the ConfigMap as `/etc/kubestro/config.yaml` (readOnly volume) and injects each `client_secret` as an env var via `secretKeyRef`. A config/secret change plus a rollout (as GitOps tools like Flux/ArgoCD already do) picks up the new config on next boot — no hot-reload, no CRD, no extra RBAC. 

 - Provider key (`google`, `keycloak`, ...) is the stable slug: used in redirect URL (`/auth/oidc/{id}/callback`) and in the discovery-endpoint response. Map key replaces the earlier `id:` list-item field. 
 - `issuer_url`: OIDC issuer identifier, not the discovery endpoint itself — backend fetches `{issuer_url}/.well-known/openid-configuration` at startup to resolve authorize/token/jwks endpoints (standard OIDC discovery). 
 - `icon`: slug resolved against homarr-labs/dashboard-icons (https://github.com/homarr-labs/dashboard-icons), served via their CDN. `icon_url`: explicit override for custom/self-hosted providers not in that set. 

 Non-k8s/simple deployments: same env-var override mechanism still works standalone (set `OIDC_PROVIDERS__<ID>__*` directly), config file path still required via e.g. `OIDC_CONFIG_FILE`.

Back