F-10: automated Authelia repo<->host drift check
New services/authelia-diff.sh compares the access_control: section of the repo baseline against the live host configuration.yml. OIDC clients, identity providers, and secret values stay out of scope by design. Exit codes: 0 ok, 1 drift, 2 file missing, 3 section missing, 4 tool missing. posture-check.sh gains check_authelia_config_drift, which calls the diff script and reports drift as warning (not critical). SKIP_AUTHELIA_DRIFT=1 opts out; AUTHELIA_DIFF_SCRIPT overrides the path. WORKFLOW.md gets a dedicated "Ausnahme: Authelia configuration.yml" section analogous to the Traefik dynamic-config exception, with the mandatory repo->host merge workflow and the env-variable contract. Smoke-tested locally: identical files rc=0, ACL change rc=1 with proper unified diff, non-ACL change (session.default_redirection_url) correctly ignored. Operator follow-up: set up a read-only repo mirror at /mnt/user/services/homelab-infra/ so the check finds a current baseline. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,7 @@ In diesem Audit-Zyklus werden diese Punkte **nicht** umgesetzt. Sie sind dokumen
|
|||||||
| erledigt 2026-05-29 | Monitoring-Stack Digest-Pinning (F-07) | 9 Container in `monitoring/docker-compose.yml` per Tag@sha256 gepinnt: prometheus, alertmanager, alertmanager-ntfy-bridge (python:3.13-alpine), blackbox-exporter, loki, promtail, grafana, node-exporter, cadvisor. Digests aus dem aktuell laufenden Container ausgelesen, damit der Pin den Live-Stand reflektiert. influxdb3-core war bereits gepinnt. |
|
| erledigt 2026-05-29 | Monitoring-Stack Digest-Pinning (F-07) | 9 Container in `monitoring/docker-compose.yml` per Tag@sha256 gepinnt: prometheus, alertmanager, alertmanager-ntfy-bridge (python:3.13-alpine), blackbox-exporter, loki, promtail, grafana, node-exporter, cadvisor. Digests aus dem aktuell laufenden Container ausgelesen, damit der Pin den Live-Stand reflektiert. influxdb3-core war bereits gepinnt. |
|
||||||
| erledigt 2026-05-29 | Komodo-Bootstrap-Trockenlauf-Skript (F-09 Rest) | `ops/restore-tests/komodo-bootstrap-{compose.test.yml,test.sh,plan.md,runbook.md}` analog zum Immich-Restore-Test angelegt. Test-Compose nutzt dieselben Image-Digests wie Produktion, isoliert unter Project `restoretest-komodo`, Test-Periphery ohne docker.sock-Mount, Test-Port nur `127.0.0.1:19120`. Wegwerf-Secrets im Compose. Erster Lauf manuell durch Operator. |
|
| erledigt 2026-05-29 | Komodo-Bootstrap-Trockenlauf-Skript (F-09 Rest) | `ops/restore-tests/komodo-bootstrap-{compose.test.yml,test.sh,plan.md,runbook.md}` analog zum Immich-Restore-Test angelegt. Test-Compose nutzt dieselben Image-Digests wie Produktion, isoliert unter Project `restoretest-komodo`, Test-Periphery ohne docker.sock-Mount, Test-Port nur `127.0.0.1:19120`. Wegwerf-Secrets im Compose. Erster Lauf manuell durch Operator. |
|
||||||
| erledigt 2026-05-29 | Renovate-Bot gegen Gitea (F-12) | Live: Service-Account `renovate` (uid 2, kein Admin) angelegt, Collaborator Write auf `Micha/homelab-infra`, PAT in `/mnt/user/appdata/secrets/renovate_token.txt` (chmod 600). Cron `renovate-six-hourly` (`20 */6 * * *`) live in `/etc/cron.d/root`. Erstlauf 2026-05-29 erfolgreich: 5 PRs (mongo digest+minor, postgres digest+minor, minor-and-patch-updates gruppiert), 1 Dependency-Dashboard-Issue, 8 Branches. Komodo-Major durch packageRule deaktiviert wie erwartet. Architektur-Detail: Repo-Config in `renovate.json`, Bot-Config in `ops/renovate/bot-config.js` (Renovate liest die im Repo nur als Repo-Config, Bot-Settings dort triggern "forbidden/disabled"). |
|
| erledigt 2026-05-29 | Renovate-Bot gegen Gitea (F-12) | Live: Service-Account `renovate` (uid 2, kein Admin) angelegt, Collaborator Write auf `Micha/homelab-infra`, PAT in `/mnt/user/appdata/secrets/renovate_token.txt` (chmod 600). Cron `renovate-six-hourly` (`20 */6 * * *`) live in `/etc/cron.d/root`. Erstlauf 2026-05-29 erfolgreich: 5 PRs (mongo digest+minor, postgres digest+minor, minor-and-patch-updates gruppiert), 1 Dependency-Dashboard-Issue, 8 Branches. Komodo-Major durch packageRule deaktiviert wie erwartet. Architektur-Detail: Repo-Config in `renovate.json`, Bot-Config in `ops/renovate/bot-config.js` (Renovate liest die im Repo nur als Repo-Config, Bot-Settings dort triggern "forbidden/disabled"). |
|
||||||
|
| erledigt 2026-05-30 | Authelia Repo<->Host Drift-Check (F-10) | `services/authelia-diff.sh` vergleicht die `access_control:`-Sektion zwischen Repo-Baseline und Host-Datei (Default; per env `AUTHELIA_DIFF_SECTIONS` erweiterbar). OIDC-Clients/Identity-Provider und Secret-Werte bleiben bewusst aussen vor. Exit-Codes: 0 = ok, 1 = Drift, 2 = Datei fehlt, 3 = Sektion fehlt, 4 = Werkzeug fehlt. Posture-Check ruft das Skript als Check `authelia_config_drift` auf (`SKIP_AUTHELIA_DRIFT=1` skippt, `AUTHELIA_DIFF_SCRIPT` ueberschreibt den Pfad); Drift wird als Warning gemeldet, nicht Critical. Smoke-Test lokal: identische Files -> rc=0, ACL-Drift im Domain-Eintrag -> rc=1 mit unified diff. WORKFLOW.md hat jetzt eine eigene Pflicht-Sektion "Ausnahme: Authelia configuration.yml" analog zur Traefik-Dynamic-Sektion. Pflicht-Setup auf dem Host: Repo-Spiegel unter `/mnt/user/services/homelab-infra/`. |
|
||||||
|
|
||||||
## Sprint 7 - Off-site und 3-2-1 (offen)
|
## Sprint 7 - Off-site und 3-2-1 (offen)
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,20 @@ Dieses Dokument ist nur noch ein historischer Verlauf. Der aktuelle operative Ab
|
|||||||
|
|
||||||
## Historische Meilensteine
|
## Historische Meilensteine
|
||||||
|
|
||||||
|
### 2026-05-30 - F-10: Authelia Repo<->Host Drift-Check
|
||||||
|
|
||||||
|
Der dokumentierte "by-design"-Drift zwischen `security/authelia/configuration.yml` (Repo-Baseline) und `/mnt/user/appdata/authelia/config/configuration.yml` (Host) wird jetzt automatisch ueberwacht. Vorher: Manueller Merge auf den Host war Pflicht, aber keine Pruefung. Eine vergessene ACL-Synchronisation waere erst bei einem Login-Fehler aufgefallen.
|
||||||
|
|
||||||
|
- Neues Skript `services/authelia-diff.sh`: extrahiert die `access_control:`-Sektion aus beiden YAMLs per awk-Block-Extractor (Top-Level-Key bis zum naechsten Top-Level-Key), normalisiert Kommentar- und Leerzeilen, vergleicht via `diff -u`. Default-Sektion ist `access_control`, weil das laut F-10 der primaere Drift-Vektor ist; per env `AUTHELIA_DIFF_SECTIONS` koennen weitere Top-Level-Sektionen (`session`, `regulation`, `totp`, ...) ergaenzt werden. OIDC-Clients, Identity-Provider und Secret-Werte bleiben bewusst aussen vor.
|
||||||
|
- Exit-Code-Schema: 0 = ok, 1 = Drift (Diff auf stdout), 2 = Datei fehlt, 3 = Sektion fehlt, 4 = Werkzeug fehlt. Macht das Skript auch standalone nutzbar (`ssh kallilab "bash /mnt/user/services/homelab-infra/services/authelia-diff.sh"`).
|
||||||
|
- `services/posture-check/posture-check.sh` ruft das Skript am Ende des Checks-Blocks auf (`check_authelia_config_drift`). Drift wird als **Warning** gemeldet, nicht Critical, weil die produktive Authelia trotz Drift weiter laeuft und die ACL fuer schon angemeldete Sessions weiter wirkt. Skip-Mechanismus: `SKIP_AUTHELIA_DRIFT=1`. Pfad-Override: `AUTHELIA_DIFF_SCRIPT`.
|
||||||
|
- Pflicht-Setup auf dem Host: Repo-Spiegel unter `/mnt/user/services/homelab-infra/` als read-only-Clone von Gitea `Micha/homelab-infra` mit regelmaessigem `git pull --ff-only`. Default-Pfade des Skripts setzen das voraus. Ohne Repo-Spiegel meldet der Check Warning, weil die Baseline-Datei fehlt - keine stille Inaktivierung.
|
||||||
|
- Lokaler Smoke-Test 2026-05-30 erfolgreich: identische Files -> rc=0; ACL-Drift im Domain-Eintrag `scrutiny.kaleschke.info -> scrutiny-renamed.kaleschke.info` -> rc=1 mit unified diff, ACL-Block korrekt extrahiert, Kommentar- und Leerzeilen rausgefiltert. False-Positive auf `session.default_redirection_url`-Aenderung korrekt vermieden (gehoert nicht zu `access_control`).
|
||||||
|
- `docs/WORKFLOW.md` hat jetzt eine eigene Sektion "Ausnahme: Authelia configuration.yml" analog zur Traefik-Dynamic-Sektion. Pflicht-Workflow: 1. Repo-Aenderung + Commit + Push, 2. manueller Merge in die Host-Datei mit Erhalt der OIDC-Sektionen, 3. `docker restart authelia` + Login-Smoke-Test, 4. `services/authelia-diff.sh` muss `exit 0` liefern.
|
||||||
|
- `docs/REPO_MAP.md` und `docs/SERVICE_CATALOG.md` zeigen das Skript und den neuen Posture-Check-Eintrag.
|
||||||
|
|
||||||
|
Operator-Folgeschritt (klein, nicht heute): Repo-Spiegel `/mnt/user/services/homelab-infra/` auf dem Host einrichten und in den vorhandenen `gitea-bundle-mirror-6h`-Plan oder einen eigenen 6h-Cron einbinden, damit das Skript einen aktuellen Vergleichsstand findet.
|
||||||
|
|
||||||
### 2026-05-29 - Stack-Hygiene Sprint: Healthchecks, Monitoring-Digests, Komodo-Bootstrap-Skript, Renovate-Vorbereitung
|
### 2026-05-29 - Stack-Hygiene Sprint: Healthchecks, Monitoring-Digests, Komodo-Bootstrap-Skript, Renovate-Vorbereitung
|
||||||
|
|
||||||
Vier Audit-Punkte am Stueck abgearbeitet. Pro Block: Live-Verifikation am Host, Doku im Repo.
|
Vier Audit-Punkte am Stueck abgearbeitet. Pro Block: Live-Verifikation am Host, Doku im Repo.
|
||||||
|
|||||||
+2
-1
@@ -66,9 +66,10 @@ Secret-Werte werden hier nicht dokumentiert. Aufgefuehrt werden nur Variablennam
|
|||||||
| `monitoring/grafana/provisioning/*` | Grafana Datasource-/Dashboard-Provisioning fuer Prometheus und Loki |
|
| `monitoring/grafana/provisioning/*` | Grafana Datasource-/Dashboard-Provisioning fuer Prometheus und Loki |
|
||||||
| `ops/glance/config/glance.yml` | Glance Dashboard-Konfiguration fuer Homelab-Monitore, Internet-/DNS-/VPN-Widgets, Community-Widgets, Docker-Containergruppen, Zeitfortschritt, Host-Snapshot, Bookmarks und zweite Infrastruktur-Seite |
|
| `ops/glance/config/glance.yml` | Glance Dashboard-Konfiguration fuer Homelab-Monitore, Internet-/DNS-/VPN-Widgets, Community-Widgets, Docker-Containergruppen, Zeitfortschritt, Host-Snapshot, Bookmarks und zweite Infrastruktur-Seite |
|
||||||
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, SQLite-Container-Dumps und Komodo Mongo |
|
| `ops/borg-ui/scripts/pre-backup-dumps.sh` | Host-seitiges Dump-Skript fuer PostgreSQL, SQLite-Container-Dumps und Komodo Mongo |
|
||||||
| `services/posture-check/posture-check.sh` | Host-seitiger Posture-Check fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand und ntfy-Alarmierung |
|
| `services/posture-check/posture-check.sh` | Host-seitiger Posture-Check fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand, Authelia-Repo<->Host-Drift und ntfy-Alarmierung |
|
||||||
| `services/posture-check/docker-critical-events.sh` | Host-seitiger Docker-Event-Watcher fuer kritische ntfy-Alarme |
|
| `services/posture-check/docker-critical-events.sh` | Host-seitiger Docker-Event-Watcher fuer kritische ntfy-Alarme |
|
||||||
| `services/posture-check/posture_check.sh` | Kompatibilitaets-Wrapper fuer die historische Schreibweise aus `STORAGE_LAYOUT.draft.md` |
|
| `services/posture-check/posture_check.sh` | Kompatibilitaets-Wrapper fuer die historische Schreibweise aus `STORAGE_LAYOUT.draft.md` |
|
||||||
|
| `services/authelia-diff.sh` | Vergleicht `access_control:`-Sektion zwischen Repo-Baseline und Host-Datei; wird vom Posture-Check als Check `authelia_config_drift` aufgerufen |
|
||||||
| `ops/hermes-agent/config/hermes/config.yaml` | Hermes Agent Konfiguration mit Env-Platzhaltern |
|
| `ops/hermes-agent/config/hermes/config.yaml` | Hermes Agent Konfiguration mit Env-Platzhaltern |
|
||||||
| `ops/hermes-agent/hermes.env.example` | Beispiel fuer Hermes `.env`; echte Datei liegt auf Host-Appdata |
|
| `ops/hermes-agent/hermes.env.example` | Beispiel fuer Hermes `.env`; echte Datei liegt auf Host-Appdata |
|
||||||
| `ops/hermes-agent/stack.env.example` | Beispiel fuer Hermes Stack-ENV; echte `stack.env` bleibt host-/komodoseitig und ist per `.gitignore` ausgeschlossen |
|
| `ops/hermes-agent/stack.env.example` | Beispiel fuer Hermes Stack-ENV; echte `stack.env` bleibt host-/komodoseitig und ist per `.gitignore` ausgeschlossen |
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Secret-Werte sind nicht enthalten. Es werden nur Secret-Namen, Env-Key-Namen und
|
|||||||
|
|
||||||
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
| Service | Zweck | Autoritativer Pfad | URL / Zugang | Abhaengigkeiten | Datenpfade | Backup / Restore | Traefik | Besonderheiten / TODOs |
|
||||||
|---|---|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|---|---|
|
||||||
| `posture-check` | Host-Posture-Audit fuer Filesystem, Mover-Drift, NVMe-SMART und Fuellstand | `services/posture-check/posture-check.sh` | Unraid User-Script / Cron / Borg Pre-Hook | `findmnt`, `df`, `nvme`, optional `curl` fuer ntfy | `/mnt/user/services/posture-check/last.json` | Repo-Skript + letzter JSON-Status | nein | Muss auf dem Unraid-Host bei Boot, stuendlich und vor Borg laufen; Disk1-NTFS ist nach Disk1 Phase 2 nicht mehr erlaubt (`ALLOW_DISK1_NTFS=0` Standard); Warning/Critical alarmieren via ntfy nur bei neuer Ursache oder nach `ALERT_REPEAT_SECONDS` |
|
| `posture-check` | Host-Posture-Audit fuer Filesystem, Mover-Drift, NVMe-SMART, Fuellstand und Authelia-Repo<->Host-Drift | `services/posture-check/posture-check.sh` | Unraid User-Script / Cron / Borg Pre-Hook | `findmnt`, `df`, `nvme`, optional `curl` fuer ntfy; ruft `services/authelia-diff.sh` fuer `authelia_config_drift` auf | `/mnt/user/services/posture-check/last.json` | Repo-Skript + letzter JSON-Status | nein | Muss auf dem Unraid-Host bei Boot, stuendlich und vor Borg laufen; Disk1-NTFS ist nach Disk1 Phase 2 nicht mehr erlaubt (`ALLOW_DISK1_NTFS=0` Standard); Warning/Critical alarmieren via ntfy nur bei neuer Ursache oder nach `ALERT_REPEAT_SECONDS`. Authelia-Drift-Check braucht einen Repo-Spiegel unter `/mnt/user/services/homelab-infra/` (siehe `docs/WORKFLOW.md` Sektion "Ausnahme: Authelia configuration.yml") |
|
||||||
| `docker-critical-events` | Live-Alarmierung fuer Docker `die`/`oom`/`kill` Events | `services/posture-check/docker-critical-events.sh` | Unraid User-Script / Hintergrundprozess | Docker CLI, ntfy | `/mnt/user/services/posture-check/docker-critical-events-last.log` | Repo-Skript + letzter Event-Log | nein | Optional als Unraid User-Script `at array start` starten; sendet nach `homelab-alerts` |
|
| `docker-critical-events` | Live-Alarmierung fuer Docker `die`/`oom`/`kill` Events | `services/posture-check/docker-critical-events.sh` | Unraid User-Script / Hintergrundprozess | Docker CLI, ntfy | `/mnt/user/services/posture-check/docker-critical-events-last.log` | Repo-Skript + letzter Event-Log | nein | Optional als Unraid User-Script `at array start` starten; sendet nach `homelab-alerts` |
|
||||||
|
|
||||||
## Backup- und Restore-Hinweise
|
## Backup- und Restore-Hinweise
|
||||||
|
|||||||
@@ -269,6 +269,42 @@ Diese Ausnahme bleibt bewusst bestehen. Der File-Provider wird weiterhin nur fue
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Ausnahme: Authelia configuration.yml
|
||||||
|
|
||||||
|
> **Diese Datei wird von Komodo nicht automatisch deployed.**
|
||||||
|
|
||||||
|
`security/authelia/configuration.yml` ist die Repo-Baseline fuer nicht geheime Einstellungen (Access-Control, Session, Storage-Struktur, Notifier, TOTP). Die produktive Host-Datei darf zusaetzlich OIDC-Clients und hostseitige Identity-Provider-Konfiguration enthalten. Secret-Werte und die User-Datenbank bleiben grundsaetzlich ausserhalb von Git.
|
||||||
|
|
||||||
|
| Git-Pfad | Host-Pfad (NAS) |
|
||||||
|
|---|---|
|
||||||
|
| `security/authelia/configuration.yml` | `/mnt/user/appdata/authelia/config/configuration.yml` |
|
||||||
|
|
||||||
|
### Pflicht-Workflow bei Aenderungen an `configuration.yml`
|
||||||
|
|
||||||
|
1. Datei im Git-Repo (`security/authelia/`) aendern.
|
||||||
|
2. Commit + Push.
|
||||||
|
3. Aenderung manuell in die Host-Datei mergen, OIDC-/Identity-Provider-Sektionen erhalten.
|
||||||
|
4. `docker restart authelia` und Login-Smoke-Test auf einer ACL-betroffenen Domain.
|
||||||
|
5. `services/authelia-diff.sh` (Default-Aufruf) muss `exit 0` liefern.
|
||||||
|
|
||||||
|
### Automatische Drift-Erkennung
|
||||||
|
|
||||||
|
`services/authelia-diff.sh` vergleicht die `access_control:`-Sektion zwischen Repo-Baseline und Host-Datei. Der Posture-Check (`services/posture-check/posture-check.sh`) ruft das Skript als Check `authelia_config_drift` auf und meldet Drift als Warning via ntfy.
|
||||||
|
|
||||||
|
Konfigurierbare Variablen (Defaults sind das produktive Zielbild):
|
||||||
|
|
||||||
|
- `AUTHELIA_REPO_BASELINE` — Pfad zur Repo-Datei auf dem Host, Default `/mnt/user/services/homelab-infra/security/authelia/configuration.yml`
|
||||||
|
- `AUTHELIA_HOST_CONFIG` — Pfad zur produktiven Host-Datei, Default `/mnt/user/appdata/authelia/config/configuration.yml`
|
||||||
|
- `AUTHELIA_DIFF_SECTIONS` — Komma-Liste der zu vergleichenden Top-Level-Sektionen, Default `access_control`
|
||||||
|
- `AUTHELIA_DIFF_SCRIPT` — Pfad zum Diff-Skript fuer den Posture-Check, Default `/mnt/user/services/homelab-infra/services/authelia-diff.sh`
|
||||||
|
- `SKIP_AUTHELIA_DRIFT=1` — Check im Posture-Check ueberspringen
|
||||||
|
|
||||||
|
Pflicht-Setup auf dem Host: Repo-Spiegel unter `/mnt/user/services/homelab-infra/` (Read-only-Clone von Gitea `Micha/homelab-infra`, regelmaessig `git pull --ff-only`). Ohne Repo-Spiegel meldet der Check Warning, weil die Baseline-Datei fehlt — Critical wird der Check bewusst nicht.
|
||||||
|
|
||||||
|
> **Merksatz:** Push allein reicht hier nicht. Ohne den manuellen Merge ins Host-Configfile wirkt die Aenderung nicht, und der Drift-Check wuerde Warning melden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Secrets-Regeln
|
## Secrets-Regeln
|
||||||
|
|
||||||
- Secrets liegen niemals im Repository
|
- Secrets liegen niemals im Repository
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Vergleicht die Repo-Baseline der Authelia-Konfiguration gegen die produktive
|
||||||
|
# Host-Datei. Bewusst nur fuer Sektionen, die laut Repo-Konvention auf Host
|
||||||
|
# und Repo identisch sein muessen (Default: access_control). OIDC-Clients,
|
||||||
|
# identity_providers und Secret-Werte bleiben hostseitig und werden nicht
|
||||||
|
# verglichen.
|
||||||
|
#
|
||||||
|
# Aufruf-Defaults siehe Variablen unten. Aufruf typischerweise:
|
||||||
|
# bash services/authelia-diff.sh
|
||||||
|
#
|
||||||
|
# Exit-Codes:
|
||||||
|
# 0 alle verglichenen Sektionen identisch
|
||||||
|
# 1 Drift festgestellt (Diff wird auf stdout ausgegeben)
|
||||||
|
# 2 Repo-Baseline oder Host-Datei fehlt
|
||||||
|
# 3 Sektion in mindestens einer Datei nicht gefunden
|
||||||
|
# 4 internes Werkzeug fehlt (awk/diff)
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
AUTHELIA_REPO_BASELINE="${AUTHELIA_REPO_BASELINE:-/mnt/user/services/homelab-infra/security/authelia/configuration.yml}"
|
||||||
|
AUTHELIA_HOST_CONFIG="${AUTHELIA_HOST_CONFIG:-/mnt/user/appdata/authelia/config/configuration.yml}"
|
||||||
|
AUTHELIA_DIFF_SECTIONS="${AUTHELIA_DIFF_SECTIONS:-access_control}"
|
||||||
|
|
||||||
|
for cmd in awk diff; do
|
||||||
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||||
|
echo "authelia-diff: missing required command '$cmd'" >&2
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! -f "$AUTHELIA_REPO_BASELINE" ]; then
|
||||||
|
echo "authelia-diff: repo baseline not found: $AUTHELIA_REPO_BASELINE" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [ ! -f "$AUTHELIA_HOST_CONFIG" ]; then
|
||||||
|
echo "authelia-diff: host config not found: $AUTHELIA_HOST_CONFIG" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extrahiert einen Top-Level-Block aus einer YAML-Datei.
|
||||||
|
# Block-Anfang: Zeile, die mit "<section>:" beginnt (kein Whitespace davor).
|
||||||
|
# Block-Ende: naechste Top-Level-Key-Zeile (`^[A-Za-z_][A-Za-z0-9_]*:`).
|
||||||
|
# Eingaberauschen wird entfernt: reine Kommentarzeilen, trailing whitespace,
|
||||||
|
# Leerzeilen.
|
||||||
|
extract_section() {
|
||||||
|
local file="$1"
|
||||||
|
local section="$2"
|
||||||
|
awk -v section="$section" '
|
||||||
|
BEGIN { inside = 0; found = 0 }
|
||||||
|
{
|
||||||
|
line = $0
|
||||||
|
sub(/[[:space:]]+$/, "", line)
|
||||||
|
}
|
||||||
|
# Top-Level-Key entdeckt
|
||||||
|
/^[A-Za-z_][A-Za-z0-9_]*:/ {
|
||||||
|
key = line
|
||||||
|
sub(/:.*$/, "", key)
|
||||||
|
if (key == section) {
|
||||||
|
inside = 1
|
||||||
|
found = 1
|
||||||
|
print line
|
||||||
|
next
|
||||||
|
} else if (inside == 1) {
|
||||||
|
inside = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inside == 1 {
|
||||||
|
# Kommentar- und Leerzeilen ignorieren
|
||||||
|
if (line ~ /^[[:space:]]*#/) next
|
||||||
|
if (line ~ /^[[:space:]]*$/) next
|
||||||
|
print line
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (!found) exit 10
|
||||||
|
}
|
||||||
|
' "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpdir="$(mktemp -d -t authelia-diff.XXXXXX)"
|
||||||
|
trap 'rm -rf "$tmpdir"' EXIT
|
||||||
|
|
||||||
|
overall_status=0
|
||||||
|
diff_output=""
|
||||||
|
missing_sections=""
|
||||||
|
|
||||||
|
IFS=',' read -r -a sections <<< "$AUTHELIA_DIFF_SECTIONS"
|
||||||
|
for section in "${sections[@]}"; do
|
||||||
|
section="${section// /}"
|
||||||
|
[ -z "$section" ] && continue
|
||||||
|
|
||||||
|
repo_file="$tmpdir/repo.$section"
|
||||||
|
host_file="$tmpdir/host.$section"
|
||||||
|
|
||||||
|
if ! extract_section "$AUTHELIA_REPO_BASELINE" "$section" > "$repo_file" 2>/dev/null; then
|
||||||
|
missing_sections="${missing_sections}${missing_sections:+, }$section (repo)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! extract_section "$AUTHELIA_HOST_CONFIG" "$section" > "$host_file" 2>/dev/null; then
|
||||||
|
missing_sections="${missing_sections}${missing_sections:+, }$section (host)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! diff_chunk="$(diff -u \
|
||||||
|
--label "repo:$section" "$repo_file" \
|
||||||
|
--label "host:$section" "$host_file")"; then
|
||||||
|
overall_status=1
|
||||||
|
diff_output="${diff_output}${diff_chunk}"$'\n'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$missing_sections" ] && [ "$overall_status" -eq 0 ]; then
|
||||||
|
echo "authelia-diff: sections missing: $missing_sections" >&2
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$overall_status" -ne 0 ]; then
|
||||||
|
printf '%s' "$diff_output"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -10,6 +10,8 @@ TMP_DIR="${TMP_DIR:-/tmp/kallilab-posture-check}"
|
|||||||
ALLOW_DISK1_NTFS="${ALLOW_DISK1_NTFS:-0}"
|
ALLOW_DISK1_NTFS="${ALLOW_DISK1_NTFS:-0}"
|
||||||
ALERT_STATE_PATH="${ALERT_STATE_PATH:-/mnt/user/services/posture-check/last-alert.state}"
|
ALERT_STATE_PATH="${ALERT_STATE_PATH:-/mnt/user/services/posture-check/last-alert.state}"
|
||||||
ALERT_REPEAT_SECONDS="${ALERT_REPEAT_SECONDS:-86400}"
|
ALERT_REPEAT_SECONDS="${ALERT_REPEAT_SECONDS:-86400}"
|
||||||
|
SKIP_AUTHELIA_DRIFT="${SKIP_AUTHELIA_DRIFT:-0}"
|
||||||
|
AUTHELIA_DIFF_SCRIPT="${AUTHELIA_DIFF_SCRIPT:-/mnt/user/services/homelab-infra/services/authelia-diff.sh}"
|
||||||
|
|
||||||
mkdir -p "$TMP_DIR"
|
mkdir -p "$TMP_DIR"
|
||||||
RESULTS_FILE="$TMP_DIR/results.$$"
|
RESULTS_FILE="$TMP_DIR/results.$$"
|
||||||
@@ -219,6 +221,41 @@ check_nvme_smart() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_authelia_config_drift() {
|
||||||
|
if [ "$SKIP_AUTHELIA_DRIFT" = "1" ]; then
|
||||||
|
add_result "ok" "authelia_config_drift" "Authelia drift check skipped via SKIP_AUTHELIA_DRIFT=1"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$AUTHELIA_DIFF_SCRIPT" ] && [ ! -f "$AUTHELIA_DIFF_SCRIPT" ]; then
|
||||||
|
add_result "warning" "authelia_config_drift" "Authelia diff script missing: $AUTHELIA_DIFF_SCRIPT"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local output
|
||||||
|
local rc
|
||||||
|
output="$(bash "$AUTHELIA_DIFF_SCRIPT" 2>&1)"
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
case "$rc" in
|
||||||
|
0)
|
||||||
|
add_result "ok" "authelia_config_drift" "Authelia repo baseline matches host config (access_control)"
|
||||||
|
;;
|
||||||
|
1)
|
||||||
|
add_result "warning" "authelia_config_drift" "Authelia repo<->host drift in access_control; run authelia-diff.sh for details"
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
add_result "warning" "authelia_config_drift" "Authelia diff aborted: $output"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
add_result "warning" "authelia_config_drift" "Authelia diff: section missing in repo or host: $output"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
add_result "warning" "authelia_config_drift" "Authelia diff returned unexpected rc=$rc: $output"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
send_ntfy() {
|
send_ntfy() {
|
||||||
local severity="$1"
|
local severity="$1"
|
||||||
local topic="$2"
|
local topic="$2"
|
||||||
@@ -388,6 +425,7 @@ main() {
|
|||||||
done
|
done
|
||||||
|
|
||||||
check_nvme_smart
|
check_nvme_smart
|
||||||
|
check_authelia_config_drift
|
||||||
write_json
|
write_json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user