From baf97e2d85f814c57a51e42f3edee7c3f027efe9 Mon Sep 17 00:00:00 2001 From: Christoph Emsenhuber Date: Mon, 24 Aug 2026 06:26:22 +0200 Subject: [PATCH] TP30 angelegt: Credential-Rotation als Sammel-TP, gebuendelt gegen Projektende Vier Rotationsposten (MikroTik-admin, IoT-PSK, Shelly-Geraetepasswort, CF-Access-Token) lagen als verstreute Follow-up-Zeilen herum. Der teure Teil jeder Rotation sind die Konsumenten (HA-Re-Auth x4, Nautobot-Stack- Redeploy), nicht das Setzen -- einzeln gemacht zahlt man den mehrfach. Deshalb ein Sammel-TP mit Ausloesekriterium statt Termin. - 100 Zeilen Radius-/Etappe-1-Detail aus den Follow-ups nach TP30 verschoben (nicht dupliziert), Follow-ups tragen jetzt einen Zeiger - Etappe 1 (Service-Accounts ha/nautobot) ist durch; admin ist NICHT rotiert - Stale: "nach TP17.1 sind es weniger Geraete" -- TP17.1 ist verworfen, die Geraete bleiben WLAN-Clients, die Rechnung gilt unveraendert - Handoff 08-24 + Naechster-Schritt-Block als ueberholt markiert Co-Authored-By: Claude Opus 5 --- docs/handoff-20260824-session.md | 6 + docs/teilprojekte.md | 280 +++++++++++++++++++------------ 2 files changed, 179 insertions(+), 107 deletions(-) diff --git a/docs/handoff-20260824-session.md b/docs/handoff-20260824-session.md index 8760d1d..3749df8 100644 --- a/docs/handoff-20260824-session.md +++ b/docs/handoff-20260824-session.md @@ -20,6 +20,12 @@ Fünf Commits: `d245d10`, `e8f7f80`, `0a7f2e2`, `2f18319`, `e9a5b36`. ## 🔴 Womit die nächste Session anfangen sollte +> ⚠️ **ÜBERHOLT am 2026-08-24 (User-Entscheid):** die Rotation ist **nicht** der Sessionstart. +> Sie ist zu **[TP30 — Credential-Rotation](teilprojekte.md)** geworden, einem Sammel-TP, der +> **gegen Projektende gebündelt** abgearbeitet wird — Begründung: es kommen weitere Passwörter +> hinzu, und der teure Teil sind die Konsumenten (HA-Re-Auth, Stack-Redeploy), den man nicht +> mehrfach zahlen will. **Der Inhalt unten bleibt sachlich gültig** und steht jetzt in TP30. + **Passwort-Rotation, Etappe 2.** Die Vorarbeit steht komplett, der Rest ist die einzige Sache mit echter Dringlichkeit — das `admin`-Passwort ist zweimal in ein Transkript geraten (22.08. und, durch meinen eigenen Enumerationsfehler, nochmal am 23.08.; **derselbe Wert**, da alle vier Geräte ihn teilen). diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 6bc40f3..be3da5f 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -91,10 +91,13 @@ ab jetzt bei jeder Änderung mitgezogen, nicht nur die TP-Abschnitte.)* > bleibt WLAN-Client; `s9` zurückgebaut) · ✅ **TP17.3 ERLEDIGT** (Ursache **`eco_mode`** bewiesen; > `s23` + `s26` repariert; **`eco_mode` flottenweit aus**, 22/22 außer `s24`) · > 🔜 **TP17.2 aktiviert** (Shelly-Gerätepasswort, an die PSK-Rotation gekoppelt) · -> 🔑 **Rotation des MikroTik-Admin-Passworts** — seit 08-23 bewusst **hinter** TP17.1 eingereiht. +> 🔑 **Alle Passwort-/Token-Rotationen sind seit 2026-08-24 TP30** (Sammel-TP) — **bewusst +> gebündelt gegen Projektende**, User-Entscheid. Damit ist die ältere Einreihung „hinter TP17.1" +> gegenstandslos (TP17.1 ist verworfen). **Etappe 1 — die Service-Accounts — ist durch;** +> das `admin`-Passwort selbst ist **nicht rotiert** und bleibt es bis dahin bewusst. > 📌 **Einstieg für die nächste Session: [`handoff-20260824-session.md`](handoff-20260824-session.md)** -> — Start bei der **Passwort-Rotation Etappe 2** (Nautobot + HA auf die neuen Service-Accounts -> umhängen, dann `admin` rotieren). Ältere Sitzungsvorschläge: +> — ⚠️ dessen Empfehlung „Start bei der Passwort-Rotation Etappe 2" ist durch den TP30-Entscheid +> **überholt**; der Rest der Übergabe gilt. Ältere Sitzungsvorschläge: > [`handoff-20260822-naechste-schritte.md`](handoff-20260822-naechste-schritte.md). > ✅ **`crs326-core` ist transaktionsfrei** (seit 2026-08-22, geprüft): ein gemeldeter Drift ist ab > jetzt **echt**, nicht beabsichtigt — `python3 nautobot/gc-transaktion.py status`. @@ -925,6 +928,167 @@ die Redundanzfrage oben. - **Abh.:** keine harten. Profitiert von TP25 (Abdeckung/AP-Zuordnung) und TP11 (Monitoring), wenn es dahin kommt. **Kein Blocker für irgendetwas.** + +### TP30 — Credential-Rotation (Sammel-TP) ▸ 🔜 **ANGELEGT 2026-08-24, bewusst GEBÜNDELT gegen Projektende** +> **User-Entscheid 2026-08-24:** „ich würde gerne daraus einen eigenen punkt machen. ich bin mir +> sicher, dass es noch öfters passwörter zu rotieren geben wird. das machen wir dann alles gegen +> projektende." +> +> **Warum ein eigener TP und nicht vier verstreute Follow-up-Zeilen:** die Rotationen teilen sich Werkzeug, +> Fallen und vor allem den **teuren Teil — den Konsumenten** (HA, Nautobot, MikroMCP, `~/.secrets`). +> Wer sie einzeln macht, zahlt den Re-Auth-Aufwand mehrfach. Gebündelt ist es **ein** Durchgang je +> Gerät. Deshalb steht hier die Liste, nicht der Termin. + +- **Auslösekriterium (statt Datum):** wenn die offenen TPs abgearbeitet sind bzw. Christoph das + Projekt schließt. 🔴 **Harte Ausnahme, die den Termin vorzieht:** ein *neuer* Leak, ein + fremdzugängliches Gerät oder ein Personenwechsel — dann sofort und einzeln, nicht gebündelt. + +| # | Credential | Umfang | Anlass | Vorarbeit | Preis der Rotation | +|---|---|---|---|---|---| +| 1 | **MikroTik `admin`** | core · branch · ap1 · ap2 (**ein** geteilter Wert) | 🔴 **zweimal in ein Transkript geraten** (2026-08-22 via `sshpass -p`; 2026-08-23 durch einen Enumerationsfehler) | ✅ **Etappe 1 durch** (s.u.) | nach Etappe 2 nur noch `~/.secrets/credentials.env` + `~/.claude.json` + MikroMCP-Neustart | +| 2 | **IoT-WLAN-PSK** (`sec-iot`) | `dirtyvader-iot`, 26 Clients | steht **im Klartext** im TP17-Text ⇒ auch in der **Git-Historie**; Redigieren holt ihn dort nicht raus | Hebel `multi-passphrase` am Core verifiziert vorhanden, Tabelle leer | 23 Shellys per Skript + **3 von Hand** (`.249` NSPanel Pro, `.244` Nuki Bridge, `.227` SwitchBot) | +| 3 | **Shelly-Gerätepasswort** | 23 Shellys | Härtung (bisher **keine** Auth auf den Geräten) | ✅ Werkzeug fertig (`migrate.py cmd_auth` + Digest-Fallback) | **je Gerät ein HA-Re-Auth-Flow** — das ist der Aufwand, nicht `SetAuth` | +| 4 | **CF-Access-Service-Token** (`CF_API_TOKEN`) | Cloudflare-Zugang, s. TP14.4 | ⏳ **läuft am 2027-01-09 ohnehin ab** — harter Termin, unabhängig vom Projektende | Runbook liegt (`tp14.4-cf-access-token-runbook.md`) | Token neu ausstellen + `~/.secrets` nachziehen; **account-owned**, anderer verify-Endpoint | + +> ℹ️ **#3 ist TP17.2 und bleibt dort inhaltlich zu Hause** — hier steht es, weil es denselben +> Geräte-Durchgang wie #2 benutzt (ein Reboot statt zwei), nicht als Duplikat. + +#### Detail — Radius, Etappe 1 und Etappe 2 (am 2026-08-24 aus den Follow-ups hierher gezogen) + +**Vorgeschichte des Entscheids** (Stand bis 2026-08-23, User: „machen wir, aber erst später"): +⏭️ ~~**Nachgelagert seit 2026-08-23: erst TP17.1, dann rotieren.**~~ +**Revidiert noch am selben Tag (User): beides läuft PARALLEL.** Der Passphrase-Override je MAC +(s.u.) macht den Flag-Day überflüssig, damit war die Reihenfolge nie technisch nötig — nur +ökonomisch. Regel für die Parallelität: **ein Gerät, das ohnehin auf Thread/Zigbee wandert, +bekommt den neuen PSK gar nicht**, sondern nur einen Übergangs-Eintrag in der `access-list`. +⚠️ Der Entscheid betrifft **beide** Passwörter: der **IoT-WLAN-PSK** steht im Klartext im +TP17-Text ([Archiv](teilprojekte-archiv.md#tp17)) und damit auch in der Git-Historie — **bleibt +auf User-Entscheid 2026-08-23 vorerst unverändert**, weil Redigieren ihn nicht aus der Historie +holt und Rotieren heute ~22 Shellys kostet. ~~Nach TP17.1 sind es deutlich weniger.~~ +🔴 **Hinfällig seit 2026-08-23: TP17.1 ist verworfen** — die Geräte bleiben WLAN-Clients, es +werden also *nicht* weniger. Die Rechnung „~23 Shellys + 3 Fremdgeräte" gilt unverändert. Anlass: das Core-Passwort ist bei einer Debug-Ausgabe im Klartext in +ein Sitzungstranskript geraten. Ursache war `sshpass -p`, das es in die **Kommandozeile** +schreibt — sichtbar in `ps` und in jedem argv-Trace. +#### 🔑 Radius-Befund 2026-08-23: das Admin-Konto teilen sich FÜNF Konsumenten +Vor dem Rotieren erhoben — das ist deutlich mehr als „vier Geräte + eine Datei": + +| Halter | Nachziehen | +|---|---| +| `~/.secrets/credentials.env` | Datei | +| `~/.claude.json` (MikroMCP-Env, `ROUTER_*`/`CRS326_*`) | JSON + MCP-Neustart | +| **Nautobot-Stack** `NAUTOBOT_ROUTEROS_USERNAME/PASSWORD` | Stack-Datei + **Portainer-Redeploy auf der DS923** | +| **HA: VIER `mikrotik`-Integrationen** (`.99.1/.2/.11/.12`, 40 `device_tracker`) | 🔴 **`supports_reconfigure: false` — NICHT skriptbar**, 4× Re-Auth von Hand | +| Repo-Skripte (`routeros/*.py`, `nautobot/*.py`, `docs/tp*.sh`) | ziehen aus `~/.secrets` → automatisch | + +⇒ **User-Entscheid 2026-08-23: Konten trennen statt ein Passwort teilen.** Nicht das Rotieren ist +das Problem, sondern dass ein einziges `admin` von fünf Stellen benutzt wird — jede Rotation kostet +sonst wieder vier Re-Auths und einen Stack-Redeploy. + +#### ✅ Etappe 1 DURCH (2026-08-23): dedizierte Service-Accounts auf allen vier Geräten +Rein **additiv**, kein laufender Dienst berührt. Vorher existierte **nur** `admin` (Gruppe `full`). + +| Gruppe | Policy | User | Zweck | +|---|---|---|---| +| `grp-ha` | `read,api,rest-api,test` | `ha` | HA-Mikrotik-Integration, **lesend** über API 8728 | +| `grp-nautobot` | `ssh,read,write,test,sensitive` | `nautobot` | Golden Config über SSH/Netmiko (Backup **und** Deploy) | + +Passwörter: `MIKROTIK_HA_PASS` / `MIKROTIK_NAUTOBOT_PASS` in `~/.secrets/credentials.env` +(32 Zeichen, je Dienst eigen, geräteübergreifend gleich). +🔒 **Angelegt über ein Skript, das die Werte aus der Datei liest** — bewusst *nicht* über +`manage_user`, dessen `password`-Parameter im Sitzungstranskript landen würde. + +**Abnahme, auf allen vier Geräten geprüft:** +- `ha` liest (`identity`, `dhcp-lease` — am Core 59 Einträge, genau was das Device-Tracking braucht), + **Schreibversuch wird abgewiesen**. +- `nautobot` meldet sich per SSH an und exportiert; **kein REST** (bewusst kein `rest-api` in der Policy). +- 🎯 **Der Export von `nautobot` ist byte-identisch zu dem von `admin`** (391/56/87/87 Zeilen je Gerät) + ⇒ **die GC-Compliance driftet beim Umstellen nicht.** Das war das Hauptrisiko dieser Etappe. +- `/user` wird von **keiner** ComplianceRule abgedeckt ⇒ die neuen Konten erzeugen selbst keinen Drift. + +#### ⏭️ Etappe 2 offen — die Konsumenten umhängen, DANN `admin` rotieren +1. **Nautobot** auf `nautobot` umstellen (Stack-Env + Portainer-Redeploy), GC-Backup-Lauf als Abnahme. +2. **HA**: die vier `mikrotik`-Einträge auf den `ha`-User bringen. ⚠️ Reconfigure ist nicht skriptbar; + Entfernen-und-neu-Anlegen **wäre** skriptbar, riskiert aber die 40 `device_tracker`-Entity-IDs + (sie leiten sich aus der MAC ab, kämen also gleich zurück — **aber erst nachdem** die alten + Registry-Einträge weg sind, sonst hängt HA ein `_2` an; dieselbe Falle wie beim Shelly-Rename). +3. **Erst danach** `admin` rotieren — dann berührt es nur noch `~/.secrets` + `~/.claude.json`. + +🔴 **Eigener Fehler, protokolliert:** beim Erheben des Radius hat ein `json.dumps`-Aufruf über +`~/.claude.json` das **ap1-Passwort im Klartext ins Transkript geschrieben**. Da alle vier Geräte +dasselbe `admin`-Passwort teilen, ist es **derselbe Wert, der am 2026-08-22 bereits verbrannt ist** — +keine neue Expositionsklasse, aber ein zweiter Beleg dafür, dass die Rotation fällig ist. +**Merkregel: Secrets-Enumeration gibt nur Schlüsselnamen aus, nie Werte** — auch nicht abgeschnitten. + +✅ **Vorbedingung erfüllt, geprüft 2026-08-23:** alle vier +Skripte laufen auf `sshpass -e` (`tp6-marker/server.py`, `tp6-monitor-core.sh`, +`tp25-walk-messung.sh`, `tp25-pin-s22.sh`) — die frühere Notiz, zwei davon hätten die Schwäche +noch, war veraltet. Übrig blieb nur **`CLAUDE.md`, das `sshpass -p` weiterhin aktiv als Reboot-Weg +empfahl** — am 2026-08-23 auf `sshpass -e` korrigiert. **Damit ist die Rotation ohne Rückfallgefahr +fahrbar.** +Weg: `manage_user set-password` (⚠️ `/user set*` ist per Deny-Policy blockiert), danach +`~/.secrets/credentials.env` (`ROUTER_*_PASS`/`CRS326_*_PASS`) und `~/.claude.json` nachziehen. +Es ist **ein** Passwort für alle vier Geräte — die „Überlebensversicherung" aus CLAUDE.md. +- 🔎 **Nachtrag 2026-08-23 (Recherche-Session, read-only — kein Eingriff): der PSK in der Doku ist + noch der LIVE konfigurierte.** Gegengeprüft am Manager `crs326-core` (`/interface wifi security`, + Profil `sec-iot` → `cfg-iot` → SSID `dirtyvader-iot`, `datapath.vlan-id=30`, + `wpa2-psk,wpa3-psk`) — und zwar **per Fingerprint statt Klartext** (Länge + drei Zeichenpaare), + damit der Wert nicht ein zweites Mal in ein Transkript wandert. **Diese Methode ist die Merkregel + daraus:** einen Verdacht auf Übereinstimmung prüft man mit Stichproben, nicht durch Ausgeben. +- ✅ **User-Entscheid 2026-08-23 zur Git-Historie: belassen, im Nachtrag dokumentieren** — **kein** + `git filter-repo`. Begründung trägt: genau **eine** getrackte Fundstelle + ([Archiv](teilprojekte-archiv.md#tp17)), drei Commits (`e76289c` Ersteintrag 2026-07-11, + `f0d1ff9` 08-08, `7ee64b5` Doku-Split 08-23), Remote **ausschließlich** `gitea.emsenhuber.net`, + **ein** lokaler Klon. Eine History-Rewrite hätte hier also nichts gerettet, was nicht ohnehin nur + auf der eigenen Infrastruktur liegt — und den Preis (alle Hashes neu) für nichts bezahlt. +- 📊 **Warum die Rotation heute teuer ist — live gemessen 2026-08-23:** **26 der 27 WLAN-Clients des + gesamten Netzes hängen auf `dirtyvader-iot`** (`dirtyvader-main` 1, MEDIA/UNTRUSTED/GUEST je 0). + VLAN30 führt **41 Leases/Reservierungen** (5 aktuell `bound`, der Rest sind statische + Reservierungen ausgeschalteter Geräte). Neben den ~26 Shellys hängen dort **P750W** (Drucker), + **Airfryer** (`espressif`, `.180`), **SwitchBot floor-lamp**, **Twinkly** `.228`, **DTUBI** `.8`, + **SONOFF-NSPanelPro** und ein **iPhone** `.177`. ⇒ Ein Passwortwechsel ist heute eine + Batch-Aktion über ~26 Geräte, und **das ist genau die Rechnung, die TP17.1 verkleinert.** +- 🔧 **Zwei Umsetzungshinweise fürs spätere Rotations-Paket:** + **(a)** `mcp/shelly/migrate.py` hat **kein** Rotate-Kommando (nur `migrate`/`deanchor`/`auth`/ + `table`) — es bräuchte eine kleine Variante über denselben `set_sta`-Pfad. + **(b) Ein Flag-Day ist vermeidbar:** RouterOS 7 kann in `/interface wifi access-list` + **Passphrase-Overrides je MAC**. Also neuer PSK aufs Profil, Altgeräte übergangsweise per MAC mit + dem alten weiter, danach die Liste leeren. 💡 Nebeneffekt: der TP25-Befund „keine `access-list`" + bekäme damit endlich einen Zweck — und seit dem 08-23 gibt es die ComplianceRule + `wifi-access-list`, die Einträge dort auch sichtbar macht. +- **Mitzuziehen bei der Rotation** (legitime, gitignorete Ablagen desselben Werts): + `~/.secrets/credentials.env` (+ `.bak-20260808`), `routeros/.secrets/wlan-psks.env`, + `mcp/shelly/.env`. + +- **CF-Access-Service-Token** — **Rotationsposten #4**, am 2026-08-24 aus den Follow-ups hierher + gezogen (stand dort als „TP14.4 — CF-Access-Service-Token rotieren"). Sachlich gehört er zu + **TP14.4** (CF-Access-Profil für Claude, Runbook `docs/tp14.4-cf-access-token-runbook.md`); hier + steht er, damit die Rotationsliste vollständig ist. ⚠️ Der `CF_API_TOKEN` läuft ohnehin + **2027-01-09** ab — spätestens dann ist dieser Posten fällig, unabhängig vom Projektende. + +#### Fallen, die für jede künftige Rotation gelten (nicht neu erheben) +- 🔴 **Niemals `sshpass -p`** — schreibt das Passwort in die Kommandozeile, sichtbar in `ps` und in + jedem argv-Trace. **Genau so entstand Leak #1.** `-e` hält es in der Umgebung des Kindprozesses. + Der Repo-Stand ist bereits durchgängig `-e`. +- 🔴 **Passwörter nie per MCP-`password`-Parameter setzen**, sondern per Skript aus `~/.secrets` + (`manage_user set-password`; `/user set*` ist per Deny-Policy blockiert). +- 🔴 **Keine Secrets-Enumeration im Transkript** — das war Leak #2, ohne dass irgendein Werkzeug + fehlerhaft war. +- 🔒 **`wifi-security` ist als ComplianceRule grün, aber NICHT deploybar** (Passphrasen stehen als + `<>` im Template). Ist-Stand für #2 immer per REST vom Gerät lesen + (`GET http://10.40.99.1/rest/interface/wifi/security`), **nie** aus `wlan-psks.env`. +- ⚠️ **CAPsMAN, für #2:** eine Profiländerung wirkt erst nach `remote-cap provision` für **beide** + APs — und die Abnahme ist eine **frische DHCP-Lease je SSID**, nicht die Registration-Table. +- ⚠️ **Für #2 zuerst `multi-passphrase` gegen WPA3/SAE testen — auf einer Wegwerf-SSID, nie an + `dirtyvader-iot`.** `sec-iot` fährt `wpa2-psk,wpa3-psk`; trägt multi-passphrase SAE nicht, sperrt + man **26 IoT-Geräte auf einmal** aus, inklusive Nuki und NSPanel. +- ⚠️ **`s1`/`s2`/`s3` sind ausgesteckt** und kommen im Dezember mit dem **alten** PSK zurück — der + Übergangs-Eintrag muss sie überleben oder sie werden bei Rückkehr von Hand nachgezogen. +- 🔴 **HA- und Repo-Nummerierung der Shellys weichen ab** (`s10`, `s17`) — **immer über MAC/IP + zuordnen, nie über die s-Nummer.** +- **Abh.:** keine harten; #2 und #3 laufen sinnvollerweise in **einem** Geräte-Durchgang. + **Blockiert nichts.** Die frühere Kopplung „erst TP17.1, dann rotieren" ist **gegenstandslos** — + TP17.1 ist am 2026-08-23 verworfen, die Geräte bleiben WLAN-Clients. + --- ## Abgeschlossene Teilprojekte ▸ [`teilprojekte-archiv.md`](teilprojekte-archiv.md) @@ -1046,109 +1210,10 @@ den Weg, über den man den Fehler zurücknehmen wollte. Re-Walk + Dead-Spot-Kartierung laufen als Schritt 5 von TP25 — und zwar erst **nach** den Funkparameter-Fixes, weil vorher gemessene Werte wertlos sind. - **TP10 —** DDNS-Auto-Updater für `bf4.emsenhuber.net` (auf dem Core möglich, `device-mode` erlaubt scheduler). -- 🔑 **Admin-Passwort der vier MikroTik rotieren (offen seit 2026-08-22, User: „machen wir, - aber erst später").** ⏭️ ~~**Nachgelagert seit 2026-08-23: erst TP17.1, dann rotieren.**~~ - **Revidiert noch am selben Tag (User): beides läuft PARALLEL.** Der Passphrase-Override je MAC - (s.u.) macht den Flag-Day überflüssig, damit war die Reihenfolge nie technisch nötig — nur - ökonomisch. Regel für die Parallelität: **ein Gerät, das ohnehin auf Thread/Zigbee wandert, - bekommt den neuen PSK gar nicht**, sondern nur einen Übergangs-Eintrag in der `access-list`. - ⚠️ Der Entscheid betrifft **beide** Passwörter: der **IoT-WLAN-PSK** steht im Klartext im - TP17-Text ([Archiv](teilprojekte-archiv.md#tp17)) und damit auch in der Git-Historie — **bleibt - auf User-Entscheid 2026-08-23 vorerst unverändert**, weil Redigieren ihn nicht aus der Historie - holt und Rotieren heute ~22 Shellys kostet. Nach TP17.1 sind es deutlich weniger. Anlass: das Core-Passwort ist bei einer Debug-Ausgabe im Klartext in - ein Sitzungstranskript geraten. Ursache war `sshpass -p`, das es in die **Kommandozeile** - schreibt — sichtbar in `ps` und in jedem argv-Trace. - --- - #### 🔑 Radius-Befund 2026-08-23: das Admin-Konto teilen sich FÜNF Konsumenten - Vor dem Rotieren erhoben — das ist deutlich mehr als „vier Geräte + eine Datei": - - | Halter | Nachziehen | - |---|---| - | `~/.secrets/credentials.env` | Datei | - | `~/.claude.json` (MikroMCP-Env, `ROUTER_*`/`CRS326_*`) | JSON + MCP-Neustart | - | **Nautobot-Stack** `NAUTOBOT_ROUTEROS_USERNAME/PASSWORD` | Stack-Datei + **Portainer-Redeploy auf der DS923** | - | **HA: VIER `mikrotik`-Integrationen** (`.99.1/.2/.11/.12`, 40 `device_tracker`) | 🔴 **`supports_reconfigure: false` — NICHT skriptbar**, 4× Re-Auth von Hand | - | Repo-Skripte (`routeros/*.py`, `nautobot/*.py`, `docs/tp*.sh`) | ziehen aus `~/.secrets` → automatisch | - - ⇒ **User-Entscheid 2026-08-23: Konten trennen statt ein Passwort teilen.** Nicht das Rotieren ist - das Problem, sondern dass ein einziges `admin` von fünf Stellen benutzt wird — jede Rotation kostet - sonst wieder vier Re-Auths und einen Stack-Redeploy. - - #### ✅ Etappe 1 DURCH (2026-08-23): dedizierte Service-Accounts auf allen vier Geräten - Rein **additiv**, kein laufender Dienst berührt. Vorher existierte **nur** `admin` (Gruppe `full`). - - | Gruppe | Policy | User | Zweck | - |---|---|---|---| - | `grp-ha` | `read,api,rest-api,test` | `ha` | HA-Mikrotik-Integration, **lesend** über API 8728 | - | `grp-nautobot` | `ssh,read,write,test,sensitive` | `nautobot` | Golden Config über SSH/Netmiko (Backup **und** Deploy) | - - Passwörter: `MIKROTIK_HA_PASS` / `MIKROTIK_NAUTOBOT_PASS` in `~/.secrets/credentials.env` - (32 Zeichen, je Dienst eigen, geräteübergreifend gleich). - 🔒 **Angelegt über ein Skript, das die Werte aus der Datei liest** — bewusst *nicht* über - `manage_user`, dessen `password`-Parameter im Sitzungstranskript landen würde. - - **Abnahme, auf allen vier Geräten geprüft:** - - `ha` liest (`identity`, `dhcp-lease` — am Core 59 Einträge, genau was das Device-Tracking braucht), - **Schreibversuch wird abgewiesen**. - - `nautobot` meldet sich per SSH an und exportiert; **kein REST** (bewusst kein `rest-api` in der Policy). - - 🎯 **Der Export von `nautobot` ist byte-identisch zu dem von `admin`** (391/56/87/87 Zeilen je Gerät) - ⇒ **die GC-Compliance driftet beim Umstellen nicht.** Das war das Hauptrisiko dieser Etappe. - - `/user` wird von **keiner** ComplianceRule abgedeckt ⇒ die neuen Konten erzeugen selbst keinen Drift. - - #### ⏭️ Etappe 2 offen — die Konsumenten umhängen, DANN `admin` rotieren - 1. **Nautobot** auf `nautobot` umstellen (Stack-Env + Portainer-Redeploy), GC-Backup-Lauf als Abnahme. - 2. **HA**: die vier `mikrotik`-Einträge auf den `ha`-User bringen. ⚠️ Reconfigure ist nicht skriptbar; - Entfernen-und-neu-Anlegen **wäre** skriptbar, riskiert aber die 40 `device_tracker`-Entity-IDs - (sie leiten sich aus der MAC ab, kämen also gleich zurück — **aber erst nachdem** die alten - Registry-Einträge weg sind, sonst hängt HA ein `_2` an; dieselbe Falle wie beim Shelly-Rename). - 3. **Erst danach** `admin` rotieren — dann berührt es nur noch `~/.secrets` + `~/.claude.json`. - - 🔴 **Eigener Fehler, protokolliert:** beim Erheben des Radius hat ein `json.dumps`-Aufruf über - `~/.claude.json` das **ap1-Passwort im Klartext ins Transkript geschrieben**. Da alle vier Geräte - dasselbe `admin`-Passwort teilen, ist es **derselbe Wert, der am 2026-08-22 bereits verbrannt ist** — - keine neue Expositionsklasse, aber ein zweiter Beleg dafür, dass die Rotation fällig ist. - **Merkregel: Secrets-Enumeration gibt nur Schlüsselnamen aus, nie Werte** — auch nicht abgeschnitten. - - ✅ **Vorbedingung erfüllt, geprüft 2026-08-23:** alle vier - Skripte laufen auf `sshpass -e` (`tp6-marker/server.py`, `tp6-monitor-core.sh`, - `tp25-walk-messung.sh`, `tp25-pin-s22.sh`) — die frühere Notiz, zwei davon hätten die Schwäche - noch, war veraltet. Übrig blieb nur **`CLAUDE.md`, das `sshpass -p` weiterhin aktiv als Reboot-Weg - empfahl** — am 2026-08-23 auf `sshpass -e` korrigiert. **Damit ist die Rotation ohne Rückfallgefahr - fahrbar.** - Weg: `manage_user set-password` (⚠️ `/user set*` ist per Deny-Policy blockiert), danach - `~/.secrets/credentials.env` (`ROUTER_*_PASS`/`CRS326_*_PASS`) und `~/.claude.json` nachziehen. - Es ist **ein** Passwort für alle vier Geräte — die „Überlebensversicherung" aus CLAUDE.md. - - 🔎 **Nachtrag 2026-08-23 (Recherche-Session, read-only — kein Eingriff): der PSK in der Doku ist - noch der LIVE konfigurierte.** Gegengeprüft am Manager `crs326-core` (`/interface wifi security`, - Profil `sec-iot` → `cfg-iot` → SSID `dirtyvader-iot`, `datapath.vlan-id=30`, - `wpa2-psk,wpa3-psk`) — und zwar **per Fingerprint statt Klartext** (Länge + drei Zeichenpaare), - damit der Wert nicht ein zweites Mal in ein Transkript wandert. **Diese Methode ist die Merkregel - daraus:** einen Verdacht auf Übereinstimmung prüft man mit Stichproben, nicht durch Ausgeben. - - ✅ **User-Entscheid 2026-08-23 zur Git-Historie: belassen, im Nachtrag dokumentieren** — **kein** - `git filter-repo`. Begründung trägt: genau **eine** getrackte Fundstelle - ([Archiv](teilprojekte-archiv.md#tp17)), drei Commits (`e76289c` Ersteintrag 2026-07-11, - `f0d1ff9` 08-08, `7ee64b5` Doku-Split 08-23), Remote **ausschließlich** `gitea.emsenhuber.net`, - **ein** lokaler Klon. Eine History-Rewrite hätte hier also nichts gerettet, was nicht ohnehin nur - auf der eigenen Infrastruktur liegt — und den Preis (alle Hashes neu) für nichts bezahlt. - - 📊 **Warum die Rotation heute teuer ist — live gemessen 2026-08-23:** **26 der 27 WLAN-Clients des - gesamten Netzes hängen auf `dirtyvader-iot`** (`dirtyvader-main` 1, MEDIA/UNTRUSTED/GUEST je 0). - VLAN30 führt **41 Leases/Reservierungen** (5 aktuell `bound`, der Rest sind statische - Reservierungen ausgeschalteter Geräte). Neben den ~26 Shellys hängen dort **P750W** (Drucker), - **Airfryer** (`espressif`, `.180`), **SwitchBot floor-lamp**, **Twinkly** `.228`, **DTUBI** `.8`, - **SONOFF-NSPanelPro** und ein **iPhone** `.177`. ⇒ Ein Passwortwechsel ist heute eine - Batch-Aktion über ~26 Geräte, und **das ist genau die Rechnung, die TP17.1 verkleinert.** - - 🔧 **Zwei Umsetzungshinweise fürs spätere Rotations-Paket:** - **(a)** `mcp/shelly/migrate.py` hat **kein** Rotate-Kommando (nur `migrate`/`deanchor`/`auth`/ - `table`) — es bräuchte eine kleine Variante über denselben `set_sta`-Pfad. - **(b) Ein Flag-Day ist vermeidbar:** RouterOS 7 kann in `/interface wifi access-list` - **Passphrase-Overrides je MAC**. Also neuer PSK aufs Profil, Altgeräte übergangsweise per MAC mit - dem alten weiter, danach die Liste leeren. 💡 Nebeneffekt: der TP25-Befund „keine `access-list`" - bekäme damit endlich einen Zweck — und seit dem 08-23 gibt es die ComplianceRule - `wifi-access-list`, die Einträge dort auch sichtbar macht. - - **Mitzuziehen bei der Rotation** (legitime, gitignorete Ablagen desselben Werts): - `~/.secrets/credentials.env` (+ `.bak-20260808`), `routeros/.secrets/wlan-psks.env`, - `mcp/shelly/.env`. -- **TP14.4 —** CF-Access-Service-Token rotieren. +- 🔑 **Alle Passwort-/Token-Rotationen laufen seit 2026-08-24 unter [TP30](#tp30) — Sammel-TP, + gebündelt gegen Projektende (User-Entscheid).** Dort steht die Rotationsliste (MikroTik `admin`, + IoT-PSK, Shelly-Gerätepasswort, CF-Access-Token), der Radius der fünf Konsumenten, der + Etappe-1-Abschluss und die Fallenliste. **Etappe 1 ist durch**, Etappe 2 wartet bewusst. - ~~**Doku-Aufräumen** (`docs/doku-cleanup-session.md`)~~ ✅ **abgeschlossen 2026-08-23.** Punkte A–D (08-16), E (08-18/19) und **F — der Split** (08-23) sind durch: abgeschlossene TPs liegen jetzt in [`teilprojekte-archiv.md`](teilprojekte-archiv.md), TP25 ist von 394 auf ~100 Zeilen kondensiert, @@ -1161,7 +1226,8 @@ den Weg, über den man den Fehler zurücknehmen wollte. **TP8** (Identity/802.1X) · **TP11** (Monitoring) · **TP12** (IPv6) · **TP13** (Botschafts-WLANs) · **TP16.2** (Härtung bypass-Dienste) · **TP18** (Garage-Objektspeicher) · **TP20.1** (Vaultwarden → Platform-PG) · -**TP23** (DNS-Policy, s. Regel oben). +**TP23** (DNS-Policy, s. Regel oben) · **TP30** (Credential-Rotation — nicht research-, sondern +**termin**-gated: gebündelt gegen Projektende, User-Entscheid 2026-08-24). *(**TP17.1** — Shelly Gen4 → Thread, aktiviert 2026-08-23 — läuft **nicht hier**, sondern im HA-Projekt `~/dev/ha-xstate`; netzseitig ist nichts zu bauen. Es blockt bewusst die PSK-Rotation.)* *(**TP16.1** stand hier bis 2026-08-17 fälschlich als offen — es ist seit demselben Tag ✅ abgeschlossen und