From cf09e404ef61f9f57876f51c385dc66f0295bb27 Mon Sep 17 00:00:00 2001 From: ALI YESILKAYA Date: Tue, 7 Jul 2026 11:13:45 +0200 Subject: [PATCH] =?UTF-8?q?feat(portal):=20acc=C3=A8s=20Internet=20direct?= =?UTF-8?q?=20au=20portail=20(kaya.freeboxos.fr:9080)=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(wireguard): accès distant au lab via VPN (Freebox 51820/udp → s01) - rôle wireguard : serveur wg0 (10.99.0.0/24) sur storage-01, profils clients générés dans /etc/wireguard/clients/ (fichier .conf / QR code) - gateway : filtrage nftables par pair — full (tout le lab) / portal (uniquement Traefik :80 = portail Guacamole), masquerade VPN→cluster - dnsmasq : bind-dynamic + écoute wg0 → *.lab.local résolu dans le tunnel - pairs initiaux : alkatrazz (full), invite-01 (portal) - vault : clés WireGuard + reprise de l'archive Authentik (remplace #78) - doc : admin/infra/wireguard.md (onboarding pair, pièges, exploitation) Co-Authored-By: Claude Fable 5 * feat(portal): accès Internet direct — kaya.freeboxos.fr:9080 Choix simplicité (2026-07-07) : exposition directe du portail plutôt que le VPN (WireGuard reste déployé mais dormant, sans redirection Freebox). - gateway : DNAT 9080/tcp → Traefik (192.168.10.200:80) + rate-limit 30 connexions neuves/min sur le trafic Internet (LAN non concerné) - IngressRoute guacamole : host kaya.freeboxos.fr accepté - Guacamole : formulaire local en premier ("*, openid") — l'accès externe passe par des comptes locaux, Authentik n'est pas exposé (SSO = LAN) - doc : section « Accès externe » dans admin/k8s/auth-portal.md Co-Authored-By: Claude Fable 5 --------- Co-authored-by: Claude Fable 5 --- CLAUDE.md | 4 +-- admin/k8s/auth-portal.md | 33 ++++++++++++++----- .../roles/gateway/templates/nftables.conf.j2 | 10 ++++++ k8s/apps/guacamole/deployment.yaml | 9 +++-- k8s/apps/guacamole/ingress.yaml | 2 +- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b2a2845..2ca449f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,8 +21,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co - ✅ SearXNG opérationnel — `searxng.lab.local`, namespace `ai`, **méta-moteur de recherche web self-host** (privé, in-cluster) consommé par l'outil `web_search` d'Asa (API JSON). Manifests `k8s/apps/searxng/` - ✅ Ghostfolio opérationnel — `ghostfolio.lab.local`, namespace `ai`, suivi de portefeuille (PostgreSQL s01 + Redis in-cluster) - ✅ hermes-auto-improve — analyse quotidienne de `admin/` par Hermes à 22h (n8n → trigger :9095), PR sur `hermes/daily-work` -- 🆕 Annuaire + portail consoles (2026-07-06) — **Authentik** (`auth.lab.local`, IdP OIDC) + **Guacamole** (`portail.lab.local`, consoles SSH web vers s01/g01 via user `console` sans sudo), namespace `auth`. Config initiale (admin Authentik, provider OIDC, connexions) : voir `admin/k8s/auth-portal.md` -- 🆕 WireGuard (2026-07-06) — accès distant au lab via `kaya.freeboxos.fr:51820/udp` (Freebox → s01), pairs `full` (admin) / `portal` (invités = portail Guacamole seul, filtrage nftables). Voir `admin/infra/wireguard.md` +- 🆕 Annuaire + portail consoles (2026-07-06) — **Authentik** (`auth.lab.local`, IdP OIDC) + **Guacamole** (`portail.lab.local`, consoles SSH web vers s01/g01 via user `console` sans sudo), namespace `auth`. Config initiale (admin Authentik, provider OIDC, connexions) : voir `admin/k8s/auth-portal.md`. **Accès Internet** : `kaya.freeboxos.fr:9080` (comptes locaux Guacamole, Authentik non exposé, rate-limit nftables) +- 🆕 WireGuard (2026-07-06) — serveur VPN prêt sur s01 (pairs `full`/`portal`, filtrage nftables) mais **dormant** : pas de redirection Freebox `51820/udp` (choix simplicité 2026-07-07, accès portail via `:9080` direct). Voir `admin/infra/wireguard.md` - ⏳ WOL compute nodes non configuré (BIOS) — allumage manuel requis Journal de progression : `PROGRESS.md` → `progress/YYYY-MM-DD.md` diff --git a/admin/k8s/auth-portal.md b/admin/k8s/auth-portal.md index 4281230..a2bd079 100644 --- a/admin/k8s/auth-portal.md +++ b/admin/k8s/auth-portal.md @@ -85,20 +85,37 @@ kubectl -n auth create secret generic guacamole-secret \ 3. Settings → Users : les comptes Authentik apparaissent après leur **premier login** (`POSTGRESQL_AUTO_CREATE_ACCOUNTS=true`) → leur assigner les connexions (READ). +## Accès externe (Internet) — `kaya.freeboxos.fr:9080` + +Le portail est joignable depuis Internet **sans VPN** (choix assumé 2026-07-07, +simplicité d'abord — le VPN WireGuard reste dispo, cf. `admin/infra/wireguard.md`) : + +- **Chaîne** : `kaya.freeboxos.fr:9080` → redirection Freebox `9080/tcp → funk-s01` + → DNAT nftables `→ 192.168.10.200:80` (Traefik) → IngressRoute (host + `kaya.freeboxos.fr` accepté) → Guacamole +- **Auth externe = comptes locaux Guacamole** (Settings → Users → New user + mot de + passe fort + cocher ses connexions). **Authentik n'est PAS exposé** : le SSO ne + fonctionne que du LAN (le lien « OpenID » échoue depuis Internet — normal). +- **Garde-fous** : rate-limit nftables (30 connexions neuves/min) + anti-bruteforce + Guacamole (5 échecs → ~5 min) + mots de passe forts obligatoires. ⚠️ HTTP **non + chiffré** : mots de passe des comptes locaux interceptables en théorie — ne pas + réutiliser un mot de passe important, et envisager TLS (vrai domaine + Let's + Encrypt) ou l'option TOTP de Guacamole si l'usage s'installe. + ## Pièges / notes -1. **Tout est en HTTP** (pas de TLS sur `*.lab.local`) — OK pour un LAN privé, mais ne - **jamais** exposer le portail sur Internet en l'état. +1. **Tout est en HTTP** (pas de TLS) — accepté y compris pour l'accès Internet + (cf. section ci-dessus), avec garde-fous réseau + mots de passe dédiés. 2. **JWKS via le Service interne** (`authentik.auth.svc.cluster.local:9000`) : l'appel serveur→serveur de Guacamole ne dépend pas de la résolution `lab.local` des pods. L'issuer, lui, reste `http://auth.lab.local/...` (doit matcher le claim `iss` des tokens émis via le navigateur). -3. **`EXTENSION_PRIORITY="openid, *"`** : arrivée sur le portail = **redirection - immédiate vers Authentik** (pas de formulaire local). Conséquence : `guacadmin` est - inaccessible — l'admin Guacamole passe par un compte SSO auquel on a coché - **« Administer system »** (fait pour `Alkatrazz`). Prérequis absolu avant d'activer : - avoir donné ce droit, sinon plus d'admin. Dépannage si Authentik est HS : remettre - `"*, openid"` dans `k8s/apps/guacamole/deployment.yaml` (le formulaire local revient). +3. **`EXTENSION_PRIORITY="*, openid"`** : formulaire local affiché en premier (requis + pour les comptes locaux de l'accès Internet), lien « OpenID » en dessous pour le SSO + LAN. La variante `"openid, *"` (redirection SSO immédiate, testée puis abandonnée + le 2026-07-07) est incompatible avec l'accès externe sans exposer Authentik. + NB : le compte SSO `Alkatrazz` a « Administer system » — admin possible par les + deux chemins. 4. **Le slug de l'application Authentik doit être exactement `guacamole`** : Authentik le génère depuis le nom (« Portail consoles » → `portail-consoles`) et l'issuer/JWKS deviennent faux → log Guacamole `Non 200 status code (404) ... /o/guacamole/jwks/` diff --git a/ansible/roles/gateway/templates/nftables.conf.j2 b/ansible/roles/gateway/templates/nftables.conf.j2 index 7242c8d..75e198a 100644 --- a/ansible/roles/gateway/templates/nftables.conf.j2 +++ b/ansible/roles/gateway/templates/nftables.conf.j2 @@ -77,6 +77,13 @@ table inet filter { ip daddr 192.168.10.20 tcp dport { 7777, 8888 } ct state new,established,related accept ip daddr 192.168.10.20 udp dport 7777 ct state new,established,related accept + # Portail public — trafic Internet DNATé (9080 → Traefik :80). + # Rate-limit sur les connexions neuves : anti-bruteforce/scan réseau, + # en plus de la protection intégrée de Guacamole. Le LAN domestique n'est + # pas concerné (accepté par la règle 192.168.1.0/24 plus haut). + ip daddr 192.168.10.200 tcp dport 80 ct state new limit rate 30/minute burst 15 packets accept + ip daddr 192.168.10.200 tcp dport 80 ct state established,related accept + # WireGuard → lab : filtrage par pair (host_vars wireguard_peers) {% for peer in wireguard_peers | selectattr('access', 'equalto', 'full') | list %} # {{ peer.name }} — accès complet @@ -103,6 +110,9 @@ table ip nat { # (joignable via 192.168.1.200 sans route vers 192.168.10.0/24) iif {{ wan_interface }} tcp dport { 7777, 8888 } dnat to 192.168.10.20 iif {{ wan_interface }} udp dport 7777 dnat to 192.168.10.20:7777 + + # Portail Guacamole public — kaya.freeboxos.fr:9080 (redirection Freebox → s01) + iif {{ wan_interface }} tcp dport 9080 dnat to 192.168.10.200:80 } chain postrouting { diff --git a/k8s/apps/guacamole/deployment.yaml b/k8s/apps/guacamole/deployment.yaml index b5e58f2..f8c6ad7 100644 --- a/k8s/apps/guacamole/deployment.yaml +++ b/k8s/apps/guacamole/deployment.yaml @@ -59,12 +59,11 @@ spec: value: "preferred_username" - name: OPENID_SCOPE value: "openid profile email" - # OIDC prioritaire : arrivée sur le portail = redirection immédiate vers - # Authentik (pas de formulaire local). Conséquence : guacadmin devient - # inaccessible — l'admin passe par un compte SSO avec « Administer system ». - # Dépannage sans Authentik : remettre "*, openid" ici et re-sync. + # Formulaire local en premier : requis pour l'accès Internet + # (kaya.freeboxos.fr:9080 — comptes locaux Guacamole, Authentik n'étant + # pas exposé). Le lien « OpenID » reste dispo pour le SSO depuis le LAN. - name: EXTENSION_PRIORITY - value: "openid, *" + value: "*, openid" - name: TZ value: "Europe/Paris" resources: diff --git a/k8s/apps/guacamole/ingress.yaml b/k8s/apps/guacamole/ingress.yaml index a7ef817..262a3be 100644 --- a/k8s/apps/guacamole/ingress.yaml +++ b/k8s/apps/guacamole/ingress.yaml @@ -7,7 +7,7 @@ spec: entryPoints: - web routes: - - match: Host(`portail.lab.local`) + - match: Host(`portail.lab.local`) || Host(`kaya.freeboxos.fr`) kind: Rule services: - name: guacamole