Funk-lab/admin/k8s/auth-portal-admin.md
ALI YESILKAYA 514cb89579
feat(grafana): SSO OIDC via Authentik + admin par groupe lab-admins (#86)
- values.yaml monitoring : auth.generic_oauth (auth_url navigateur,
  token/api sur le Service interne), root_url, mapping lab-admins→Admin /
  sinon Viewer. Login local conservé (break-glass).
- vault : vault_grafana_oauth_client_secret (= secret k8s
  monitoring/grafana-oauth-secret, déjà créé)
- doc : runbook « ajouter une app » complété (exemple Grafana concret +
  groupe lab-admins) et procédure SQL pour promouvoir un compte SSO admin
  Guacamole (appliquée à Alkatrazz)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 12:11:00 +02:00

7.7 KiB

Portail — administration au quotidien (Authentik + Guacamole)

Guide d'exploitation du hub utilisateurs. L'architecture, le déploiement et les pièges sont dans admin/k8s/auth-portal.md ; le guide à envoyer aux utilisateurs est dans docs/portail-guide-utilisateur.md.

Les deux consoles d'admin

Console URL Compte
Authentik (identités, apps du hub) http://auth.lab.local (LAN) ou http://kaya.freeboxos.fr:9081 → icône ⚙ akadmin
Guacamole (connexions, sessions) tuile « Portail consoles » puis Settings Alkatrazz (SSO, « Administer system »)

guacadmin (compte local) est inaccessible tant que le SSO est prioritaire — c'est voulu. Dépannage : piège n°3 de auth-portal.md.

Rendre un compte SSO admin Guacamole (fait pour Alkatrazz) : les droits système ne s'assignent pas via un compte non-admin, donc au bootstrap on passe par la base (guacamole_entity : type='USER', name = username Authentik casse comprise) :

-- sur storage-01, id de l'entité = son entity_id dans guacamole_entity
INSERT INTO guacamole_system_permission (entity_id, permission)
SELECT <id>, perm::guacamole_system_permission_type
FROM (VALUES ('ADMINISTER'),('CREATE_CONNECTION'),('CREATE_CONNECTION_GROUP'),
             ('CREATE_SHARING_PROFILE'),('CREATE_USER'),('CREATE_USER_GROUP')) AS v(perm);

Ensuite ce compte gère tout depuis l'UI (y compris promouvoir d'autres admins).

Cycle de vie d'un utilisateur

