mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 08:34:41 +02:00
- 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>
149 lines
8.2 KiB
Markdown
149 lines
8.2 KiB
Markdown
# 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 :
|
||
|
||
```bash
|
||
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.
|