Funk-lab/admin/k8s/auth-portal.md
ALI YESILKAYA fe0aa89ffa
feat(security): durcissement edge funklab.online (vraie IP client + rate-limit + TLS/headers) (#95)
- Traefik externalTrafficPolicy: Local → IP client réelle (fin du SNAT kube-proxy)
- middleware ratelimit par IP (100/min, burst 200) sur les 6 routes publiques
- middleware security-headers (HSTS, nosniff, X-Frame SAMEORIGIN, Referrer-Policy)
- TLSOption globale : plancher TLS 1.2 + ciphers modernes
- Guacamole REMOTE_IP_VALVE → ban anti-bruteforce par IP (fin du piège n°5)
- nftables : fermeture des ports Internet legacy 9080/9081 (HTTP clair redondant)
- allowCrossNamespace pour mutualiser les middlewares depuis infra
- docs : section Durcissement (public-domain.md) + CAA OVH + pièges à jour

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 22:58:24 +02:00

8.2 KiB
Raw Blame History

Annuaire + portail consoles — Authentik & Guacamole

Annuaire d'identités Authentik (IdP OIDC/LDAP) et portail Guacamole donnant accès aux consoles SSH de storage-01 et gpu-01 dans le navigateur, avec un compte unique par utilisateur. Namespace k8s : auth.

Ce document = architecture, déploiement, pièges. Voir aussi : admin/k8s/auth-portal-admin.md (administration au quotidien : utilisateurs, machines, apps du hub, révocation) et docs/portail-guide-utilisateur.md (guide à envoyer aux utilisateurs).

Vue d'ensemble

Utilisateur ──▶ portail.lab.local (Guacamole) ──login OIDC──▶ auth.lab.local (Authentik)
                        │
                        └──▶ guacd ──SSH (user « console », clé ed25519)──▶ s01 / g01
URL Service Rôle
http://auth.lab.local Authentik Annuaire : comptes, groupes, SSO OIDC
http://portail.lab.local Guacamole Portail : consoles SSH web s01/g01

Composants

  • Authentik (k8s/apps/authentik/) : server + worker (ghcr.io/goauthentik/server:2026.5.3), Redis in-cluster, PVC authentik-media (RWX, nfs), base PostgreSQL sur storage-01 (même pattern que Ghostfolio/n8n).
  • Guacamole (k8s/apps/guacamole/) : webapp guacamole/guacamole:1.6.0 + proxy guacamole/guacd:1.6.0, base PostgreSQL sur storage-01 (connexions, permissions). Le Job ArgoCD guacamole-initdb pose le schéma si absent (idempotent).
  • Ansible : rôle postgresql (bases authentik + guacamole), rôle console_user (user console sans sudo sur s01 et g01, clé publique Guacamole).

Secrets

Vault Ansible (make vault-view) :

Variable Usage
vault_pg_authentik_password Base PG authentik
vault_pg_guacamole_password Base PG guacamole
vault_console_ssh_private_key Clé privée SSH des connexions Guacamole (user console)

Secrets k8s (créés à la main, hors git, comme ghostfolio-secret) — mots de passe identiques au vault, secret-key = 48+ caractères aléatoires :

kubectl create ns auth
kubectl -n auth create secret generic authentik-secret \
  --from-literal=secret-key='<clé aléatoire>' \
  --from-literal=pg-password='<vault_pg_authentik_password>' \
  --from-literal=redis-password='<aléatoire>'
kubectl -n auth create secret generic guacamole-secret \
  --from-literal=pg-password='<vault_pg_guacamole_password>'

Déploiement (ordre)

  1. ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags postgresql,console_user
  2. ansible-playbook -i inventory.yml playbooks/gpu-01.yml --tags console_user
  3. Créer les secrets k8s ci-dessus (avant le premier sync, sinon pods en CreateContainerConfigError)
  4. Merge sur main → ArgoCD crée les Applications authentik et guacamole (~3 min)

Configuration initiale — Authentik

  1. Compte admin : ouvrir http://auth.lab.local/if/flow/initial-setup/ (valable uniquement tant qu'aucun admin n'existe) → définir mot de passe de akadmin.
  2. Provider OIDC pour Guacamole — Admin → Applications → Providers → Create → OAuth2/OpenID Provider :
    • Name : guacamole — Authorization flow : implicit-consent
    • Client type : Public (Guacamole utilise le flux implicite, pas de client secret)
    • Client ID : guacamole
    • Redirect URI : http://portail.lab.local/
    • Signing Key : sélectionner le certificat self-signed (sinon JWKS vide → login KO)
  3. Application — Applications → Create : Name Portail consoles, slug guacamole (doit correspondre à /application/o/guacamole/ configuré côté Guacamole : issuer + JWKS), Provider guacamole.
  4. Utilisateurs — Directory → Users → Create (+ groupes si besoin). Le preferred_username Authentik devient le nom de compte Guacamole.

Configuration initiale — Guacamole

  1. Se connecter en guacadmin / guacadmin (formulaire local, extension base) et changer ce mot de passe immédiatement (portail exposé à tout le LAN).
  2. Settings → Connections → New connection (×2) :
    • Protocol SSH — Hostname 192.168.10.1 (s01) ou 192.168.10.20 (g01) — Port 22
    • Username console — Private key : coller vault_console_ssh_private_key
  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) — domaine public HTTPS

