- 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>
8.2 KiB
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) etdocs/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, PVCauthentik-media(RWX, nfs), base PostgreSQL sur storage-01 (même pattern que Ghostfolio/n8n). - Guacamole (
k8s/apps/guacamole/) : webappguacamole/guacamole:1.6.0+ proxyguacamole/guacd:1.6.0, base PostgreSQL sur storage-01 (connexions, permissions). Le Job ArgoCDguacamole-initdbpose le schéma si absent (idempotent). - Ansible : rôle
postgresql(basesauthentik+guacamole), rôleconsole_user(userconsolesans 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)
ansible-playbook -i inventory.yml playbooks/storage-01.yml --tags postgresql,console_useransible-playbook -i inventory.yml playbooks/gpu-01.yml --tags console_user- Créer les secrets k8s ci-dessus (avant le premier sync, sinon pods en
CreateContainerConfigError) - Merge sur
main→ ArgoCD crée les Applicationsauthentiketguacamole(~3 min)
Configuration initiale — Authentik
- Compte admin : ouvrir
http://auth.lab.local/if/flow/initial-setup/(valable uniquement tant qu'aucun admin n'existe) → définir mot de passe deakadmin. - 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)
- Name :
- Application — Applications → Create : Name
Portail consoles, slugguacamole(doit correspondre à/application/o/guacamole/configuré côté Guacamole : issuer + JWKS), Providerguacamole. - Utilisateurs — Directory → Users → Create (+ groupes si besoin). Le
preferred_usernameAuthentik devient le nom de compte Guacamole.
Configuration initiale — Guacamole
- Se connecter en
guacadmin/guacadmin(formulaire local, extension base) et changer ce mot de passe immédiatement (portail exposé à tout le LAN). - Settings → Connections → New connection (×2) :
- Protocol
SSH— Hostname192.168.10.1(s01) ou192.168.10.20(g01) — Port22 - Username
console— Private key : collervault_console_ssh_private_key
- Protocol
- 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
- HTTPS sur Internet, HTTP en interne : l'accès public passe par
*.funklab.onlineen TLS Let's Encrypt (durcissement 2026-07-07) ; les routes internes*.lab.localrestent en HTTP clair (LAN de confiance). L'issuer OIDC est donc le domaine HTTPS (cf. piège n°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ésolutionlab.localdes pods. L'issuer, lui, restehttp://auth.lab.local/...(doit matcher le claimissdes tokens émis via le navigateur). EXTENSION_PRIORITY="openid, *": arriver sur Guacamole = redirection immédiate vers Authentik (le hub). Conséquence :guacadmininaccessible — l'admin passe par le compte SSOAlkatrazz(« Administer system »). Dépannage si Authentik est HS : remettre"*, openid"dans le deployment + re-sync (le formulaire local revient).- 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 GuacamoleNon 200 status code (404) ... /o/guacamole/jwks/et token rejeté. Corriger : Applications → Edit → Slug. - Anti-bruteforce intégré (extension
ban) : 5 échecs → IP bloquée ~5 min. ✅ Corrigé (2026-07-07) :REMOTE_IP_VALVE_ENABLED=true(deployment) + Traefik enexternalTrafficPolicy: 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é enCluster. Purge immédiate : redémarrer le pod guacamole. - User
consolesans sudo (volontaire) : le portail sert à observer/opérer léger. L'administration passe par les comptes admin habituels, pas par Guacamole. - Enregistrement des sessions : possible (guacd + volume partagé) mais non configuré — gap connu, à ajouter si le portail s'ouvre à d'autres utilisateurs.
- 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.