diff --git a/fileflows/guard/README.md b/fileflows/guard/README.md deleted file mode 100644 index fd209bd..0000000 --- a/fileflows/guard/README.md +++ /dev/null @@ -1,87 +0,0 @@ -# FileFlows ApiKey Guard - -## Problem - -Die FileFlows-API liefert `ApiKey`-Felder in Flow-Parts beim `GET` grundsätzlich -als Literal `[REDACTED]` aus. Wird ein Flow danach gespeichert — aus der Web-UI -oder über einen `GET → PUT`-Roundtrip (Scripts, Automationen) — landet dieser -Platzhalter in der Datenbank. - -Folge: die Nodes `Sonarr - Trigger Manual Import` und -`Radarr - Trigger Manual Import` authentisieren sich mit `[REDACTED]`, die Arr -antwortet **401**, der Node bricht **still** ab. - -Fehlerbild in der Kette: - -``` -SABnzbd (movetdarr.sh) → FileFlows → Arr Manual Import - ↑ 401, still -``` - -- n8n Media-Handoff bleibt auf `processing` stehen -- `movetdarr.sh` pollt den Handoff-Lease weiter → SAB-Job hängt in der Queue - bis zum 24-h-Timeout -- Symptom beim Nutzer: "hängt seit Stunden in der Queue" - -**Ein einziger UI-Save zerschießt alle vier Keys gleichzeitig**, weil der GET -alle vier als `[REDACTED]` ausliefert (verifiziert per Negativtest: 1 Key -sabotiert → 4 Keys in der DB defekt). - -## Lösung - -`ff-apikey-guard.sh` prüft alle Flows in der FileFlows-SQLite auf ApiKeys mit -Länge != 32 und schreibt die echten Keys via Butler-Proxy -(`PUT /fileflows/api/flow`) zurück. - -Keys kommen aus einer lokalen Map, nie aus Git. - -## Deployment (tdarr, 10.2.1.104) - -```bash -sudo install -m 750 fileflows/guard/ff-apikey-guard.sh \ - /app-config/ff-guard/ff-apikey-guard.sh - -# Butler-Token -printf '%s' '' | sudo tee /app-config/ff-guard/butler.token -sudo chmod 600 /app-config/ff-guard/butler.token - -# Key-Map: " " pro Zeile, Keys aus den Arr-config.xml auf 10.2.1.100 -# 8989 sonarrUHD / 8990 sonarrFHD / 7878 radarrUHD / 7879 radarrFHD -sudo chmod 600 /app-config/ff-guard/arr-keys.map -``` - -Läuft als systemd-Timer alle 15 Minuten (`cron` ist auf tdarr inaktiv): - -``` -/etc/systemd/system/ff-apikey-guard.service Type=oneshot -/etc/systemd/system/ff-apikey-guard.timer OnUnitActiveSec=15min -``` - -```bash -sudo systemctl enable --now ff-apikey-guard.timer -``` - -## Betrieb - -```bash -# Log -sudo tail /app-config/ff-guard/guard.log - -# Manuell prüfen/reparieren -sudo systemctl start ff-apikey-guard.service - -# Timer-Status -systemctl list-timers ff-apikey-guard.timer -``` - -Logzeilen (Datum TT.MM.JJJJ): - -- `OK: alle Flow-ApiKeys 32 Zeichen` — nichts zu tun -- `WARNUNG: defekte ApiKeys in Flow — repariere` -- `Flow repariert: N Key(s) zurueckgeschrieben (HTTP 200)` - -## Nach einem UI-Save immer prüfen - -Wer einen Flow in der FileFlows-UI speichert, sollte danach den Guard anstoßen -oder maximal 15 Minuten auf den Timer warten. Vorher schlagen alle -Arr-Importe still fehl. diff --git a/fileflows/guard/ff-apikey-guard.sh b/fileflows/guard/ff-apikey-guard.sh deleted file mode 100755 index 0b38dd6..0000000 --- a/fileflows/guard/ff-apikey-guard.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash -# ff-apikey-guard.sh — repariert kaputte Arr-ApiKeys in FileFlows-Flows -# -# URSACHE: Die FileFlows-API liefert ApiKey-Felder im GET als "[REDACTED]". -# Wird ein Flow aus der Web-UI (oder per GET->PUT-Roundtrip) gespeichert, -# landet dieser Platzhalter in der DB. Die "Trigger Manual Import"-Nodes -# schlagen dann still fehl (Arr antwortet 401), der n8n-Handoff bleibt auf -# "processing" und der SAB-Job haengt bis zum 24h-Timeout in der Queue. -# -# Dieses Skript erkennt ApiKeys != 32 Zeichen und schreibt die echten Keys -# aus /app-config/ff-guard/arr-keys.map zurueck (Format: " "). -set -u - -BUTLER="${BUTLER:-http://10.5.85.2:8888}" -GUARD_DIR="${GUARD_DIR:-/app-config/ff-guard}" -TOKEN_FILE="$GUARD_DIR/butler.token" -KEYMAP="$GUARD_DIR/arr-keys.map" -LOG="$GUARD_DIR/guard.log" -DB="${DB:-/app-config/fileflows-data/Data/FileFlows.sqlite}" - -mkdir -p "$GUARD_DIR" -log() { echo "$(date '+%d.%m.%Y %H:%M:%S'): $1" >> "$LOG"; } - -for f in "$TOKEN_FILE" "$KEYMAP"; do - [ -r "$f" ] || { log "FEHLER: Datei fehlt oder nicht lesbar: $f"; exit 1; } -done -[ -r "$DB" ] || { log "FEHLER: DB nicht lesbar: $DB"; exit 1; } - -TOKEN="$(tr -d '\n\r' < "$TOKEN_FILE")" - -# Flows mit defekten Keys ermitteln -FLOWUIDS="$(python3 - "$DB" <<'PY' -import sqlite3, json, sys -con = sqlite3.connect("file:%s?mode=ro" % sys.argv[1], uri=True) -for uid, name, typ, d in con.execute( - "select Uid,Name,Type,Data from DbObject where Type like '%Flow%'"): - try: - o = json.loads(d) - except Exception: - continue - for p in o.get("Parts", []): - k = (p.get("Model") or {}).get("ApiKey") - if k is not None and len(str(k)) != 32: - print(uid) - break -PY -)" - -if [ -z "$FLOWUIDS" ]; then - log "OK: alle Flow-ApiKeys 32 Zeichen" - exit 0 -fi - -RC=0 -for uid in $FLOWUIDS; do - log "WARNUNG: defekte ApiKeys in Flow $uid — repariere" - OUT="$(mktemp)"; PATCHED="$(mktemp)" - - if ! curl -sf -m 60 -H "Authorization: Bearer $TOKEN" \ - "$BUTLER/fileflows/api/flow/$uid" -o "$OUT"; then - log "FEHLER: GET flow $uid fehlgeschlagen" - rm -f "$OUT" "$PATCHED"; RC=1; continue - fi - - CHANGED="$(python3 - "$OUT" "$KEYMAP" "$PATCHED" <<'PY' -import json, sys -flow = json.load(open(sys.argv[1])) -keys = {} -for line in open(sys.argv[2]): - parts = line.split() - if len(parts) == 2 and len(parts[1]) == 32: - keys[parts[0]] = parts[1] -n = 0 -for p in flow.get("Parts", []): - mod = p.get("Model") or {} - if "ApiKey" not in mod: - continue - url = str(mod.get("URL") or mod.get("ApiUrl") or "") - port = url.rstrip("/").rsplit(":", 1)[-1] - if port in keys and str(mod["ApiKey"]) != keys[port]: - mod["ApiKey"] = keys[port] - n += 1 -json.dump(flow, open(sys.argv[3], "w")) -print(n) -PY -)" - - if [ "${CHANGED:-0}" = "0" ]; then - log "WARNUNG: Flow $uid — kein Key konnte gemappt werden (Ports pruefen)" - rm -f "$OUT" "$PATCHED"; RC=1; continue - fi - - HTTP="$(curl -s -m 60 -o /dev/null -w '%{http_code}' -X PUT \ - -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \ - "$BUTLER/fileflows/api/flow" --data @"$PATCHED")" - - if [ "$HTTP" = "200" ]; then - log "Flow $uid repariert: $CHANGED Key(s) zurueckgeschrieben (HTTP 200)" - else - log "FEHLER: PUT flow $uid -> HTTP $HTTP" - RC=1 - fi - rm -f "$OUT" "$PATCHED" -done -exit $RC