diff --git a/docs/teilprojekte.md b/docs/teilprojekte.md index 5d650e1..b331f1e 100644 --- a/docs/teilprojekte.md +++ b/docs/teilprojekte.md @@ -40,6 +40,11 @@ liest, liest ihn als Erstes: er wird bei jeder Änderung mitgezogen, nicht nur d unterstellte einen Registry-Pull (`fetch: no` auf ap1/ap2) und enthielt eine **falsche** Firewall-Freigabe-Behauptung. **CF-Stand:** `bf-public` `inactive` / 0 Connectoren; die vier öffentlichen Namen laufen noch über bf-mm/bf-nas/bf-pve **an Caddy vorbei** direkt aufs Backend. +- 🆕 **TP16.3 §1-Blocker remote erledigt (2026-08-31):** Ingress von `bf-public` auf + `https://10.40.20.40:443` + `originServerName`; Firewall-Freigabe `vlan99 → vlan20:443` **über + Nautobot GC** (Plan `Completed`, Re-Baseline `ingest-core-firewall.py --apply`, danach + **135/135 compliant / 0 Drifts**); `ROUTER_AP3_PASS` in `~/.secrets`. **Offen bleibt nur die + Vor-Ort-Session** (§2/§3: `container.npk`, `device-mode`, Container) und danach Flip + Abbau. - 🆕 **Globale Verhaltensregeln konsolidiert (2026-08-29, TP35 Schicht 3):** `~/.config/opencode/AGENTS.md` ist jetzt die **SSoT** für globale Verhaltensregeln (Secrets, VLAN-Schema, 5 Lessons, SoC, Übergabe-Mechanik, Mid-Action-Checkpoint, Commit-Hinweis, Backup-Guard). `~/.claude/CLAUDE.md` hält denselben Block als Claude-Code-Spiegelung mit Verweis auf die SSoT. opencode liest AGENTS.md mit Vorrang vor `~/.claude/CLAUDE.md`. - **Fünf MikroTik seit 2026-08-30** — neu dazu **`ap3`** (cAP ax `cAPGi-5HaxD2HaxD`, **`10.40.99.13`**, @@ -79,11 +84,13 @@ liest, liest ihn als Erstes: er wird bei jeder Änderung mitgezogen, nicht nur d account-weite). Abnahme über den Host-Header von einem zweiten Host: 11× 200, `nautobot` 302. Offen: **Schritt 5–6** (Connector für `bf-public`, CNAME-Flip, Abbau der sechs Container) — **Runbook steht: [`tp16.3-bf-public-ap-connector-runbook.md`](tp16.3-bf-public-ap-connector-runbook.md)**, - Vor-Ort-Session an ap1/ap2/ap3. 🔴 **Zwei Blocker davor, beide remote lösbar** (08-30 gemessen): - **(a)** der `bf-public`-Ingress zeigt auf `:80`, wo Caddy mit **308 → https** antwortet ⇒ Redirect-Schleife - über Cloudflare; Fix = `https://10.40.20.40:443` + `originServerName` je Regel (über 443 mit korrekter - SNI liefern alle vier Namen 200). **(b)** es gibt **keine** Freigabe `vlan99 → vlan20:443` — der - Connector liefe in `TP5-WOULD-DROP`. + Vor-Ort-Session an ap1/ap2/ap3. ✅ **Die drei §1-Blocker sind am 2026-08-31 remote erledigt** — + **(a)** Ingress auf `https://10.40.20.40:443` + `originServerName` je Regel umgestellt (die alte + `:80`-Zeile hätte über CF eine Redirect-Schleife gebaut, weil Caddy dort 308 auf https antwortet); + **(b)** Freigabe `vlan99 → vlan20:443` **über Nautobot GC** deployt (`ip-firewall-filter` steht unter + Drift-Kontrolle, TP26 ⇒ kein Direkt-Write), Position vor `TP5: log-only` verifiziert, **135/135 + compliant, 0 Drifts**; **(c)** `ROUTER_AP3_PASS` in `~/.secrets` nachgetragen (REST-Auth 200). + ⇒ **Vor Ort startet die Arbeit bei §2/§3** (Pakete, `device-mode`, Container). - **DNS/Resolver = AdGuard-Paar `agh-bf1`/`agh-bf2`** (LXC 110/111 auf pve, **`10.40.20.36`/`.37`**, TP23 Stufe 2 + TP31 Schritt 4 ✅ seit 2026-08-26): Upstream DoH zum CF-Gateway, conditional `[/bf.emsenhuber.net/] → 10.40.20.1`, 47 Rewrites (16 Service → Caddy `.20.40` + 10 Host-Namen @@ -221,7 +228,7 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na > | TP14.4 | 🔜 | CF-Access-Token | — | > | TP16 | ✅ | CF-Tunnel HA wieder voll | 2026-08-24 | > | TP16.2 | 🔜 | Härtung bypass-Dienste | — | -> | TP16.3 | 🔜 | `bf-public`-Connector auf ap1/ap2/**ap3** (Runbook steht) | — | +> | TP16.3 | 🔜 | `bf-public`-Connector ap1/ap2/**ap3** (§1-Blocker ✅, Rest vor Ort) | — | > | TP17.1 | ❌ | Shelly Gen4 → Zigbee | 2026-08-23 | > | TP17.3 | ✅ | Shelly-Regression behoben | 2026-08-23 | > | TP18 | 🔜 | Garage-Objektspeicher | — | @@ -441,12 +448,12 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na ap1/ap2 ⇒ **zwei verschiedene `container.npk`**. Und ap3 steht auf `device-mode=basic` (nicht `home`), dort ist `fetch` bereits erlaubt — wir nutzen trotzdem auf allen dreien den `.tar`-Import, damit alle dasselbe Image fahren (gepinnt: `cloudflared 2026.6.1`, Digest `sha256:6d91c121…`, 27,5 MB). -- 🔴 **Blocker A — Redirect-Schleife.** `bf-public` zeigt auf `http://10.40.20.40:80`; Caddy antwortet +- ✅ **Blocker A — Redirect-Schleife, behoben 2026-08-31.** `bf-public` zeigt auf `http://10.40.20.40:80`; Caddy antwortet dort mit **308 → `https:///`**, also zurück durch Cloudflare in denselben Tunnel ⇒ `ERR_TOO_MANY_REDIRECTS` für alle vier Namen. **Fällt heute nicht auf**, weil die drei Alttunnel **an Caddy vorbei** direkt aufs Backend gehen — die Schleife entsteht erst mit dem Umstieg. Fix = `https://10.40.20.40:443` + `originServerName` je Regel (über 443 mit korrekter SNI: 4× 200). -- 🔴 **Blocker B — die Freigabe existiert nicht.** Die `forward`-Kette des Core wurde vollständig +- ✅ **Blocker B — die Freigabe fehlte, angelegt 2026-08-31 über Nautobot GC.** Die `forward`-Kette des Core wurde vollständig gelesen (36 Regeln, Nr. 35 = `TP5: deny-by-default`): **keine** Regel `vlan99 → vlan20` für 80/443. Die einzige MGMT→INFRA-Regel (Nr. 26) ist ein `src-port=8728`-**Rückweg** der API. ⚠️ **Der Vorgänger-Runbook behauptet das Gegenteil** („Regel 27 deckt `vlan99→vlan20:80` ab ✅") — @@ -454,7 +461,7 @@ nachmessen und dann entscheiden**. Blocker gibt es keine mehr. TP5 ist in der Na in `TP5-WOULD-DROP` + Drop. Egress zu CF (Regel 13 `LAN->WAN`) und DNS (Regeln 30–33) sind dagegen ✅. ⇒ Das `masquerade` des `veth`-Netzes ist deshalb **Pflicht**, nicht Kosmetik: sonst kommen die Pakete mit `172.17.0.2` am Core an, wo weder Route noch Regel sie kennt. -- 🟡 **Blocker C — `ROUTER_AP3_PASS` fehlt in `~/.secrets/credentials.env`** (steht nur in +- ✅ **Blocker C — `ROUTER_AP3_PASS` fehlte in `~/.secrets/credentials.env`, nachgetragen 2026-08-31** (steht nur in `~/.claude.json`), gegen die Credential-Store-Konvention. Der `sshpass -e`-Reboot-Weg braucht es dort. ⚠️ Nebenbefund: **`credentials.env` lässt sich in zsh nicht sourcen** — ab ~Zeile 69 stehen rohe WireGuard-Zeilen, zsh bricht ab und lässt die Variablen **leer**; das sieht aus wie ein ungültiger diff --git a/docs/tp16.3-bf-public-ap-connector-runbook.md b/docs/tp16.3-bf-public-ap-connector-runbook.md index 6672271..eb1c408 100644 --- a/docs/tp16.3-bf-public-ap-connector-runbook.md +++ b/docs/tp16.3-bf-public-ap-connector-runbook.md @@ -84,12 +84,21 @@ docs/cf-backup/cnames-tunnel-20260830-vor-tp16.3-schnitt.json # inkl. Record-I --- -## §1 Drei Blocker — **remote zu erledigen, BEVOR jemand in den Keller geht** +## §1 Drei Blocker — ✅ **ALLE ERLEDIGT 2026-08-31 (remote)** -> Alle drei sind vom Schreibtisch aus lösbar. Wer sie offen lässt, steht vor Ort vor einem -> Connector, der `healthy` meldet, während die Seite eine Redirect-Schleife dreht. +> ✅ **Nichts davon ist vor Ort noch zu tun.** Abschnitt bleibt als Nachweis stehen; die Fixes sind +> gemessen, nicht nur abgesetzt. **Vor Ort startet die Arbeit bei §2/§3.** +> +> | Blocker | Stand | Nachweis | +> |---|---|---| +> | **A** Redirect-Schleife (`:80`) | ✅ behoben | Ingress zeigt auf `https://10.40.20.40:443`, `originServerName` je Regel gesetzt | +> | **B** Freigabe `vlan99 → vlan20:443` | ✅ behoben | Regel via Nautobot GC deployt, Plan `Completed`, am Gerät verifiziert, **135/135 compliant, 0 Drifts** | +> | **C** `ROUTER_AP3_PASS` | ✅ behoben | in `~/.secrets/credentials.env` (`chmod 600`), REST-Auth gegen ap3 = **HTTP 200** | -### 1.1 🔴 Blocker A — `bf-public` zeigt auf `:80`, und Caddy antwortet dort mit 308 +### 1.1 ✅ Blocker A — `bf-public` zeigte auf `:80`, und Caddy antwortet dort mit 308 + +> **Erledigt 2026-08-31.** Ingress zurückgelesen: alle vier Namen → `https://10.40.20.40:443`, +> `SNI` = der jeweilige Hostname. Der `PUT` unten ist der ausgeführte Stand, nicht mehr eine Aufgabe. Gemessen: `curl -H "Host: vw.emsenhuber.net" http://10.40.20.40/` → **`308` → `Location: https://vw.emsenhuber.net/`**. @@ -117,7 +126,17 @@ curl -s -X PUT -H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: applic **Abnahme:** `.success == true`, danach Ingress zurücklesen und die vier `https://…:443` sehen. -### 1.2 🔴 Blocker B — die Firewall lässt MGMT → Caddy **nicht** durch +### 1.2 ✅ Blocker B — die Firewall liess MGMT → Caddy **nicht** durch + +> **Erledigt 2026-08-31 über Nautobot Golden Config** (`gc-manual-plan.py --device crs326-core --deploy`, +> Change-ID `TP16.3-BlockerB`, Plan `23e5b667-…` **Completed**), **nicht** per Direkt-Write — `ip-firewall-filter` +> steht unter Drift-Kontrolle (TP26). Backup vorher: `core-pre-tp16.3-blockerB-20260831.backup` (TP22-Regel 3). +> Danach `ingest-core-firewall.py --apply` (Re-Baseline) + `--refresh-compliance` ⇒ **135/135, 0 Drifts.** +> **Position verifiziert:** die Regel sitzt direkt **vor** `TP5: log-only` und `TP5: deny-by-default`. +> **Funktional verifiziert:** `/tool fetch` von ap3 auf `https://10.40.20.40` erreicht Caddy und bekommt +> einen **TLS-Alert von Caddy selbst** — ein Alert kann nur vom Server kommen, das Paket ist also da. +> Der Alert ist die **SNI-Abweisung** (Gegenprobe: ohne SNI `000`, mit korrektem SNI `200`) und genau +> der Grund, warum `originServerName` in §1.1 gesetzt ist. **Kein Fehler, sondern der Beweis.** Die `forward`-Kette des Core wurde vollständig gelesen (36 Regeln, Nr. 35 = `TP5: deny-by-default`). **Es gibt keine Regel `vlan99 → vlan20` für 80/443.** Die einzige Regel in dieser Richtung ist @@ -154,7 +173,10 @@ Ohne die Regel unten läuft der Connector in Regel 34 (`TP5-WOULD-DROP`, Log) un `veth`-Netz `172.17.0.0/24` ist dem Core unbekannt und hätte keinen Rückweg. Deshalb ist das `masquerade` in §3.4 **nicht optional**, sondern die Voraussetzung dieser Regel. -### 1.3 🟡 Blocker C — `ROUTER_AP3_PASS` fehlt in `~/.secrets/credentials.env` +### 1.3 ✅ Blocker C — `ROUTER_AP3_PASS` fehlte in `~/.secrets/credentials.env` + +> **Erledigt 2026-08-31.** `ROUTER_AP3_USER`/`_PASS` nachgetragen, Datei `chmod 600`, +> Sicherung `~/.secrets/credentials.env.bak-20260831`. Funktionsbeweis: REST-Auth gegen ap3 = **HTTP 200**. Vorhanden sind `ROUTER_AP1_PASS`, `ROUTER_AP2_PASS`, `CRS326_CORE_PASS`, `CRS326_BRANCH_PASS`. Das **ap3-Passwort steht nur in `~/.claude.json`** (MCP-Env) — gegen die globale Konvention