Créer (≈2 min)

  1. Authentik → Directory → Users → Createusername en minuscules (c'est lui qui devient le compte Guacamole, casse comprise), email facultatif
  2. Sur l'utilisateur → Set password (mot de passe dédié, jamais réutilisé — le portail est en HTTP)
  3. Directory → Groups → guacamole → onglet Users → Add existing user⚠️ obligatoire : l'application est liée à ce groupe, sans lui → « accès refusé »
  4. L'utilisateur se connecte une première fois (hub → tuile) — son compte apparaît alors côté Guacamole
  5. Guacamole → Settings → Users → <lui> → cocher ses connexions (s01 et/ou g01) → Save. Ne jamais cocher les permissions du haut (Administer…) pour un invité.

Restreindre / auditer

  • Qui est connecté : Guacamole → Settings → Active Sessions — et Kill pour couper une session en direct
  • Historique : Settings → History (qui, quelle machine, quand, durée)
  • Événements de login : Authentik → Events → Logs (échecs, IP, user agent)

Révoquer (départ, téléphone volé, doute)

  1. Authentik → Directory → Users → <lui>Deactivate (il ne peut plus se logger nulle part — c'est LE geste principal)
  2. Guacamole → Active SessionsKill sa session si une est ouverte
  3. (Optionnel, définitif) le retirer du groupe guacamole, puis supprimer les deux comptes (Authentik + Guacamole)

Gérer les machines accessibles (Guacamole)

Ajouter une machine = Settings → Connections → New Connection :

Champ Valeur
Protocol SSH
Hostname / Port IP de la machine / 22
Username console (déployé par le rôle Ansible console_user)
Private key vault_console_ssh_private_key (make vault-view)

Prérequis côté machine : appliquer le rôle console_user (ajouter l'hôte au playbook si nouveau). Puis cocher la connexion aux utilisateurs concernés. Options utiles par connexion : SFTP (transfert de fichiers), enregistrement d'écran, limites de concurrence.

Ajouter une application au hub (le vrai pouvoir d'Authentik)

Pour chaque nouvelle app (Grafana, n8n…) :

  1. Applications → Providers → Create — type selon l'app : OAuth2/OpenID (app moderne), Proxy (app sans auth propre), SAML, LDAP
  2. Applications → Applications → Create — Name, slug (⚠️ utilisé dans les URLs OIDC, piège n°4), provider, Launch URL (l'URL publique si accès Internet), icône facultative
  3. Onglet Policy / Group / User Bindings → lier un groupe → seuls ses membres voient la tuile
  4. Configurer l'app cliente (client ID, endpoints — cf. la page Overview du provider)

La tuile apparaît automatiquement sur le hub des membres du groupe.

Le groupe lab-admins (admin partout)

Groupe transverse : ses membres reçoivent le rôle admin dans chaque app intégrée (mapping fait côté app, ex. Grafana role_attribute_path). Alkatrazz en fait partie. Créer si absent : Directory → Groups → Create lab-admins, y ajouter les admins.

Exemple concret : Grafana (SSO OIDC)

Côté k8s c'est déjà fait (values.yaml monitoring : auth.generic_oauth, secret k8s monitoring/grafana-oauth-secret = vault_grafana_oauth_client_secret). Reste la config Authentik (UI) :

  1. Applications → Providers → Create → OAuth2/OpenID Provider :
    • Name grafana, Authorization flow default-provider-authorization-implicit-consent
    • Client type : Confidential (Grafana garde un secret, contrairement à Guacamole)
    • Client ID : grafana · Client Secret : coller vault_grafana_oauth_client_secret (make vault-view) — doit être identique des deux côtés
    • Redirect URI (Strict) : http://grafana.lab.local/login/generic_oauth
    • Signing Key : le certificat self-signed
  2. Applications → Create : Name Grafana, slug grafana, provider grafana, Launch URL http://grafana.lab.local, une icône si tu veux
  3. Bindings → lier un groupe (ou laisser ouvert). Pour être admin : être dans lab-admins (mappé → rôle Grafana Admin ; les autres → Viewer)
  4. Tester : hub → tuile Grafana → connecté en Admin. Break-glass si le SSO casse : http://grafana.lab.local/login en admin / adminPassword (values.yaml).

⚠️ Grafana n'est exposé que sur le LAN (grafana.lab.local) — la tuile ne fonctionne donc que depuis le LAN tant qu'on n'ajoute pas de redirection Internet dédiée (comme pour le portail). Pièges : redirect_uri au caractère près, et les pods ne résolvant pas lab.local, token_url/api_url pointent sur le Service interne.

Durcissement (quand l'usage s'installe)

  • MFA/TOTP : chaque utilisateur peut enrôler une app d'authentification (Settings utilisateur → MFA Devices). Pour l'imposer : Flows & Stages → ajouter une stage authenticator-validation au flow d'authentification par défaut.
  • Rappels : rate-limit nftables 30 conn/min (rôle gateway), anti-bruteforce Guacamole (5 échecs → ~5 min, IP Traefik = blocage global, piège n°5), lockout Authentik (reputation policies).
  • Upgrade paths documentés : TLS (vrai domaine + Let's Encrypt) ou bascule VPN (admin/infra/wireguard.md, serveur prêt et dormant).

Débogage express

kubectl -n auth get pods                                  # tout doit être 1/1
kubectl -n auth logs deploy/guacamole --tail=50           # rejets de token, ban, DB
kubectl -n auth logs deploy/authentik-server --tail=50    # flows, redirect_uri, 400
Symptôme Cause probable
« Redirect URI Error » (page Authentik) Redirect URI du provider ≠ http://kaya.freeboxos.fr:9080/ au caractère près
Login SSO accepté puis retour à la page de login Guacamole Signing Key absente du provider, ou slug ≠ guacamole (JWKS 404 dans les logs)
Tout le monde bloqué au login Anti-bruteforce (piège n°5) — attendre ~5 min ou redémarrer le pod guacamole
Tuile absente pour un utilisateur Pas membre du groupe guacamole
Console noire / connexion SSH refusée Machine éteinte, ou clé console révoquée (rôle console_user)