Merge TP41 (CF-Access-Reparatur + ZT-Konsolidierung) + TP42-Anlage

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-09-01 19:21:03 +02:00
5 changed files with 339 additions and 0 deletions

View File

@@ -21,6 +21,13 @@
# OEFFENTLICH (via Cloudflare Tunnel + Access; Clients ohne WARP)
# =========================================================================
vw.emsenhuber.net {
# TP41 T2: /admin nur lokal/WARP-intern (kein CF-Header). Via CF (Header CF-Connecting-IP
# gesetzt) -> 404 statt Vault-Admin. Ersetzt die frühere WAF-Edge-Regel (403).
@cf_admin {
header CF-Connecting-IP *
path /admin /admin/*
}
respond @cf_admin 404
reverse_proxy http://10.40.20.127
}

View File

@@ -0,0 +1,166 @@
# Handoff 2026-09-01 — TP41 CF-Access-Reparatur + Zero-Trust-Konsolidierung
> **Branch `tp41-cf-access-repair`.** Alle CF-Änderungen sind **live via API** gemacht (Schreibpfad
> `CF_API_TOKEN` + curl, cf-tunnel-mapping.md §11). Working-Tree: `docs/cf-backup/tp41-20260901/`
> (Snapshots, secret-frei) + dieser Handoff + `teilprojekte.md`-Eintrag; `mcp/cloudflare/.env`
> (gitignored) wurde geändert (Token-Konsolidierung). Helper-Skripte lagen im Scratchpad/`/tmp`
> (`cf_session.py`, `cf_harden.py`, `cf_groups.py`, `cf_vwadmin.py`, `cf_carveout.py`, `t4a.py`).
## Auslöser
Zugriff auf CF-geschützte Apps zwang Christoph **und Geli** faktisch **täglich** zum E-Mail-OTP-Login,
obwohl 30 Tage gelten sollten; föderierte Logins (GitHub/Google) „funktionieren nicht". Root-Causes:
(1) **Team-Domain-Rename `bf4` → `emsenhuber`** ⇒ Provider-OAuth-Apps kennen die neue Callback-URL nicht;
(2) App-**Session 24h**; (3) diverse Ordnungs-/Sicherheitslecks. Daraus wurde eine
Zero-Trust-Konsolidierungs-Runde.
## ✅ LIVE erledigt (verifiziert)
- **Session 720h** auf Wildcard (`16aaec78`), vw-App (`1dbc45ca`), Warp-Login (`6c32fe23`).
- **login_method-Loch geschlossen:** reusable Policy **`bf-users` (`4ccc9b7e`)** = `allow` mit **nur**
`email:christoph@emsenhuber.com` + `email:<geli>@outlook.de` (kein `login_method`-Include mehr).
Attached an Wildcard / App-Launcher (`6df5c431`) / Warp-Login. Reusable Policy `8e44f5d1`
**entkoppelt** → hängt jetzt **nur noch an Terpenfinder** (Fremdprojekt, nicht angefasst).
- **Access-Gruppen (Prefix `zt-`):** `zt-humans` (`6eeec7f3`, christoph+geli), `zt-home`
(`c0f8ba0d`, IP `90.146.33.177/32`), `zt-automation` (`1b60b608`, svc-token `65f1821a`).
Policies `bf-users` / `bf4` (`5165d139`) / `claude-mcp` (`39fe0e9d`) zeigen jetzt **auf die Gruppen**
→ Personen-/IP-/Token-Pflege künftig nur noch in der Gruppe.
- **vw = voll Bypass** (Passwort-Lebensader: Web-Vault + Bitwarden-App/Extension/Desktop offen, **kein**
CF-Login davor). Ein Carve-out-Versuch (nur Client-Pfade bypass, Rest gaten) wurde **verworfen**:
CF-**Bypass kurzschließt** spezifischere path-Apps, und `/` (Web-Vault-Root) teilt den Prefix mit
`/admin` — nicht trennbar. Die 3 Experiment-Apps wurden wieder gelöscht.
- **`vw.emsenhuber.net/admin` öffentlich geblockt** per **WAF-Custom-Rule** (Zone-Ruleset
`416af72d0dd54853805875bf5752afd7`, Regel `f26744eb…`, `action=block`,
expr `http.host eq "vw.emsenhuber.net" and (path eq "/admin" or starts_with(path,"/admin/"))`).
**Verifiziert über CF-Edge** und vom User per **Mobilfunk** („you have been blocked"). Lokal (Heim-LAN,
Split-Horizon → Caddy) und später WARP-intern bleibt `/admin` erreichbar.
- **API-Token konsolidiert:** `mcp/cloudflare/.env` `CF_API_TOKEN` = **`…4148`** (id `493ed8bd…`),
Backup `mcp/cloudflare/.env.bak-tp41-20260901`. Der User hat `…4148` anschließend **vollständig**
gemacht (u.a. **Access: Service Tokens Write** + **Zero Trust Write** + WAF + Groups + DNS für
emsenhuber.net **und** teilzeitladen.xyz). **Altes Token `…2174` (id `9984078812bc18d4ebb6a64b570144f2`)
ist am 2026-09-01 vom User revoked ✅.**
> ⚠️ **API-Token-Altlast → ARBEITSPAKET für die Folgesession (User 2026-09-01):** der User fand ein
> weiteres API-Token **`b00722522c685920f73cfcc62e9555d9`** mit **exakt denselben Permissions wie
> `d47435d5c86b764bbf7c5b19ae827033`** — vermutlich eine **blaueblüten/Terpene-Altlast**.
> **Auftrag: Projekte nachziehen** — feststellen, welcher Consumer welches der beiden Tokens nutzt,
> auf **eines** konsolidieren, das verwaiste dann abbauen. Token-/Credentials-Hygiene (TP30-nah).
## 🔜 OFFEN (Token reicht jetzt für alles außer T5)
- **T4 — kumulatives Service-Token `zt-svc`** (Basis: `t4a.py`, war nur an fehlender Perm gescheitert):
1. `claude-mcp` (`65f1821a`) **rename → `zt-svc`** + **rotate** (Secret einmalig).
2. `terpene-svc`-Policy (`bf7d2e5e`) **additiv** += group `zt-automation` (akzeptiert dann alt **und** neu).
3. Secret ablegen: `mcp/cloudflare/.env` (`CF_ACCESS_CLIENT_ID/SECRET`) **und**
`~/.secrets/credentials.env` — dort auch die Terpene-Aliase **`TERPENE_ACCESS_CLIENT_ID/SECRET`**
(die die Tools lesen) **und** `TERPENE_VERIFY_CF_CLIENT_ID/SECRET` (beide zeigten auf terpene-verify-v2).
4. **Verify Terpene:** `python3 ~/dev/blaueblueten-n8n/tools/test_whoami.py`
(→ `420.teilzeitladen.xyz/api/admin/whoami`, muss weiter funktionieren).
5. Erst **nach** grünem Verify: `terpene-verify-v2` aus `terpene-svc` entfernen, dann
**`terpene-verify` (`a6be7efa`) + `terpene-verify-v2` (`1082bad1`) löschen**.
6. `~/.secrets/README.md`-Index nachziehen. opencode/`exports.zsh` optional (gui-env-sync).
→ End: **ein** Service-Token `zt-svc` über Gruppe `zt-automation` in allen Apps + Consumern.
- **T3 — WARP löst `emsenhuber.net` intern auf** (User-Wahl „Variante 2"): WARP-Device-Profile
`fallback_domains` += `emsenhuber.net` → interner Resolver **`10.40.20.1`** (liefert Split-Horizon
`*.emsenhuber.net` → Caddy `10.40.20.40`). Route **`10.40.0.0/16` existiert** (tunnel `d1da7c8a`).
Danach `/admin` + alle internen Namen über **WARP** via Caddy erreichbar (kein CF/WAF). ⚠️ **account-/
profilweit** → als Lifecycle-Change **proaktiv melden**. (Token hat jetzt Zero-Trust-Write.)
- **T2 — 404 statt 403 (User-Wunsch):** WAF-**Custom-Response ist Free-Plan-gesperrt** („not entitled to
use a custom response"). 403-Block bleibt — außer man macht es **Origin-seitig in Caddy** (`respond 404`
wenn Header `CF-Connecting-IP` gesetzt = via CF gekommen; lokal/WARP-intern ohne Header → durchlassen).
Das komponiert sauber mit T3 (WARP-intern trifft Caddy ohne CF-Header). Eigener Caddy-Deploy (LXC 130).
- **T5 — IdP-Konsolen (USER-Hausaufgabe, DER Daily-OTP-Fix, bestätigt kaputt):** User-Test lieferte
GitHub **„The redirect_uri is not associated with this application"**. Fix in den **Provider-Konsolen**:
- **GitHub** OAuth-App `Ov23li2h96hAkGRPJXYV` → *Authorization callback URL*
- **Google** OAuth-Client → *Authorized redirect URIs*
- beide = **`https://emsenhuber.cloudflareaccess.com/cdn-cgi/access/callback`**.
Danach Login-Test je Provider; Gegenprobe CF-Audit `GET /accounts/…/access/logs/access_requests`
(`identity_provider=github/google` statt `onetimepin`).
- **T6 (optional) — Rate-Limit:** vw `/identity/connect/token` + gitea-Login. **Kein** Managed-Challenge
vor vw-API/`/identity`, git-/api-Pfaden, `assetlinks.json` (bricht Bitwarden-Clients / git / MCP).
- **T7 — Doku:** ggf. `docs/tp41-cf-access-repair-runbook.md` (Detail-Runbook) ergänzen.
## 🆕 NEU — dw/Geli an der Auth vorbei (Terpenfinder, CGNAT)
Ziel: dw erreicht `420.teilzeitladen.xyz` **ohne** CF-Login. IP-Bypass wie `bf4` scheitert an Gelis
**CGNAT**. **Eleganteste Lösung (User-Idee): Split-Horizon am dw-Standort** — dw-FritzBox setzt lokalen
DNS-Override `420.teilzeitladen.xyz` → BF-Caddy (`caddy-bf1` / `10.40.20.40`), erreichbar über den
bestehenden **WG-Tunnel dw↔core**; Caddy braucht einen Block `420.teilzeitladen.xyz` → macmini-Worker
(`10.40.20.167:8890`) **mit Cert** (DNS-01; Token hat jetzt DNS-Write für `teilzeitladen.xyz`).
Vorab prüfen: (a) FritzBox-Host-Override möglich; (b) WG-Route dw→10.40.20.40; (c) Worker wirklich auf
`macmini:8890` von Caddy erreichbar. **Cross-Projekt** (teilzeitladen.xyz). Alternative: Geli-Gerät in
**WARP** (Session statt Login, CGNAT unkritisch) + Access-Policy auf WARP-Identität.
## ❓ Scope-Klärung für die neue Session
Der User nannte „TP3/TP4/TP5 gleich mitnehmen" — **diese sind laut `teilprojekte.md` abgeschlossen**
(TP3 WLAN-Rebuild ✅, TP4 ap1-Router/WAN-Edge ✅, TP5 deny-by-default ✅). Vermutlich Zahlendreher.
**Offene Kandidaten:** TP6 (CAKE, Projektziel), TP16.1 (WARP-Mesh nativ), TP16.3, TP24 (DC-USV),
TP25 (WLAN-Signal/Re-Walk). **Vor Start klären, welche gemeint sind** (je eigene Session empfohlen;
Subagenten nur für parallele, abgegrenzte Teilaufgaben innerhalb einer Session).
## 🧭 Test-Vantage-Lehre (wichtig, hat hier Stunden gekostet)
Von der **Heim-IP** löst `*.emsenhuber.net` → `10.40.20.40` (Caddy) und **umgeht CF komplett** — CF-Access/
WAF-Gating ist von zuhause **nicht** sichtbar (alles wirkt „offen"). Edge-Verhalten **erzwingen** mit
`curl --resolve <host>:443:<CF-anycast-IP>` (CF-IP via `dig @1.1.1.1 +short <host>`). **WebFetch ist für
Access/Redirects unzuverlässig** (erreichte Origin trotz Gating) — **nicht** als Beweis verwenden; echter
Remote-Test = User-Gerät im Mobilfunk.
## Referenz-IDs
Apps: Wildcard `16aaec78` · vw/hass/gitea-Bundle `1dbc45ca` · App-Launcher `6df5c431` · Warp-Login
`6c32fe23` · Terpenfinder v3 `e6a7991f`. Policies: `bf-users` `4ccc9b7e` · `bf4` `5165d139` · `claude-mcp`
`39fe0e9d` · `terpene-svc` `bf7d2e5e` · (Terpene-only) `8e44f5d1`. Gruppen: `zt-humans` `6eeec7f3` ·
`zt-home` `c0f8ba0d` · `zt-automation` `1b60b608`. Service-Tokens: `claude-mcp`→`zt-svc` `65f1821a` ·
`terpene-verify` `a6be7efa` (Waise) · `terpene-verify-v2` `1082bad1`. WAF: Ruleset `416af72d…`, Regel
`f26744eb…`. Team-Domain `emsenhuber.cloudflareaccess.com` (Org-`name`-Altlabel `bf4…` nicht anfassen).
---
## ✅ Update — Folgesession 2026-09-01 (T4 durch, Token-Altlast geklärt, Drift-Korrekturen)
### T4 — zt-svc ✅ DURCH (Variante B, inkl. Worker)
- `claude-mcp` (`65f1821a`) → **`zt-svc`** umbenannt **und rotiert** (Secret in
`mcp/cloudflare/.env` `CF_ACCESS_CLIENT_ID/SECRET` + `~/.secrets/credentials.env`; dort
`TERPENE_ACCESS_*` und `TERPENE_VERIFY_CF_*` jetzt = zt-svc). client_id
`ad1b47dee8ba9625eebb30247d163dda.access`.
- **Worker-Pin gefunden** (`blaueblueten-n8n/worker/src/index.js:44`): Admin wird nur dem Token mit
`common_name == env.TERPENE_SVC_CLIENT_ID` gewährt. Deshalb Variante B: **`wrangler secret put
TERPENE_SVC_CLIENT_ID`** = zt-svc-client_id (wrangler-OAuth-Session, `workers_scripts:write` — die
„Deploy blockiert"-Notiz galt nur für API-Tokens). Kein Code-Redeploy nötig.
- `terpene-svc` (`bf7d2e5e`) include = **nur noch Gruppe `zt-automation`** (`1b60b608`).
**`terpene-verify` (`a6be7efa`) + `terpene-verify-v2` (`1082bad1`) gelöscht.** Einziges verbleibendes
Access-Service-Token = **`zt-svc`**. Verify: `test_whoami.py` → `admin:true`, common_name = zt-svc. ✅
### Token-Altlast (b00722 / d47435) — GEKLÄRT (Rollen waren im Ur-Handoff vertauscht)
- **`b00722`** ist **NICHT** die Altlast, sondern das **LIVE** von Caddy genutzte DNS-01-Token
(LXC130 `/etc/caddy/caddy.env`, SSoT). Certs valide bis Nov 2026.
- **`d47435`** = **stale Klartext-Kopie** in `credentials.env` (gleiche Perms, kein Live-Consumer).
n8n hält **0 Credentials**, blaueblüten hält keinen der beiden. `credentials.env`-Kopie am
2026-09-01 auf **b00722** realignt (SSoT-Abgleich).
- 🔜 **USER-Aktion:** **`d47435` revoken** (Dashboard oder `…4148` kurz „Account API Tokens Write"
geben — `…4148` kann API-Tokens weder listen noch revoken, Bestätigung 9109/1000).
### Drift-Korrekturen (live gemessen)
- **T3-Resolver:** interner Split-Horizon liegt auf **`10.40.20.36`/`.37`** (→ `*.emsenhuber.net = .40`),
**nicht** auf `10.40.20.1` (der liefert public CF). T3-fallback_domains müssen auf `.36/.37` zeigen.
- **`10.40.20.16/.17`** (AdGuard laut CLAUDE.md) sind **stale** → neu als **TP42** angelegt
(`docs/handoff-20260901-tp42-naming.md`): `.bf.lan`/`.bf.emsenhuber.net`-Vereinheitlichung.
### 🔴 Leak (Transparenz)
Beim maskierten Lesen von `credentials.env` ist der Wert **`TERPENE_ANDROID_KEYSTORE_PW`** ins
Sitzungstranskript geraten (Regex-Loch `_PW`). **Rotation erwägen** (Terpene-Android-Signing).
### T3 — WARP-intern ✅ APPLIED (2026-09-01)
- Ziel-Profil geklärt: das custom „Cloudflare Mesh"-Profil matcht **nur** `warp_connector@…` → Christoph/Geli
laufen im **Default-Profil** (`0197d1b3`). `fallback_domains += emsenhuber.net → [10.40.20.36, 10.40.20.37]`
dort gesetzt (15 Suffixe). Tunnel-Route `10.40.0.0/16` via `d1da7c8a` existiert; Exclude-Liste enthält
**kein** `10.0.0.0/8` (nur `192.168/16` + CGNAT-minus-Mesh) → `.36/.37` sind über WARP routbar.
- ⏳ **User-Verify:** WARP am Gerät **neu verbinden** (Profil-Cache), dann `dig vw.emsenhuber.net → .40`
und `/admin` über WARP erreichbar.
### T2 — 404 statt 403 ✅ DURCH (2026-09-01)
- Caddyfile `vw`-Block: `@cf_admin {header CF-Connecting-IP *; path /admin /admin/*} → respond 404`.
Deploy LXC130 (Backup `/etc/caddy/Caddyfile.bak-tp41-20260901`), reload ok.
- WAF-Regel **`f26744eb` gelöscht** (nur noch die gitea-skip-Regel `3c707c3c` im Ruleset).
- Verify: **Edge `/admin` = 404** (war 403), Edge `/` = 200, **lokal/WARP `/admin` = 200**. ✅
### Noch offen
- **d47435-Revoke** (User, Account API Tokens Write). **T3-Client-Verify** (User, WARP neu verbinden).
- **T5** (GitHub/Google-Callbacks — der eigentliche OTP-Fix, User) — **Schritt-für-Schritt:**
[`docs/tp41-t5-idp-callback-anleitung.md`](tp41-t5-idp-callback-anleitung.md). **T6/T7/dw-Geli**.
- 🔴 **`TERPENE_ANDROID_KEYSTORE_PW`-Rotation erwägen** (Transkript-Leak, s.o.).

View File

@@ -0,0 +1,40 @@
# Handoff 2026-09-01 — TP42 Namens-Vereinheitlichung bf.lan → emsenhuber.net
> **Angelegt aus einem TP41-Randbefund.** Reine Anlage + Bestandsaufnahme; **keine Live-Änderung**
> in dieser Session. Umsetzung = eigene Session.
## Auslöser
Beim Verifizieren des T3-Resolvers (TP41) live gemessen:
| Resolver | vw.emsenhuber.net | Bewertung |
|---|---|---|
| 10.40.20.36 / .37 | 10.40.20.40 | ✅ korrekt (reale Client-Resolver, via DHCP) |
| 10.40.20.1 (Core) | 188.114.96.10 / .97.10 | public CF (Core macht DoH→CF) |
| 10.40.20.16 | CNAME nginx-bf.emsenhuber.net (kein A) | 🔴 stale |
| 10.40.20.17 | nginx.bf.emsenhuber.net + 10.40.41.123 | 🔴 stale, totes VLAN1 |
Daneben: Core `/ip dns static` = 11× `*.bf.lan`; Caddyfile doppelt jeden internen Namen als
`*.bf.emsenhuber.net`.
## Befund-Fundstellen (Start für die Umsetzung)
- **Core (`crs326-core`) `/ip dns static`:** router.lan, core.bf.lan, macmini.bf.lan, pve.bf.lan,
pve-mcp.bf.lan, nas.bf.lan, docker.bf.lan, platform-pg.bf.lan, ap1.bf.lan, ap2.bf.lan, branch.bf.lan.
- **Caddyfile (`caddy/Caddyfile`, LXC130/.40):** `*.bf.emsenhuber.net`-Aliase an nautobot/ccu/iobroker/
z2m25/pve-mcp/ha-mcp/n8n-mcp/gitea-mcp/pve/portainer/pbs.
- **AdGuard `.36`/`.37`:** aktive Split-Horizon-Rewrites `*.emsenhuber.net → .40` (Sollquelle).
- **Stale `.16`/`.17`:** alte AdGuard, `nginx*`-Antworten + `10.40.41.123` → abbauen/klären.
- **DHCP:** Search-/Domain-Option je Netz prüfen (welcher Suffix wird verteilt?).
## Ziel
Ein interner Namensraum `emsenhuber.net` (Split-Horizon `.36/.37 → .40`). `.bf.lan` +
`.bf.emsenhuber.net` raus. Sollzustand in Nautobot (TP37).
## Offen / Entscheidungen für die Umsetzungssession
1. Zielschema fix: nur `emsenhuber.net`, oder `bf.emsenhuber.net` als **einzige** interne Zone?
2. Migrationsreihenfolge ohne DNS-Loch (erst neue Namen, dann alte weg).
3. `.16/.17`: laufen die noch, gehören sie abgebaut? (mit TP für AdGuard-Konsolidierung abgleichen)
4. Nautobot-Erfassung: Custom Field / Records — abhängig von TP37-Datenmodell.
## Nicht anfassen
Öffentliche Zone `emsenhuber.net` (CF); Resolver-Zuordnung `.36/.37`; `.1`-DNS-Reste auf Clients
(User: „bis jetzt kein Problem"). Test-Vantage-Lehre aus TP41 beachten (von zuhause umgeht man CF).

View File

@@ -31,6 +31,19 @@ Mgmt (VLAN99, Ist 2026-08-16): core `.99.1` · branch `.99.2` · ap1 `.99.11` ·
**Compliance am 2026-08-31 nach vollem Refresh (Backup→Intended→Compliance) gelesen: 128/135.**
*(Die Fassung vom 2026-08-16 stand bis zum 18. hier und war an vier Stellen überholt. Wer diesen Block
liest, liest ihn als Erstes: er wird bei jeder Änderung mitgezogen, nicht nur die TP-Abschnitte.)*
- ⏳ **TP41 CF-Access-Reparatur (2026-09-01, Kern live + T4 durch):** Session 720h,
login_method-Loch zu (`bf-users` email-only), `zt-`-Gruppen, vw voll Bypass + `vw/admin` per WAF
geblockt (Mobilfunk-verifiziert), API-Token auf vollständiges `…4148` konsolidiert. **T4 ✅**
(ein Access-Service-Token `zt-svc`, Terpene-Worker per wrangler auf zt-svc umgestellt, Alt-Tokens
gelöscht). **T3 ✅** (WARP Default-Profil fallback_domains `emsenhuber.net → .36/.37`). **T2 ✅**
(WAF-Regel gelöscht, Caddy-Origin-404 für `/admin` via CF-Header; Edge=404, lokal=200).
**Token-Altlast geklärt:** `b00722`=live Caddy-DNS-Token, `d47435`=stale Kopie → **User revoket d47435**.
**Offen nur noch User:** **T5 = GitHub/Google-Callback** (der OTP-Fix), d47435-Revoke, T3-WARP-Client-Verify.
Handoff: [`docs/handoff-20260901-tp41.md`](handoff-20260901-tp41.md).
- 🔜 **TP42 Namens-Vereinheitlichung (2026-09-01, angelegt):** internes `.bf.lan` (Core-DNS, DHCP-Search-
Domain) und die `.bf.emsenhuber.net`-Aliase (Caddyfile) auf **einen** Namensraum `emsenhuber.net`
ziehen; stale `.16/.17`-Rewrites abbauen; Sollzustand in Nautobot. Handoff:
[`docs/handoff-20260901-tp42-naming.md`](handoff-20260901-tp42-naming.md).
- ✅ **TP16.3 ABGESCHLOSSEN (2026-09-01):** Flip **und** Abbau durch. Öffentlich laufen nur noch
`bf-public` (12 Connectoren) und `fm` — die drei Alttunnel `bf-mm`/`bf-nas`/`bf-pve` **und** der
projektfremde `terpene-db` sind gelöscht, **7 cloudflared-Container** entfernt (inkl.
@@ -475,6 +488,8 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na
> | TP37 | 🔜 | Nautobot als Netzwerkdoku: Hosts/Container/Dienste + CF-Connectoren (Okay 08-30) | — |
> | TP38 | 🔜 | OOB-Mgmt: untagged-VLAN99-Port je Switch | — |
> | TP40 | 🔜 | HA-Recorder-Retention: 41 GB `states` beschneiden (Okay 09-01) | — |
> | TP41 | ⏳ | CF-Access-Reparatur: **T4/T3/T2 ✅**; Token-Altlast geklärt; offen nur noch User-Aufgaben (T5 IdP-Callbacks = OTP-Fix, d47435-Revoke, T3-WARP-Client-Verify) | — |
> | TP42 | 🔜 | Namens-Vereinheitlichung bf.lan→emsenhuber.net: `.bf.lan`/`.bf.emsenhuber.net` aus allen Geräten raus, in Nautobot festhalten | — |
> | — | — | **35 archivierte TPs** in `teilprojekte-archiv.md` (inkl. TP39 ✅ 2026-09-01) | — |
### TP5.1 — DNS-Visibility & Flow-Observability für Low-Trust-Geräte (Airfryer-Fall) ▸ vorgemerkt
@@ -2154,6 +2169,7 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
| 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 |
| 5 | **Nautobot-Tokens** (`NAUTOBOT_SUPERUSER_API_TOKEN`, `NAUTOBOT_GITEA_TOKEN`) | Nautobot-Superuser + Gitea-Anbindung | 🔴 in der TP16.3-§2/§3-Session (2026-08-31) durch schwache `sed`-Maskierung **ins Transkript** geraten | Werte in `docs/nas-vlan20/stacks/210-nautobot.yml` (gitignored) | neu ausstellen + Stack-YML nachziehen; Superuser-Token wird von den `gc-*`-Skripten gelesen |
| 6 | **MariaDB `root`** (LXC 302, `10.40.20.23`) | root-DB-Login | 🔴 am 2026-09-01 (TP39) ins Transkript geraten — die `/root/.my.cnf` trug `password <wert>` **ohne `=`**, die Feld-Maskierung ankerte auf `=` und griff nicht | Wert in `/root/.my.cnf` (chmod 600) | `SET PASSWORD` + `.my.cnf` nachziehen; **kein** externer Konsument (Dienste nutzen eigene DB-User) ⇒ billigste Rotation der Liste |
| 7 | **`TERPENE_ANDROID_KEYSTORE_PW`** | Terpene-Android-TWA-Signing (`android/android.keystore`, alias `terpene`) | 🔴 am 2026-09-01 (TP41) durch **Regex-Suffix-Loch** (`_PW` nicht abgedeckt) ins Transkript geraten | Wert in `~/.secrets/credentials.env` + Keystore-Datei | **Store-/Key-Passwort** via `keytool -storepasswd`/`-keypasswd` ändern + `credentials.env` nachziehen; Konsument = Android-Build/Play-Signing (**Cross-Projekt blaueblüten**) — den **Key selbst NICHT** neu erzeugen |
> ✅ **Der Leak-MECHANISMUS hinter #1 ist seit 2026-08-31 zu — der Wert bleibt trotzdem verbrannt.**
> Alle sechs Skripte im Repo, die `sshpass -p <PW>` benutzten (`nautobot/gc-transaktion.py` und
@@ -2173,6 +2189,12 @@ Umzug **nebeneinander**, ein zweiter AP am selben Punkt bringt nichts und stört
> um sie zu sehen. #6 ist zugleich der **billigste** Posten (kein externer Konsument), aber die
> Panne dahinter ist der teure Teil.
>
> 🔴 **#7 ist die vierte Maskierungs-Panne derselben Klasse** (nach `SHELLY_DEVICE_PW` 08-28,
> Nautobot-Tokens 08-31, MariaDB-root 09-01): diesmal ein **Regex-Suffix-Loch** — das Muster
> `(TOKEN|PASS|PASSWORD|SECRET|KEY|CLIENT_ID)` deckte den Suffix `_PW` **nicht** ab, also blieb der
> Wert von `TERPENE_ANDROID_KEYSTORE_PW` beim maskierten Lesen stehen. **Dieselbe Merkregel, erweitert:**
> die Alternation muss `PW`/`PWD` mit enthalten (`…|PW|PWD|…`), sonst greift die Feld-Ersetzung nicht.
>
> ℹ️ **#3 war bis 2026-08-24 TP17.2** und ist jetzt vollständig hier (s. Detailabschnitt unten) —
> es benutzt denselben Geräte-Durchgang wie #2, **ein Reboot statt zwei**. #4 gehört sachlich zu
> **TP14.4**, das als TP bestehen bleibt (dort steckt das CF-Access-Profil, nicht nur der Token).
@@ -2854,8 +2876,74 @@ Der HA-Recorder schreibt **unbegrenzt** — es ist keine `purge_keep_days`-Grenz
Resize tauchte dort nur auf; die **Ursache** (HA-Retention) ist HA-seitig und darum ein eigenes TP.
- 🔴 **Kein eigenmächtiger Datenlöschvorgang** — `purge` wirft echte Historie weg; die
Aufbewahrungsdauer ist eine Nutzerentscheidung. Diese Session hat **nur** vergrössert und gemessen.
### TP41 — CF-Access-Reparatur + Zero-Trust-Konsolidierung ▸ ⏳ **ANGELEGT 2026-09-01, Kern live**
**Auslöser:** CF-Access zwang Christoph **und Geli** täglich zum OTP-Login (soll: 30 Tage); GitHub/Google
„funktionieren nicht". Root-Causes: Team-Domain-Rename `bf4`→`emsenhuber` (Provider-Callback veraltet),
App-Session 24h, diverse Ordnungs-/Sicherheitslecks. Vollständiger Verlauf + offene Schritte:
**[`docs/handoff-20260901-tp41.md`](handoff-20260901-tp41.md)**. Branch `tp41-cf-access-repair`.
**✅ Live erledigt:** Session 720h (Wildcard/vw/Warp-Login) · login_method-Loch zu (reusable Policy
`bf-users` = nur `email:christoph`+`email:geli`) · `8e44f5d1` von 4 Apps auf **nur Terpenfinder**
entkoppelt · Access-**Gruppen** `zt-humans`/`zt-home`/`zt-automation`, Policies zeigen darauf · **vw voll
Bypass** (Lebensader offen) + **`vw/admin` per WAF-Regel öffentlich geblockt** (CF-Edge + Mobilfunk
verifiziert) · API-Token auf das vollständige `…4148` konsolidiert (User hat Service-Tokens- + Zero-Trust-
Write ergänzt), altes `…2174` revoken.
**✅ T4 DURCH (2026-09-01, Variante B):** ein Access-Service-Token **`zt-svc`** (`65f1821a`, rotiert) über
Gruppe `zt-automation`; Terpene-Worker per `wrangler secret put TERPENE_SVC_CLIENT_ID` auf zt-svc
umgestellt (Worker-Pin `index.js:44`); `terpene-verify`+`-v2` **gelöscht**; `test_whoami` grün.
**Token-Altlast geklärt:** `b00722` = LIVE Caddy-DNS-Token (LXC130 caddy.env, SSoT), `d47435` = stale
Kopie (kein Consumer) → **User revoket `d47435`**; `credentials.env`-Kopie auf b00722 realignt.
**✅ T3 APPLIED (2026-09-01):** Default-Profil (`0197d1b3`; das custom „Cloudflare Mesh" matcht nur den
`warp_connector`) `fallback_domains += emsenhuber.net → [10.40.20.36, 10.40.20.37]`; Tunnel-Route
`10.40.0.0/16` (`d1da7c8a`) da, kein `10/8`-Exclude → routbar. ⏳ Client-Verify: WARP neu verbinden.
**✅ T2 DURCH (2026-09-01):** WAF-Regel `f26744eb` gelöscht; Caddy `vw`-Block `respond @cf_admin 404` bei
Header `CF-Connecting-IP` (LXC130). Verify: Edge `/admin`=404, lokal/WARP `/admin`=200. ✅
**🔜 Offen:** **T5 (USER)** GitHub-OAuth `Ov23li2h96hAkGRPJXYV` + Google-Client Callback =
`https://emsenhuber.cloudflareaccess.com/cdn-cgi/access/callback` (**der eigentliche OTP-Fix**,
Fehler „redirect_uri is not associated" bestätigt) · **d47435-Revoke** (User) · **T3-Client-Verify** (User) ·
**T6** optional Rate-Limit · 🔴 `TERPENE_ANDROID_KEYSTORE_PW`-Rotation erwägen (Transkript-Leak).
**🆕 dw/Geli an Auth vorbei (CGNAT):** Split-Horizon in dw-FritzBox `420.teilzeitladen.xyz` → BF-Caddy
über WG; Caddy serviert die Terpene-App mit Cert (DNS-01, Token hat teilzeitladen.xyz-DNS). Cross-Projekt.
**Abgrenzung:** hass/gitea bleiben (diese Runde) öffentlich; Terpenfinder-Human-Policies nicht angefasst;
**Gitea-Least-Privilege** = eigener künftiger TP (jedes Projekt repo-scoped Login, Admin nur Claude/Christoph).
- Bezug **TP11** (Monitoring): eine Plattenfüllstand-Warnung hätte das Wochen früher gezeigt.
### TP42 — Namens-Vereinheitlichung bf.lan → emsenhuber.net ▸ 🔜 ANGELEGT 2026-09-01 (User-Okay erteilt)
**Auslöser (2026-09-01, TP41-Randbefund):** live gemessen liefern die realen Client-Resolver
`10.40.20.36`/`.37` `*.emsenhuber.net → 10.40.20.40` (Caddy) — korrekt. Daneben existiert aber ein
zweiter, gedrifteter interner Namensraum: der **Core** trägt in `/ip dns static` 11 Einträge auf
`*.bf.lan`, der **Caddyfile** doppelt jeden internen Namen als `*.bf.emsenhuber.net`, und die alten
AdGuard `.16`/`.17` antworten noch mit `nginx*.bf.emsenhuber.net` bzw. totem VLAN1 `10.40.41.123`.
Christoph: „aus emsenhuber.net wurde schon wieder bf.lan — das müssen wir ein für alle mal aus allen
Geräten rausprügeln und in Nautobot festhalten."
**Ziel:** genau **ein** interner Namensraum `emsenhuber.net` (Split-Horizon `.36/.37 → .40`). `.bf.lan`
und `.bf.emsenhuber.net` werden entfernt; Sollzustand in Nautobot dokumentiert.
**Scope (Reihenfolge = eigene Session):**
1. **Bestandsaufnahme** aller Fundstellen: Core `/ip dns static` (`*.bf.lan`), DHCP-Option
`domain`/Search-Domain je Netz, Caddyfile-Aliase (`*.bf.emsenhuber.net`), AdGuard-Rewrites `.36/.37`,
stale `.16/.17`, Geräte-`identity`.
2. **Entscheidung Zielschema** (nur `emsenhuber.net`, ggf. `bf.emsenhuber.net` als *einzige* interne
Zone — Christoph-Entscheid) und Migrationsreihenfolge ohne DNS-Loch.
3. **Umsetzen:** Core-DNS + DHCP + Caddyfile angleichen; stale `.16/.17` klären/abbauen.
4. **Nautobot:** interne Namen/Records als Sollzustand erfassen (Bezug TP37 Datenmodell).
**Abgrenzung:** kein CF-Public-DNS-Umbau (Zone `emsenhuber.net` öffentlich bleibt); kein Resolver-Swap
(`.36/.37` bleiben); `.1`-als-DNS-Reste auf Clients sind separat/tolerierbar (User: „bis jetzt kein
Problem"). **Abh.:** TP37 (Nautobot-Datenmodell) für Punkt 4; sonst nichts Offenes.
**Status:** 🔜 angelegt 2026-09-01, Ausarbeitung eigene Session. Handoff:
[`docs/handoff-20260901-tp42-naming.md`](handoff-20260901-tp42-naming.md).
### TP37 — Nautobot als durchgehende Netzwerkdoku: Hosts/Container/Dienste, erster Anwendungsfall CF-Connectoren ▸ 🔜 ANGELEGT 2026-08-30 (User-Okay erteilt)
> **Christophs Formulierung (2026-08-30):** *„können wir das setup mit den cf-connectoren dann auch in
> nautobot abbilden. quasi eine durchgehende netzwerkdoku stück für stück. muss eh fast sein, da du auf

View File

@@ -0,0 +1,38 @@
# TP41 T5 — IdP-Callback-URLs reparieren (der Daily-OTP-Fix)
**Problem:** Nach dem Team-Domain-Rename `bf4` → `emsenhuber` kennen die OAuth-Apps bei GitHub/Google
die neue Callback-URL nicht. Login schlägt mit „redirect_uri is not associated with this application"
fehl → Cloudflare Access fällt auf **E-Mail-OTP** zurück (das tägliche Nervthema).
**Die EINE URL**, die bei beiden Providern hinterlegt sein muss:
`https://emsenhuber.cloudflareaccess.com/cdn-cgi/access/callback`
## GitHub (Client ID `Ov23li2h96hAkGRPJXYV`)
1. github.com → rechts oben aufs Profilbild → **Settings**.
2. Linke Spalte ganz unten **Developer settings** → **OAuth Apps**.
3. Die App mit Client ID `Ov23li2h96hAkGRPJXYV` öffnen.
4. **Authorization callback URL** = `https://emsenhuber.cloudflareaccess.com/cdn-cgi/access/callback`.
5. (Optional **Homepage URL** = `https://emsenhuber.cloudflareaccess.com`.)
6. **Update application** klicken.
## Google (Client ID `276709275903-b3q55lsj203v4strbhh5mub76cib867e.apps.googleusercontent.com`)
1. console.cloud.google.com → oben das richtige **Projekt** wählen.
2. **APIs & Services** → **Credentials**.
3. Unter **OAuth 2.0 Client IDs** den Client `276709275903-…apps.googleusercontent.com`
(Typ *Web application*) öffnen.
4. **Authorized redirect URIs** → **+ ADD URI** →
`https://emsenhuber.cloudflareaccess.com/cdn-cgi/access/callback`.
5. **Authorized JavaScript origins** → **+ ADD URI** → `https://emsenhuber.cloudflareaccess.com`.
6. **SAVE**. (Google-Propagation dauert teils ein paar Minuten.)
## Testen
1. Neues **privates** Browserfenster → eine Access-geschützte Seite öffnen.
2. Beim CF-Login **GitHub** bzw. **Google** wählen → muss ohne „redirect_uri"-Fehler durchlaufen,
**keine** OTP-Mail mehr.
3. Gegenprobe (optional, kann Claude read-only): CF-Audit
`GET /accounts/<acc>/access/logs/access_requests` → `identity_provider` = `github`/`google`
statt `onetimepin`.
## Hinweis
Die Team-Domain heißt `emsenhuber.cloudflareaccess.com` (das alte Org-Label `bf4…` in CF nicht
anfassen). Session gilt 720 h (30 Tage) — nach dem Fix sollte der Login also lange halten.