#!/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 "
:" 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