Depuis le 2026-07-07, tout passe par le domaine funklab.online en HTTPS (Let's Encrypt). Authentik (auth.funklab.online) est la porte d'entrée ; le SSO fait le reste. Détail complet de la chaîne (DNS OVH, Freebox, Traefik/TLS) : admin/k8s/public-domain.md.

URL publique Service
https://auth.funklab.online Authentik — hub + login
https://portail.funklab.online Guacamole (consoles)
https://grafana.funklab.online · https://openwebui.funklab.online · https://argocd.funklab.online apps SSO
https://n8n.funklab.online n8n (login natif)
  • URL canonique = le domaine, LAN inclus (dnsmasq split-horizon : *.funklab.online → Traefik en interne). Les endpoints OIDC des apps pointent sur *.funklab.online.
  • Les anciens ports kaya.freeboxos.fr:9080/9081 (DNAT → VIPs MetalLB .202/.201) restent un chemin réseau mais le SSO ramène sur le domaine.
  • Un seul compte par personne (Authentik). Nouvelle app = nouveau provider + tuile.
  • Garde-fous : rate-limit nftables + TLS Let's Encrypt (plus de HTTP clair) + protections applicatives (Authentik lockout, Guacamole ban 5 échecs). Durcissement possible : MFA/TOTP Authentik.

Config côté Authentik (UI) — Redirect URI par app : voir le tableau de admin/k8s/public-domain.md (ex. Guacamole https://portail.funklab.online/).

Pièges / notes

  1. HTTPS sur Internet, HTTP en interne : l'accès public passe par *.funklab.online en TLS Let's Encrypt (durcissement 2026-07-07) ; les routes internes *.lab.local restent en HTTP clair (LAN de confiance). L'issuer OIDC est donc le domaine HTTPS (cf. piège n°2).
  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, *" : arriver sur Guacamole = redirection immédiate vers Authentik (le hub). Conséquence : guacadmin inaccessible — l'admin passe par le compte SSO Alkatrazz (« Administer system »). Dépannage si Authentik est HS : remettre "*, openid" dans le deployment + re-sync (le formulaire local revient).
  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/ et token rejeté. Corriger : Applications → Edit → Slug.
  5. Anti-bruteforce intégré (extension ban) : 5 échecs → IP bloquée ~5 min. Corrigé (2026-07-07) : REMOTE_IP_VALVE_ENABLED=true (deployment) + Traefik en externalTrafficPolicy: Local → Guacamole lit l'IP client réelle (X-Forwarded-For), le ban est par IP et non plus global. Avant ce fix, l'IP vue était celle du pod Traefik → le blocage touchait tout le monde. Si un ban global réapparaît : vérifier que la valve est active et que Traefik n'est pas repassé en Cluster. Purge immédiate : redémarrer le pod guacamole.
  6. User console sans sudo (volontaire) : le portail sert à observer/opérer léger. L'administration passe par les comptes admin habituels, pas par Guacamole.
  7. Enregistrement des sessions : possible (guacd + volume partagé) mais non configuré — gap connu, à ajouter si le portail s'ouvre à d'autres utilisateurs.
  8. La config Authentik (provider, app, utilisateurs) et les connexions Guacamole vivent en base, pas en IaC — comme le Server Manager Satisfactory. Backup PG = gap connu.