From 2628a0c795741f935dc0565e759ef47a517748a8 Mon Sep 17 00:00:00 2001 From: Micha Date: Sat, 6 Jun 2026 12:58:38 +0200 Subject: [PATCH] authelia-oidc: Plan + Runbook fuer app-uebergreifendes SSO - docs/AUTHELIA_OIDC_PLAN.md: v4.39-Client-Schema, Endpoints, Secret-Erzeugung, Rollout-Reihenfolge (Grafana-Proof zuerst, dann Familien-Apps), Grafana-Schritt-fuer-Schritt - MASTER_TODO: OIDC-Punkt auf Plan verweisen, naechster Schritt Grafana-Proof - README: Doku-Index ergaenzt Co-Authored-By: Claude Opus 4.8 --- docs/AUTHELIA_OIDC_PLAN.md | 166 +++++++++++++++++++++++++++++++++++++ docs/MASTER_TODO.md | 2 +- docs/README.md | 1 + 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 docs/AUTHELIA_OIDC_PLAN.md diff --git a/docs/AUTHELIA_OIDC_PLAN.md b/docs/AUTHELIA_OIDC_PLAN.md new file mode 100644 index 0000000..566b306 --- /dev/null +++ b/docs/AUTHELIA_OIDC_PLAN.md @@ -0,0 +1,166 @@ +# Authelia OIDC fuer Apps - Plan & Runbook + +Stand: 2026-06-06. Authelia-Version: **v4.39.20**. + +Ziel: App-uebergreifendes Single-Sign-On ueber Authelia als OpenID-Connect-Provider +(`https://auth.kaleschke.info`). Statt pro App eigener Logins meldet man sich einmal +bei Authelia an (inkl. 2FA) und wird per OIDC an die App durchgereicht. + +> **Status:** Entwurf/Runbook. Noch **kein** Client produktiv ausgerollt. Reihenfolge +> bewusst klein: erst ein risikoarmer Proof (Grafana), dann Familien-Apps. + +--- + +## Grundregeln (wichtig) + +- **Secrets gehoeren nie ins Repo.** OIDC-Client-Secrets (Klartext und pbkdf2-Hash) + liegen ausschliesslich in der Host-Config `/mnt/user/appdata/authelia/config/configuration.yml` + (Hash) und im jeweiligen App-Stack (Klartext, via Komodo Stack-ENV / Secret-Datei), + plus optional Vaultwarden. Dieses Dokument enthaelt nur Schema und Variablennamen. +- **OIDC-Clients leben host-seitig**, wie der bestehende `beszel`-Client. Die Repo-Baseline + `security/authelia/configuration.yml` haelt nur die nicht-geheime Struktur + (`access_control` etc.); `services/authelia-diff.sh` vergleicht standardmaessig nur + `access_control`, OIDC-Clients auf dem Host loesen also keinen Drift-Alarm aus. +- **Issuer/Endpoints** (Authelia OIDC): + - Issuer: `https://auth.kaleschke.info` + - Authorization: `https://auth.kaleschke.info/api/oidc/authorization` + - Token: `https://auth.kaleschke.info/api/oidc/token` + - Userinfo: `https://auth.kaleschke.info/api/oidc/userinfo` + - JWKS: `https://auth.kaleschke.info/jwks.json` + - Discovery: `https://auth.kaleschke.info/.well-known/openid-configuration` +- **PKCE an, wo moeglich** (`require_pkce: true`, `S256`), wie beim Beszel-Client. + +--- + +## Client-Schema (Authelia v4.39, gespiegelt vom bestehenden `beszel`-Client) + +Pro App ein Block unter `identity_providers.oidc.clients` in der **Host-Config**: + +```yaml +identity_providers: + oidc: + clients: + - client_id: '' + client_name: '' + client_secret: '' + public: false + authorization_policy: 'two_factor' # admin-Apps: two_factor; Familien-Apps: s.u. + require_pkce: true + pkce_challenge_method: 'S256' + redirect_uris: + - 'https://.kaleschke.info/' + scopes: + - 'openid' + - 'profile' + - 'email' + - 'groups' + response_types: + - 'code' + grant_types: + - 'authorization_code' + token_endpoint_auth_method: 'client_secret_basic' + userinfo_signed_response_alg: 'none' +``` + +### Client-Secret erzeugen (auf dem Host) + +```bash +docker exec authelia authelia crypto hash generate pbkdf2 \ + --variant sha512 --random --random.length 72 --random.charset rfc3986 +``` + +- Ausgabe: **Random Password** (Klartext) + **Digest** (pbkdf2-Hash). +- **Hash** -> Host-Config `client_secret`. +- **Klartext** -> App-Stack (Komodo Stack-ENV/Secret) + optional Vaultwarden. +- Klartext **nicht** ins Repo, nicht in Logs. + +--- + +## Reihenfolge / Rollout + +| Stufe | App | Domain | OIDC-Support | Policy | Risiko | Begruendung | +|---|---|---|---|---|---|---| +| **1 (Proof)** | Grafana (monitoring) | `monitoring.kaleschke.info` | nativ (`generic_oauth`) | `two_factor` | niedrig | Admin-only, lokaler Grafana-Admin bleibt als Fallback -> kein Lockout-Risiko | +| 2 | Immich | `immich.kaleschke.info` | nativ | s. u. (Familie) | mittel | Familien-Fotos, viele Nutzer; nach erfolgreichem Proof | +| 3 | Nextcloud | `cloud.kaleschke.info` | App `user_oidc` | s. u. | mittel | klassischer OIDC-Login parallel zu lokalem Admin | +| 4 | Mealie | `mealie.kaleschke.info` | nativ | s. u. | niedrig | klein, gut zum Familien-Rollout | +| 5 | Paperless-ngx | `paperless.kaleschke.info` | `django-allauth` (Umgebungsvariablen) | `two_factor` | mittel | dokumentenlastig, Operator-nah | + +**Nicht OIDC:** Vaultwarden hat kein Standard-Endnutzer-OIDC (SSO ist Enterprise/Bitwarden-Feature) -> bleibt eigener Login. ntfy bleibt wie gehabt. + +### Policy-Entscheidung Familien-Apps + +- Admin-Apps (Grafana, Paperless): `authorization_policy: two_factor`. +- Familien-Apps (Immich, Nextcloud, Mealie): **offene Operator-Entscheidung** ob + `one_factor` (nur Authelia-Passwort, bequemer fuer Familie) oder `two_factor`. + Empfehlung: mit `one_factor` starten, 2FA fuer Familie spaeter, sobald TOTP-Enrollment + pro Person eingerichtet ist (sonst Lockout fuer Familienmitglieder). + +--- + +## Stufe 1 konkret: Grafana (empfohlener Erststart) + +### A) Authelia (Host) - Client anlegen +1. Secret erzeugen (Befehl oben). Klartext + Hash notieren. +2. In `/mnt/user/appdata/authelia/config/configuration.yml` unter + `identity_providers.oidc.clients` neuen Block einfuegen: + ```yaml + - client_id: 'grafana' + client_name: 'Grafana' + client_secret: '' + public: false + authorization_policy: 'two_factor' + require_pkce: true + pkce_challenge_method: 'S256' + redirect_uris: + - 'https://monitoring.kaleschke.info/login/generic_oauth' + scopes: ['openid', 'profile', 'email', 'groups'] + response_types: ['code'] + grant_types: ['authorization_code'] + token_endpoint_auth_method: 'client_secret_basic' + userinfo_signed_response_alg: 'none' + ``` +3. `docker restart authelia`, Health + Log pruefen (`Startup complete`, keine Fehler). + +### B) Grafana (Komodo Stack-ENV) - generic_oauth +Im `monitoring`-Stack (Grafana) setzen (Klartext-Secret aus Schritt A): +``` +GF_AUTH_GENERIC_OAUTH_ENABLED=true +GF_AUTH_GENERIC_OAUTH_NAME=Authelia +GF_AUTH_GENERIC_OAUTH_CLIENT_ID=grafana +GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET= +GF_AUTH_GENERIC_OAUTH_SCOPES=openid profile email groups +GF_AUTH_GENERIC_OAUTH_AUTH_URL=https://auth.kaleschke.info/api/oidc/authorization +GF_AUTH_GENERIC_OAUTH_TOKEN_URL=https://auth.kaleschke.info/api/oidc/token +GF_AUTH_GENERIC_OAUTH_API_URL=https://auth.kaleschke.info/api/oidc/userinfo +GF_AUTH_GENERIC_OAUTH_USE_PKCE=true +GF_AUTH_GENERIC_OAUTH_ALLOW_SIGN_UP=true +# optional Rollen-Mapping ueber groups: +# GF_AUTH_GENERIC_OAUTH_ROLE_ATTRIBUTE_PATH=contains(groups[*], 'admins') && 'Admin' || 'Viewer' +``` +- `GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET` als Stack-ENV-only (kein `_FILE`-Support) -> in + `docs/SECRETS_MAP.md` als `grafana_oidc_client_secret` (Stack-ENV) nachziehen. + +### C) Test + Rollback +- Test: `monitoring.kaleschke.info` -> "Sign in with Authelia" -> Authelia-Login (2FA) -> zurueck in Grafana, eingeloggt. +- **Fallback bleibt:** lokaler Grafana-Admin-Login (`/login`) ist weiter aktiv -> kein Lockout. +- Rollback: `GF_AUTH_GENERIC_OAUTH_ENABLED=false` (Grafana redeploy) und/oder Client-Block in Authelia entfernen + `docker restart authelia`. + +--- + +## Doku-Nachzug bei jedem neuen Client + +- `docs/SECRETS_MAP.md`: pro App `_oidc_client_secret` (Stack-ENV) + Hinweis "Hash in Authelia-Host-Config". +- `docs/SERVICE_CATALOG.md`: App-Zeile um "OIDC via Authelia" ergaenzen. +- Dieses Dokument: Rollout-Tabelle abhaken. +- `docs/MASTER_TODO.md`: Fortschritt im OIDC-Punkt nachziehen. + +--- + +## Offene Operator-Entscheidungen vor breitem Rollout + +1. Familien-Apps `one_factor` vs `two_factor` (Lockout-Risiko fuer Familie ohne TOTP). +2. Gruppen/Rollen-Mapping: braucht es Authelia-Gruppen (z. B. `admins`, `family`) fuer + App-Rollen (Grafana Admin/Viewer, Nextcloud-Gruppen)? Wenn ja, in der Authelia + User-Datenbank Gruppen pflegen. +3. Reihenfolge nach dem Grafana-Proof bestaetigen. diff --git a/docs/MASTER_TODO.md b/docs/MASTER_TODO.md index 19d3d3f..acbefbf 100644 --- a/docs/MASTER_TODO.md +++ b/docs/MASTER_TODO.md @@ -26,7 +26,7 @@ Host-/Entscheidungsaufgaben beim **Operator**. | Family-Onboarding erster Termin | Operator | Checkliste ist fertig (`docs/FAMILY_ONBOARDING.md` Abschnitt "Erster Onboarding-Termin"). Operator legt fest, welche Personen/Geraete real verfuegbar sind, und arbeitet die Reihenfolge Vaultwarden -> Immich -> Mealie pro Person ab | `docs/FAMILY_ONBOARDING.md`, `docs/AUDIT_2026-05-25_TODO.md` | | Restore-Test Unraid OS Flash (Stick-Boot) | Operator | Artefakt-Validierung am 2026-06-05 erledigt (`ops/maintenance/check-unraid-flash-backup.sh`, sha256 OK, 8 Kern-Configs). **Verbleibt:** physischer Ersatzstick-Boot-Test, wenn ein Wegwerf-Stick bereitliegt | `docs/RESTORE_MATRIX.md` Abschnitt "Unraid OS Flash" | | Restore-Test Tailscale | Operator | Runbook-Stub abarbeiten: State-Validierung + Reconnect nur auf Wegwerf-Host/VM, danach Geraet in Tailscale-Admin entfernen | `docs/RESTORE_MATRIX.md` Abschnitt "Tailscale" | -| Authelia OIDC fuer Apps (Start) | Operator/Claude | Entscheidung 2026-06-06: **angehen.** Erster Schritt: SSO-Scope festlegen (welche Apps zuerst: z. B. Nextcloud, Immich, Mealie), pro App OIDC-Client-ID/-Secret-Schema und Redirect-URIs planen, Authelia `identity_providers.oidc`-Clients als Repo-Baseline entwerfen. Groesserer Block, eigener Aenderungs-/Test-Zyklus | `docs/AUDIT_2026-05-25_TODO.md`, `security/authelia/configuration.yml` | +| Authelia OIDC fuer Apps | Operator/Claude | **Plan + Runbook erstellt 2026-06-06** (`docs/AUTHELIA_OIDC_PLAN.md`): v4.39-Client-Schema, Issuer/Endpoints, Secret-Erzeugung, Rollout-Reihenfolge. **Naechster konkreter Schritt:** Stufe-1-Proof **Grafana** (`monitoring`) ausrollen — Authelia-Client + `GF_AUTH_GENERIC_OAUTH_*`; lokaler Grafana-Admin bleibt Fallback (kein Lockout). Danach Familien-Apps (Immich/Nextcloud/Mealie/Paperless) | `docs/AUTHELIA_OIDC_PLAN.md`, `security/authelia/configuration.yml` | | Gast-/IoT-Netz einrichten | Operator | Entscheidung 2026-06-06: **aktivieren/planen.** Reihenfolge: (1) **zuerst** LAN-Admin-Ports (`192.168.178.58:8082` AdGuard, weitere) per FRITZ!Box-Netzwerkfilter/Kindersicherung gegen das Gastsegment sperren, (2) dann Gast-WLAN/IoT in der FRITZ!Box aktivieren, (3) Trennung verifizieren (Gastgeraet darf LAN-Admin nicht erreichen) | `docs/NETWORK_INVENTORY.md` | --- diff --git a/docs/README.md b/docs/README.md index 7d10f8d..e09d566 100644 --- a/docs/README.md +++ b/docs/README.md @@ -31,6 +31,7 @@ Diese Datei trennt aktive Betriebsdokumentation von historischer Arbeitsdoku. Ne |---|---| | `STORAGE_LAYOUT.md` | verbindliche Storage-/Share-/Pfad-Regeln | | `SECRETS_MAP.md` | Secret-Namen, Speicherorte und Einbindungsarten ohne Werte | +| `AUTHELIA_OIDC_PLAN.md` | Plan & Runbook fuer app-uebergreifendes SSO via Authelia OIDC | | `HARDWARE_INVENTORY.md` | Host-, Disk-, SMART-, USV- und Power-Baseline | | `NETWORK_INVENTORY.md` | Router, DNS, Tailscale, Portfreigaben und Netzthemen | | `EXTERNAL_DEPENDENCIES.md` | Provider, Konten und externe Abhaengigkeiten |