diff --git a/ops/restore-tests/authelia-compose.test.yml b/ops/restore-tests/authelia-compose.test.yml index 5d82178..0093203 100644 --- a/ops/restore-tests/authelia-compose.test.yml +++ b/ops/restore-tests/authelia-compose.test.yml @@ -30,8 +30,7 @@ services: condition: service_healthy command: - authelia - - --config=/config/configuration.yml - - --config=/config/configuration.test-overlay.yml + - --config=/config/configuration.restoretest.yml environment: TZ: Europe/Berlin # Wegwerf-Secrets nur fuer den isolierten Smoke. Niemals produktive @@ -42,10 +41,10 @@ services: AUTHELIA_STORAGE_ENCRYPTION_KEY: restoretest-authelia-storage-enc-key-placeholder-32 AUTHELIA_STORAGE_POSTGRES_PASSWORD: restoretest-authelia-db AUTHELIA_NOTIFIER_SMTP_PASSWORD: restoretest-authelia-smtp-placeholder - # Die command:-Config laedt configuration.yml + Test-Overlay (zweite - # Datei gewinnt bei Konflikt). Das Overlay zwingt storage/notifier/ - # session auf isolierte Test-Backends, damit kein produktives Postgres - # erreicht und kein echter SMTP-Versand ausgeloest wird. + # Die command:-Config laedt die vom Skript erzeugte Restore-Test-Config. + # Sie ersetzt produktive storage/notifier/session-Bloecke durch isolierte + # Test-Backends, damit kein produktives Postgres erreicht und kein echter + # SMTP-Versand ausgeloest wird. AUTHELIA__SERVER__ADDRESS: tcp://0.0.0.0:9091 volumes: - /mnt/user/backups/restore-lab/authelia/config:/config diff --git a/ops/restore-tests/authelia-plan.md b/ops/restore-tests/authelia-plan.md index 7a7aac9..453117c 100644 --- a/ops/restore-tests/authelia-plan.md +++ b/ops/restore-tests/authelia-plan.md @@ -7,7 +7,7 @@ Nachweisen, dass die Authelia-Konfiguration aus dem produktiven Borg-Archiv in e Bewusst **nicht** Teil dieses Tests: - Restore mit produktiven Authelia-Secrets. Der Test nutzt ausschliesslich Wegwerf-Werte fuer `AUTHELIA_JWT_SECRET`, `AUTHELIA_SESSION_SECRET`, `AUTHELIA_STORAGE_ENCRYPTION_KEY`, `AUTHELIA_STORAGE_POSTGRES_PASSWORD`, `AUTHELIA_NOTIFIER_SMTP_PASSWORD`. Eine Echtsession auf produktiven Daten waere fachlich nicht sinnvoll. -- SMTP-Realanruf an GMX. Notifier wird im Test-Overlay auf Filesystem umgebogen. +- SMTP-Realanruf an GMX. Notifier wird in der Test-Konfiguration auf Filesystem umgebogen. - Forward-Auth gegen Traefik. Test laeuft nur auf `127.0.0.1:19091`, keine Traefik-Route. - WebAuthn-/Duo-/OIDC-Identity-Provider-Endpunkte. Smoke prueft `/api/health`. @@ -23,7 +23,7 @@ Bewusst **nicht** Teil dieses Tests: - Restore-Lab: `/mnt/user/backups/restore-lab/authelia` - Testdatenpfade: - - `/mnt/user/backups/restore-lab/authelia/config` (restaurierte configuration.yml + Test-Overlay) + - `/mnt/user/backups/restore-lab/authelia/config` (restaurierte `configuration.yml.original` + erzeugte `configuration.restoretest.yml`) - `/mnt/user/backups/restore-lab/authelia/postgres` (Test-Postgres-Datadir) - `/mnt/user/backups/restore-lab/authelia/dumps/latest/postgresql17-authelia.dump` (falls extrahiert) - `/mnt/user/backups/restore-lab/authelia/config/notifier/notifications.txt` (Filesystem-Notifier-Ausgabe) @@ -37,8 +37,8 @@ Bewusst **nicht** Teil dieses Tests: - produktive Pfade `/mnt/user/appdata/authelia/*` werden **nicht** beschrieben - produktive Secret-Dateien `/mnt/user/appdata/secrets/authelia_*.txt` werden **nicht** gemountet -- produktive shared PostgreSQL 18 wird **nicht** angesprochen (Test-Overlay zwingt `storage` auf Test-Postgres) -- echter SMTP-Versand wird **nicht** ausgeloest (Test-Overlay zwingt `notifier` auf Filesystem) +- produktive shared PostgreSQL 18 wird **nicht** angesprochen (`configuration.restoretest.yml` zwingt `storage` auf Test-Postgres) +- echter SMTP-Versand wird **nicht** ausgeloest (`configuration.restoretest.yml` zwingt `notifier` auf Filesystem) - produktive Domain `auth.kaleschke.info` wird **nicht** uebernommen - Testcontainer publishen nur auf `127.0.0.1`, keine LAN-/Tailscale-Bindung - Borg-Passphrase wird aus `/mnt/user/appdata/secrets/borg_repo_passphrase.txt` gelesen und nirgendwo geloggt @@ -48,10 +48,10 @@ Bewusst **nicht** Teil dieses Tests: 1. Restore-Lab-Pfade leer anlegen 2. `local/appdata/authelia/config` aus dem aktuellsten Borg-Archiv extrahieren 3. optional `local/borg-dumps/latest/postgresql17-authelia.dump` extrahieren; wenn nicht im Archiv vorhanden, weiter ohne DB-Restore -4. Test-Overlay-Datei `configuration.test-overlay.yml` neben die restaurierte `configuration.yml` schreiben (zwingt storage/notifier/session auf Test-Werte) +4. `configuration.restoretest.yml` aus der restaurierten `configuration.yml` erzeugen: produktive `storage`/`notifier`/`session`/JWT-Bloecke entfernen und Test-Werte anhaengen 5. Test-Postgres mit `ops/restore-tests/authelia-compose.test.yml` hochfahren 6. optional Dump per `pg_restore -Fc --clean --if-exists --no-owner --no-privileges` einspielen (mit transientem Retry wie im Immich-/Paperless-Test) -7. `authelia config validate` mit beiden Configdateien laufen lassen +7. `authelia config validate` gegen `configuration.restoretest.yml` laufen lassen 8. `restoretest-authelia` starten und HTTP-Health `http://127.0.0.1:19091/api/health` pollen 9. Report unter `/mnt/user/backups/restore-reports/authelia-YYYY-MM-DD.md` schreiben 10. Testcontainer stoppen und Restore-Lab bereinigen (`--keep-data` ueberschreibt) @@ -75,10 +75,10 @@ Optional spaeter: | Risiko | Beschreibung | Mitigation | |---|---|---| -| Overlay-Konflikt mit Originalkonfiguration | `configuration.yml` definiert ggf. Sections, die das Overlay nicht ueberschreibt | bei `config validate`-Fehler `configuration.yml.original` zum Vergleich pruefen; Overlay erweitern | +| Sanitizing-Konflikt mit Originalkonfiguration | `configuration.yml` definiert neue produktive Sections, die ersetzt werden muessen | bei `config validate`-Fehler `configuration.yml.original` zum Vergleich pruefen; Strip-Liste oder Test-Block im Skript erweitern | | SMTP-Startup-Check blockiert Start | Wenn Authelia trotz `disable_startup_check` SMTP probiert | Container-Logs lesen, ggf. Notifier-Block weiter haerten | | Postgres-Schema-Drift nach Major-Update | Authelia migriert Schema beim Start; Dump aus 17er-Cluster kann unter 18er andere Indexe brauchen | Smoke ist DB-Schema-tolerant; bei Validierung Logs auf `migration` pruefen | -| identity_validation Block fehlt im Original | Aelteres Authelia-Schema kennt den Block nicht; Overlay fuegt ihn an | Validate-Config Output lesen, ggf. Overlay anpassen | +| identity_validation Schema-Drift | Aelteres/neueres Authelia-Schema erwartet andere Keys | Validate-Config Output lesen, ggf. Test-Block anpassen | | users_database.yml mit produktiven Hashes | Daten werden ins Restore-Lab kopiert, aber niemals gemountet auf produktive Domain | OK; Testpfad ist isoliert, kein Browser-Zugang ueber LAN | ## Noch offen vor dem ersten echten Lauf diff --git a/ops/restore-tests/authelia-restore-test.sh b/ops/restore-tests/authelia-restore-test.sh index a45ce77..36517fc 100644 --- a/ops/restore-tests/authelia-restore-test.sh +++ b/ops/restore-tests/authelia-restore-test.sh @@ -49,13 +49,13 @@ Planned isolation: - Test-Postgres: postgres:18.4 mit Wegwerf-Credentials - Test-Authelia: authelia/authelia:4.39.20 (Image-Pin wie Produktion) - Wegwerf-Secrets ausschliesslich im Test-Compose -- configuration.yml wird im Restore-Lab gepatcht: +- configuration.restoretest.yml wird im Restore-Lab erzeugt: * storage -> Test-Postgres (kein produktives Postgres erreicht) * notifier -> Filesystem (KEIN SMTP-Versand) - * session -> in-memory (kein Redis-Backend noetig) + * session -> lokaler Smoke ohne produktive Session-Secrets - Test endpoint: 127.0.0.1:19091/api/health (no Traefik, no public domain) Smoke-Test: -- authelia config validate gegen gepatchte configuration.yml +- authelia config validate gegen configuration.restoretest.yml - HTTP 200 von /api/health EOF exit 0 @@ -110,10 +110,12 @@ if borg_extract "/restore/authelia-extract" "local/borg-dumps/latest/postgresql1 fi fi -# Stufe 3: configuration.yml im Restore-Lab gezielt patchen. -# Wir ersetzen storage/notifier/session-Blocks durch Test-Definitionen, -# damit der Test KEIN produktives Postgres und KEIN echtes SMTP anspricht. +# Stufe 3: configuration.yml im Restore-Lab gezielt fuer den Test sanitizen. +# Wir entfernen produktive Top-Level-Bloecke, die im Test andere Backends +# brauchen, und haengen danach Test-Definitionen an. So verlassen wir uns +# nicht darauf, dass ein Overlay alte Map-Keys wie notifier.smtp loescht. CONFIG_FILE="$RESTORE_ROOT/config/configuration.yml" +TEST_CONFIG_FILE="$RESTORE_ROOT/config/configuration.restoretest.yml" if [ ! -f "$CONFIG_FILE" ]; then echo "configuration.yml missing in restored config dir" >&2 exit 1 @@ -122,13 +124,20 @@ fi # Sichere Originalkopie fuer Diff/Diagnose cp "$CONFIG_FILE" "$CONFIG_FILE.original" -# Schreibe Drop-In fuer Test-Backends. Authelia 4.39 laedt mehrere -# Configdateien ueber wiederholte --config-Argumente; einfacher fuer Smoke -# ist ein gezielter Overlay-File, der Test-Werte vorgibt. -cat > "$RESTORE_ROOT/config/configuration.test-overlay.yml" <<'YAML' -# Test-Overlay nur fuer Restore-Smoke. Wird als zweite --config-Datei -# zusaetzlich zur restaurierten configuration.yml geladen und ueberschreibt -# externe Abhaengigkeiten. +# Entferne produktive Blocks, die der Restore-Smoke bewusst ersetzt. +awk ' + /^[A-Za-z_][A-Za-z0-9_]*:/ { + key = $0 + sub(/:.*/, "", key) + skip = (key == "storage" || key == "notifier" || key == "session" || key == "identity_validation" || key == "jwt_secret") + } + !skip { print } +' "$CONFIG_FILE" > "$TEST_CONFIG_FILE" + +cat >> "$TEST_CONFIG_FILE" <<'YAML' + +# Restore-Smoke-Test-Backends. Produktive externe Abhaengigkeiten sind oben +# entfernt und werden hier mit isolierten Test-Werten ersetzt. storage: postgres: @@ -146,8 +155,8 @@ session: cookies: - name: authelia_session_restoretest domain: kaleschke.info - authelia_url: http://127.0.0.1:19091 - default_redirection_url: http://127.0.0.1:19091 + authelia_url: https://auth.kaleschke.info + default_redirection_url: https://glance.kaleschke.info expiration: 1h inactivity: 5m @@ -192,7 +201,7 @@ if [ "$dump_available" -eq 1 ]; then dump_status="restored" fi -# Stufe 6: config validate im Container-Kontext, gegen restauriertes + overlay +# Stufe 6: config validate im Container-Kontext, gegen sanitizte Test-Config validate_status="ok" if ! docker run --rm \ -e AUTHELIA_JWT_SECRET=restoretest-authelia-jwt-secret-placeholder-32bytes \ @@ -202,16 +211,15 @@ if ! docker run --rm \ -e AUTHELIA_NOTIFIER_SMTP_PASSWORD=restoretest-authelia-smtp-placeholder \ -v "$RESTORE_ROOT/config:/config" \ authelia/authelia:4.39.20@sha256:1b363e9279e742397966333f364e0876ae02bf5c876de73e83af6d48c57ff51b \ - authelia config validate --config /config/configuration.yml --config /config/configuration.test-overlay.yml \ + authelia config validate --config /config/configuration.restoretest.yml \ >/tmp/authelia-validate.log 2>&1; then validate_status="failed" cat /tmp/authelia-validate.log >&2 exit 1 fi -# Stufe 7: Authelia-Container starten. Das Compose setzt wiederholte -# --config-Argumente, sodass das Test-Overlay zusaetzlich geladen wird; die -# zweite Datei gewinnt bei Konflikten und ersetzt storage/notifier/session. +# Stufe 7: Authelia-Container starten. Das Compose nutzt die sanitizte +# configuration.restoretest.yml mit isolierten Test-Backends. docker compose -f "$COMPOSE_FILE" up -d restoretest-authelia >/dev/null http_status="" @@ -248,7 +256,7 @@ write_report "$REPORT_FILE" <