Node-Transport: UI-Toggle 'Verbindung über VPN' → setzt Klartext-Opt-in im Install-Script (Default https/wss) #189

Closed
opened 2026-06-26 14:42:30 +00:00 by chinux · 4 comments
Owner

Ziel

Beim Hinzufuegen/Bearbeiten eines Nodes in der UI ein Schalter "Verbindung ueber VPN" (Default: aus). Ist er an, setzt das Install-Script den Transport-Trust-Schalter in die agent.conf → der Agent erlaubt fuer diesen Host Klartext-Transport (ws:///http://), weil VPN den Transport bereits absichert. Jederzeit revidierbar (Toggle aendern → neu enrollen/Script neu ausrollen).

Hintergrund

Default ist wss:///https://-Zwang (public-sicher, #113 Phase 1 + #187). VPN-Hosts (NetBird/WireGuard) haben oft kein gueltiges oeffentliches Zert fuer die interne Adresse → der Zwang wuerde sie aussperren. Ueber VPN ist Klartext aber unkritisch (Transport schon verschluesselt+authentifiziert). Loesung: explizites, UI-gesteuertes Opt-in pro Host — nie stiller Klartext-Default.

Backend / Modell

  • Node.vpn_transport (Boolean, default False) — Migration konsistent zur Kette (aktueller Head 0025 → 0026).
  • Node-Anlage-/Edit-Endpoint (admin_router) nimmt das Feld entgegen (nur operator/admin, scope-gepft).
  • Install-Script-Generierung (server/main.py, agent.conf-Block ~:882): wenn node.vpn_transport → Zeile TRUSTED_TRANSPORT=vpn (Name final mit #187 abstimmen) in die agent.conf schreiben; sonst weglassen.
  • Hinweis: bei VPN-Transport darf SERVER_URL auch http(s)/ws(s) zur internen Adresse sein — das Install-Script soll dann NICHT den https-Pflicht-400er (#113 Phase 1) werfen.

Frontend

  • Im "Node hinzufuegen"- und "Node-Einstellungen"-Dialog ein Toggle "Verbindung ueber VPN (kein oeffentliches Zertifikat noetig)" mit kurzer Erklaerung.
  • Anzeige am Node, ob VPN-Transport aktiv (Badge), damit der Betrieb sieht, welche Hosts im Klartext-ueber-VPN-Modus laufen.
  • Aendern des Toggles → Hinweis "Agent muss mit neuem Install-Script neu ausgerollt/enrollt werden" (revidierbar).

Abgrenzung / Bezug

  • Der Agent-Teil (config.rs liest den Schalter, validate_server_url + Self-Update beachten ihn) ist in #187.
  • Dieses Issue = UI + Backend + Install-Script + Modell.
  • Default bleibt der scharfe https/wss-Zwang; dies ist reines Opt-in.

Akzeptanz

  • UI-Toggle beim Node-Anlegen/-Bearbeiten; Default aus.
  • Bei "an": Install-Script setzt den Transport-Trust-Schalter; Agent verbindet/aktualisiert ueber VPN auch via ws/http; sha256-Check + #185-Auth unveraendert.
  • Bei "aus": unveraenderter https/wss-Zwang.
  • Toggle revidierbar (Re-Enroll/Script-Neuausrollung).

Branch

feat/vpn-transport-toggle

## Ziel Beim **Hinzufuegen/Bearbeiten eines Nodes in der UI** ein Schalter **"Verbindung ueber VPN"** (Default: aus). Ist er an, setzt das **Install-Script** den Transport-Trust-Schalter in die `agent.conf` → der Agent erlaubt fuer diesen Host Klartext-Transport (`ws://`/`http://`), weil VPN den Transport bereits absichert. Jederzeit **revidierbar** (Toggle aendern → neu enrollen/Script neu ausrollen). ## Hintergrund Default ist `wss://`/`https://`-Zwang (public-sicher, #113 Phase 1 + #187). VPN-Hosts (NetBird/WireGuard) haben oft kein gueltiges oeffentliches Zert fuer die interne Adresse → der Zwang wuerde sie aussperren. Ueber VPN ist Klartext aber unkritisch (Transport schon verschluesselt+authentifiziert). Loesung: **explizites, UI-gesteuertes Opt-in pro Host** — nie stiller Klartext-Default. ## Backend / Modell - `Node.vpn_transport` (Boolean, default False) — Migration konsistent zur Kette (aktueller Head 0025 → 0026). - Node-Anlage-/Edit-Endpoint (admin_router) nimmt das Feld entgegen (nur operator/admin, scope-gepft). - **Install-Script-Generierung** (`server/main.py`, agent.conf-Block ~:882): wenn `node.vpn_transport` → Zeile `TRUSTED_TRANSPORT=vpn` (Name final mit #187 abstimmen) in die agent.conf schreiben; sonst weglassen. - Hinweis: bei VPN-Transport darf `SERVER_URL` auch `http(s)`/`ws(s)` zur internen Adresse sein — das Install-Script soll dann NICHT den https-Pflicht-400er (#113 Phase 1) werfen. ## Frontend - Im "Node hinzufuegen"- und "Node-Einstellungen"-Dialog ein Toggle **"Verbindung ueber VPN (kein oeffentliches Zertifikat noetig)"** mit kurzer Erklaerung. - Anzeige am Node, ob VPN-Transport aktiv (Badge), damit der Betrieb sieht, welche Hosts im Klartext-ueber-VPN-Modus laufen. - Aendern des Toggles → Hinweis "Agent muss mit neuem Install-Script neu ausgerollt/enrollt werden" (revidierbar). ## Abgrenzung / Bezug - Der **Agent-Teil** (config.rs liest den Schalter, validate_server_url + Self-Update beachten ihn) ist in **#187**. - Dieses Issue = **UI + Backend + Install-Script + Modell**. - Default bleibt der scharfe https/wss-Zwang; dies ist reines Opt-in. ## Akzeptanz - UI-Toggle beim Node-Anlegen/-Bearbeiten; Default aus. - Bei "an": Install-Script setzt den Transport-Trust-Schalter; Agent verbindet/aktualisiert ueber VPN auch via ws/http; sha256-Check + #185-Auth unveraendert. - Bei "aus": unveraenderter https/wss-Zwang. - Toggle revidierbar (Re-Enroll/Script-Neuausrollung). ## Branch `feat/vpn-transport-toggle`
Author
Owner

ERWEITERUNG — welche SERVER_URL das Install-Script ausliefert (Kern!)

Heute packt das Script eine globale SERVER_URL in jede agent.conf (main.py:30). Fuer Mischbetrieb (manche public, manche VPN) reicht das nicht — der Toggle muss auch die richtige Erreichbarkeit waehlen, nicht nur das Klartext-Flag.

Backend kennt zwei Basis-Adressen

  • SERVER_URL_PUBLIC (ENV) — oeffentliche Domain, z. B. https://agent.example.com → wird zu wss:// + https://.
  • SERVER_URL_VPN (ENV) — VPN-interne Default-Adresse, z. B. http://172.16.1.10:8765 (NetBird-IP) → bleibt ws:///http://.
  • (SERVER_URL als Legacy/Fallback fuer Public weiter erlaubt.)

Pro-Node-Override (Entscheidung: "beides")

  • Neues Feld Node.vpn_server_url (nullable). Ist es gesetzt UND Toggle an → diese Adresse nutzen; sonst der globale SERVER_URL_VPN. Erlaubt Hosts in abweichendem Subnetz/Standort.

Auswahl-Logik beim Install-Script-Abruf (pro Node)

  • Toggle AUS (public): Basis = SERVER_URL_PUBLICwss://…/ws/agent + https://…-Download. https-Zwang greift (kein TRUSTED_TRANSPORT).
  • Toggle AN (VPN): Basis = node.vpn_server_url falls gesetzt, sonst SERVER_URL_VPNws://<vpn>/ws/agent + http://<vpn>-Download + TRUSTED_TRANSPORT=vpn in die agent.conf. Der https-Pflicht-400er (#113 Phase 1) wird fuer diesen Fall NICHT geworfen.
  • Validierung: Toggle AN aber weder vpn_server_url noch SERVER_URL_VPN gesetzt → klare Fehlermeldung beim Script-Abruf (nicht still public-URL ausliefern).

UI

  • Toggle "Verbindung ueber VPN" + (optional, eingeblendet wenn an) Feld "VPN-Adresse (leer = globaler Default)" = vpn_server_url.
  • Badge am Node: public / VPN(+Adresse).

Modell/Migration

  • Node.vpn_transport (Bool) + Node.vpn_server_url (String, nullable). Migration Head 0025 → 0026.

Akzeptanz (ergaenzt)

  • Public-Node bekommt Domain+wss/https; VPN-Node bekommt VPN-IP+ws/http+TRUSTED_TRANSPORT.
  • Pro-Node-VPN-Adresse ueberschreibt den globalen VPN-Default.
  • Toggle AN ohne jede VPN-Adresse → Fehler, kein stilles Public-Fallback.

.env / Doku

SERVER_URL_PUBLIC + SERVER_URL_VPN in .env.example + Deployment-Public.md dokumentieren.

## ERWEITERUNG — welche SERVER_URL das Install-Script ausliefert (Kern!) Heute packt das Script **eine globale `SERVER_URL`** in jede agent.conf (main.py:30). Fuer Mischbetrieb (manche public, manche VPN) reicht das nicht — der Toggle muss auch die **richtige Erreichbarkeit** waehlen, nicht nur das Klartext-Flag. ### Backend kennt zwei Basis-Adressen - `SERVER_URL_PUBLIC` (ENV) — oeffentliche Domain, z. B. `https://agent.example.com` → wird zu `wss://` + `https://`. - `SERVER_URL_VPN` (ENV) — VPN-interne Default-Adresse, z. B. `http://172.16.1.10:8765` (NetBird-IP) → bleibt `ws://`/`http://`. - (`SERVER_URL` als Legacy/Fallback fuer Public weiter erlaubt.) ### Pro-Node-Override (Entscheidung: "beides") - Neues Feld **`Node.vpn_server_url`** (nullable). Ist es gesetzt UND Toggle an → diese Adresse nutzen; sonst der globale `SERVER_URL_VPN`. Erlaubt Hosts in abweichendem Subnetz/Standort. ### Auswahl-Logik beim Install-Script-Abruf (pro Node) - **Toggle AUS (public):** Basis = `SERVER_URL_PUBLIC` → `wss://…/ws/agent` + `https://…`-Download. https-Zwang greift (kein TRUSTED_TRANSPORT). - **Toggle AN (VPN):** Basis = `node.vpn_server_url` falls gesetzt, sonst `SERVER_URL_VPN` → `ws://<vpn>/ws/agent` + `http://<vpn>`-Download **+** `TRUSTED_TRANSPORT=vpn` in die agent.conf. Der https-Pflicht-400er (#113 Phase 1) wird fuer diesen Fall NICHT geworfen. - Validierung: Toggle AN aber weder `vpn_server_url` noch `SERVER_URL_VPN` gesetzt → klare Fehlermeldung beim Script-Abruf (nicht still public-URL ausliefern). ### UI - Toggle "Verbindung ueber VPN" + (optional, eingeblendet wenn an) Feld **"VPN-Adresse (leer = globaler Default)"** = `vpn_server_url`. - Badge am Node: public / VPN(+Adresse). ### Modell/Migration - `Node.vpn_transport` (Bool) + `Node.vpn_server_url` (String, nullable). Migration Head 0025 → 0026. ### Akzeptanz (ergaenzt) - Public-Node bekommt Domain+wss/https; VPN-Node bekommt VPN-IP+ws/http+TRUSTED_TRANSPORT. - Pro-Node-VPN-Adresse ueberschreibt den globalen VPN-Default. - Toggle AN ohne jede VPN-Adresse → Fehler, kein stilles Public-Fallback. ## .env / Doku `SERVER_URL_PUBLIC` + `SERVER_URL_VPN` in `.env.example` + Deployment-Public.md dokumentieren.
Author
Owner

ERWEITERUNG — auch in den Einstellungen bestehender Nodes

Der VPN-Toggle (+ optionales vpn_server_url-Feld) muss nicht nur beim Anlegen, sondern auch nachtraeglich umschaltbar sein:

  • Frontend: NodeSettingsModal.svelte (Bestands-Node bearbeiten) bekommt denselben Toggle "Verbindung ueber VPN" + Adressfeld wie der Anlegen-Dialog (neben den bestehenden Feldern scan_range/internal_network).
  • Backend: PATCH /nodes/{node_name} (update_node, admin_router.py:263) + NodeUpdateRequest um vpn_transport (Bool) und vpn_server_url (str|null) erweitern — analog zum bestehenden internal_network-Handling (:272).

WICHTIG — Umschalten wirkt nicht "magisch" (klar kommunizieren)

Der Transport-Modus steht in der agent.conf auf dem Host (TRUSTED_TRANSPORT + SERVER_URL). Ein DB-Toggle aendert den laufenden Agent NICHT von selbst. Nach dem Umschalten muss der Agent neu konfiguriert / per neuem Install-Script ausgerollt werden (bzw. der Wert in agent.conf angepasst + Agent-Restart). Daher:

  • Beim Speichern eines geaenderten Toggles in der UI ein deutlicher Hinweis: "Aenderung wird erst nach Neu-Ausrollen/Neukonfiguration des Agents auf dem Host wirksam — Install-Script erneut ausfuehren."
  • Optional: Badge/Status "Transport-Aenderung ausstehend", bis der Agent mit dem neuen Modus reconnectet (z. B. wenn der gemeldete Modus vom DB-Wert abweicht).
  • Da der Host-Wechsel public↔VPN ohnehin eine andere SERVER_URL bedeutet, ist Re-Ausrollen der ehrliche Weg — kein Versuch, den Schalter "remote live" umzubiegen.

Akzeptanz (ergaenzt)

  • Toggle + VPN-Adresse in NodeSettingsModal editierbar; PATCH persistiert beide Felder.
  • Nach Aenderung klarer UI-Hinweis auf noetiges Re-Ausrollen; kein stilles "wirkt sofort".
## ERWEITERUNG — auch in den Einstellungen bestehender Nodes Der VPN-Toggle (+ optionales `vpn_server_url`-Feld) muss **nicht nur beim Anlegen**, sondern auch nachtraeglich umschaltbar sein: - **Frontend:** `NodeSettingsModal.svelte` (Bestands-Node bearbeiten) bekommt denselben Toggle "Verbindung ueber VPN" + Adressfeld wie der Anlegen-Dialog (neben den bestehenden Feldern scan_range/internal_network). - **Backend:** `PATCH /nodes/{node_name}` (`update_node`, admin_router.py:263) + `NodeUpdateRequest` um `vpn_transport` (Bool) und `vpn_server_url` (str|null) erweitern — analog zum bestehenden `internal_network`-Handling (:272). ## WICHTIG — Umschalten wirkt nicht "magisch" (klar kommunizieren) Der Transport-Modus steht in der **`agent.conf` auf dem Host** (TRUSTED_TRANSPORT + SERVER_URL). Ein DB-Toggle aendert den laufenden Agent NICHT von selbst. Nach dem Umschalten muss der Agent **neu konfiguriert / per neuem Install-Script ausgerollt** werden (bzw. der Wert in agent.conf angepasst + Agent-Restart). Daher: - Beim Speichern eines geaenderten Toggles in der UI ein **deutlicher Hinweis**: "Aenderung wird erst nach Neu-Ausrollen/Neukonfiguration des Agents auf dem Host wirksam — Install-Script erneut ausfuehren." - Optional: Badge/Status "Transport-Aenderung ausstehend", bis der Agent mit dem neuen Modus reconnectet (z. B. wenn der gemeldete Modus vom DB-Wert abweicht). - Da der Host-Wechsel public↔VPN ohnehin eine andere SERVER_URL bedeutet, ist Re-Ausrollen der ehrliche Weg — kein Versuch, den Schalter "remote live" umzubiegen. ## Akzeptanz (ergaenzt) - Toggle + VPN-Adresse in NodeSettingsModal editierbar; PATCH persistiert beide Felder. - Nach Aenderung klarer UI-Hinweis auf noetiges Re-Ausrollen; kein stilles "wirkt sofort".
Author
Owner

Bearbeitet zusammen mit #187 (gemeinsamer TRUSTED_TRANSPORT-Vertrag, auf Agent- und Backend-Seite identisch). Issue bleibt offen.

Commits: Agent `0416d9f` · Backend `198f8b5` · Frontend `b1a8a10` · Doku `727f25f`

Geteilter Vertrag: agent.conf-Schlüssel `TRUSTED_TRANSPORT=vpn` — Backend schreibt ihn bei VPN-Nodes, Agent liest ihn. Default ohne Schlüssel = scharf (wss/https, außer localhost).

  • Agent (config.rs): `TRUSTED_TRANSPORT` via pick aus agent.conf; `validate_server_url` lässt `ws://` zu bei localhost ODER `TRUSTED_TRANSPORT=vpn`, sonst harter Startfehler. Selbe Regel defensiv für den Self-Update-http-Download.
  • Backend (models/node.py + Migration 0026): `nodes.vpn_transport` (Bool) + `nodes.vpn_server_url` (Pro-Node-Override), beide in to_dict(). ENV `SERVER_URL_PUBLIC` (Default = SERVER_URL Legacy/Fallback) + `SERVER_URL_VPN`. `/install/{token}`: Toggle aus → SERVER_URL_PUBLIC, wss/https, #113-400er greift; Toggle an → vpn_server_url sonst SERVER_URL_VPN, ws/http + `TRUSTED_TRANSPORT=vpn`; an ohne jede Adresse → 400. provision + PATCH (admin_router.py) nehmen die Felder.
  • Frontend (`b1a8a10`): VPN-Toggle + Adress-Feld in ProvisionModal (anlegen) + NodeSettingsModal (bearbeiten, Hinweis „erst nach erneutem Ausrollen wirksam"); Badge 🌐 public / 🔒 VPN (+Adresse).

Live smoke-getestet: VPN+Pro-Node-Adresse → `ws://172.16.1.99:8765/ws/agent` + `SERVER_HTTP=http://…` + `TRUSTED_TRANSPORT=vpn`; Pro-Node-Override schlägt globalen Default; VPN an ohne jede Adresse → 400 (kein stilles Public-Fallback).

Akzeptanz: Schalter Agent+Backend identisch; Scheme/Adresse je Toggle korrekt; Override > Default; 400 statt Fallback; Toggle in Anlegen UND Bearbeiten, PATCH persistiert, Re-Ausroll-Hinweis.

⚠️ Deploy: `alembic upgrade head` (Migration 0026) + ENV `SERVER_URL_PUBLIC`/`SERVER_URL_VPN` setzen; Node-Agent neu bauen/ausrollen.

Bearbeitet zusammen mit #187 (gemeinsamer TRUSTED_TRANSPORT-Vertrag, auf Agent- und Backend-Seite identisch). Issue bleibt offen. **Commits:** Agent \`0416d9f\` · Backend \`198f8b5\` · Frontend \`b1a8a10\` · Doku \`727f25f\` **Geteilter Vertrag:** agent.conf-Schlüssel \`TRUSTED_TRANSPORT=vpn\` — Backend schreibt ihn bei VPN-Nodes, Agent liest ihn. Default ohne Schlüssel = scharf (wss/https, außer localhost). - **Agent** ([config.rs](Node-Agent/src/config.rs)): \`TRUSTED_TRANSPORT\` via pick aus agent.conf; \`validate_server_url\` lässt \`ws://\` zu bei localhost ODER \`TRUSTED_TRANSPORT=vpn\`, sonst harter Startfehler. Selbe Regel defensiv für den Self-Update-http-Download. - **Backend** ([models/node.py](server/models/node.py) + Migration [0026](server/migrations/versions/0026_node_vpn_transport.py)): \`nodes.vpn_transport\` (Bool) + \`nodes.vpn_server_url\` (Pro-Node-Override), beide in to_dict(). ENV \`SERVER_URL_PUBLIC\` (Default = SERVER_URL Legacy/Fallback) + \`SERVER_URL_VPN\`. \`/install/{token}\`: Toggle aus → SERVER_URL_PUBLIC, wss/https, #113-400er greift; Toggle an → vpn_server_url sonst SERVER_URL_VPN, ws/http + \`TRUSTED_TRANSPORT=vpn\`; an ohne jede Adresse → 400. provision + PATCH ([admin_router.py](server/routers/admin_router.py)) nehmen die Felder. - **Frontend** (\`b1a8a10\`): VPN-Toggle + Adress-Feld in ProvisionModal (anlegen) + NodeSettingsModal (bearbeiten, Hinweis „erst nach erneutem Ausrollen wirksam"); Badge 🌐 public / 🔒 VPN (+Adresse). **Live smoke-getestet:** VPN+Pro-Node-Adresse → \`ws://172.16.1.99:8765/ws/agent\` + \`SERVER_HTTP=http://…\` + \`TRUSTED_TRANSPORT=vpn\`; Pro-Node-Override schlägt globalen Default; VPN an ohne jede Adresse → 400 (kein stilles Public-Fallback). **Akzeptanz:** Schalter Agent+Backend identisch; Scheme/Adresse je Toggle korrekt; Override > Default; 400 statt Fallback; Toggle in Anlegen UND Bearbeiten, PATCH persistiert, Re-Ausroll-Hinweis. ⚠️ **Deploy:** \`alembic upgrade head\` (Migration 0026) + ENV \`SERVER_URL_PUBLIC\`/\`SERVER_URL_VPN\` setzen; Node-Agent neu bauen/ausrollen.
Author
Owner

Verifiziert @ 727f25f → erfüllt, wird geschlossen.

  • Modell: Node.vpn_transport + Node.vpn_server_url, Migration 0026 (1 Head, Kette OK) ✓
  • Zwei Backend-Adressen SERVER_URL_PUBLIC/SERVER_URL_VPN; geteilter Vertrag TRUSTED_TRANSPORT=vpn Backend↔Agent identisch (main.py:962 ↔ config.rs:39) ✓
  • Install-Scheme-Logik: Toggle aus → PUBLIC + wss/https-Zwang; an → vpn_server_url sonst SERVER_URL_VPN → ws/http + Flag; beide leer → 400 (kein stilles Public-Fallback, main.py) ✓
  • Frontend: Toggle in Node-Anlegen + NodeSettingsModal (Bearbeiten) + Badge + Re-Ausroll-Hinweis ✓; PATCH persistiert beide Felder ✓
  • Live: Backend+Frontend neu gebaut, Migration = alembic head, svelte-check 0 Fehler.

Deploy: alembic upgrade head (0026), SERVER_URL_PUBLIC/SERVER_URL_VPN setzen, Node-Agent lokal neu bauen (jetzt mit ureq-json-Fix 903ea4f) + ausrollen.

**Verifiziert @ 727f25f → erfüllt, wird geschlossen.** - Modell: `Node.vpn_transport` + `Node.vpn_server_url`, Migration **0026** (1 Head, Kette OK) ✓ - Zwei Backend-Adressen `SERVER_URL_PUBLIC`/`SERVER_URL_VPN`; **geteilter Vertrag** `TRUSTED_TRANSPORT=vpn` Backend↔Agent identisch (main.py:962 ↔ config.rs:39) ✓ - Install-Scheme-Logik: Toggle aus → PUBLIC + wss/https-Zwang; an → `vpn_server_url` sonst `SERVER_URL_VPN` → ws/http + Flag; **beide leer → 400** (kein stilles Public-Fallback, main.py) ✓ - Frontend: Toggle in Node-Anlegen **+ NodeSettingsModal** (Bearbeiten) + Badge + Re-Ausroll-Hinweis ✓; PATCH persistiert beide Felder ✓ - Live: Backend+Frontend neu gebaut, Migration = alembic head, svelte-check 0 Fehler. **Deploy:** `alembic upgrade head` (0026), `SERVER_URL_PUBLIC`/`SERVER_URL_VPN` setzen, Node-Agent lokal neu bauen (jetzt mit ureq-json-Fix 903ea4f) + ausrollen.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
chinux/theProx#189
No description provided.