97 lines
5.1 KiB
Markdown
97 lines
5.1 KiB
Markdown
|
|
# Authentification : Keycloak devant, LDAP dessous, `sudo` en secours
|
||
|
|
|
||
|
|
> **Directive d'architecture du 2026-08-03.** Trois règles, décidées ensemble et
|
||
|
|
> volontairement indissociables — chacune crée le problème que la suivante résout.
|
||
|
|
|
||
|
|
1. **Toute authentification web passe par Keycloak.** Aucun service ne tient son propre
|
||
|
|
répertoire de comptes.
|
||
|
|
2. **LDAP est la source de vérité unique** des comptes d'un tenant. Keycloak le fédère ;
|
||
|
|
les protocoles qui ne parlent pas OIDC s'y lient directement.
|
||
|
|
3. **Chaque service garde un accès de secours**, atteint par `sudo` sur l'hôte.
|
||
|
|
|
||
|
|
## 1. Pourquoi les trois vont ensemble
|
||
|
|
|
||
|
|
La chaîne est en série : `service → Keycloak → LDAP`. C'est ce qui donne « une identité, un
|
||
|
|
mot de passe » — et c'est aussi trois points de panne alignés. Si LDAP tombe, plus personne
|
||
|
|
n'entre nulle part, y compris pour réparer.
|
||
|
|
|
||
|
|
La règle 3 n'est donc pas une entorse au SSO : c'est ce qui rend les deux premières
|
||
|
|
tenables. Sans elle, la panne d'un maillon devient une exclusion totale.
|
||
|
|
|
||
|
|
## 2. Portée : le web, et seulement le web
|
||
|
|
|
||
|
|
| Protocole | Chemin d'authentification | Pourquoi |
|
||
|
|
|---|---|---|
|
||
|
|
| **HTTP(S)** — interfaces humaines | **Keycloak** (OIDC natif, ou `oauth2-proxy` devant) | c'est là que la directive s'applique |
|
||
|
|
| **IMAP / SMTP** | **LDAP direct** (Dovecot, Postfix) | ces protocoles ne parlent pas OIDC ; le flux est prouvé de bout en bout |
|
||
|
|
| **SSH** | **clé publique** (`PasswordAuthentication no`) | pas de mot de passe du tout, donc rien à fédérer |
|
||
|
|
| **PostgreSQL, Redis** | secrets applicatifs en voûte | comptes de service, pas d'humains |
|
||
|
|
|
||
|
|
Ce qui est interdit partout, c'est qu'un service tienne **son propre répertoire d'humains**.
|
||
|
|
Le chemin varie ; la source ne varie pas.
|
||
|
|
|
||
|
|
## 3. La posture retenue : la porte de secours n'est pas annoncée
|
||
|
|
|
||
|
|
Le compte local de chaque service **existe** — il ne peut pas dépendre de Keycloak, sinon il
|
||
|
|
tomberait avec lui. Mais son formulaire de connexion **n'est pas proposé au repos**.
|
||
|
|
|
||
|
|
Ce n'est pas une préférence esthétique. Un formulaire local ouvert en permanence :
|
||
|
|
|
||
|
|
- contourne la politique de mot de passe et le MFA ;
|
||
|
|
- contourne surtout la **révocation centrale** — désactiver quelqu'un dans LDAP laisserait
|
||
|
|
son compte local valide, sans que rien ne le signale ;
|
||
|
|
- offre une cible de bourrage d'identifiants sur `admin`, en continu, pour un usage qui
|
||
|
|
devrait être exceptionnel.
|
||
|
|
|
||
|
|
Le coût de la fermeture est nul depuis qu'on a tranché que **`sudo` suffit** : `sudo` *est*
|
||
|
|
le mécanisme de réouverture.
|
||
|
|
|
||
|
|
### Ce que chaque service sait vraiment faire
|
||
|
|
|
||
|
|
Vérifié auprès de l'amont le 2026-08-03, puis par **rendu réel des gabarits** dans les deux
|
||
|
|
postures — pas seulement lu.
|
||
|
|
|
||
|
|
| Service | Réglage | Effet réel | Secours par `sudo` |
|
||
|
|
|---|---|---|---|
|
||
|
|
| **Grafana** | `GF_AUTH_DISABLE_LOGIN_FORM=true` | ferme le formulaire | `grafana-cli admin reset-admin-password` |
|
||
|
|
| **Forgejo** ≥ 10 | `ENABLE_INTERNAL_SIGNIN=false` + `ENABLE_BASIC_AUTHENTICATION=false` | ferme la connexion interne **et** l'API en Basic | `forgejo admin user change-password` |
|
||
|
|
| **Nextcloud** | `hide_login_form=true` | **masque seulement** | `occ user:resetpassword`, ou `…/login?direct=1` |
|
||
|
|
|
||
|
|
> **Nextcloud est une exception, et il faut la dire.** `hide_login_form` **masque** le
|
||
|
|
> formulaire ; `…/login?direct=1` y accède encore, et l'amont le documente comme voulu —
|
||
|
|
> c'est ainsi qu'un administrateur entre. La protection est donc de **ne plus l'annoncer**,
|
||
|
|
> pas de l'interdire. Le présenter comme équivalent à Grafana ou Forgejo donnerait un faux
|
||
|
|
> confort.
|
||
|
|
|
||
|
|
Le réglage s'appelle `<rôle>_connexion_locale` dans les trois rôles, et vaut `false` par
|
||
|
|
défaut. Le passer à `true` rouvre la porte, explicitement.
|
||
|
|
|
||
|
|
**Garde de version.** `ENABLE_INTERNAL_SIGNIN` n'existe **que depuis Forgejo v10** (suivi
|
||
|
|
amont, ticket 7476 : *« This option was added to Forgejo v10 »*). Sur une version
|
||
|
|
antérieure il serait ignoré **sans erreur** — le rôle croirait avoir fermé la porte. Un
|
||
|
|
`assert` refuse donc `connexion_locale: false` sous 10.0.0 plutôt que de laisser croire.
|
||
|
|
|
||
|
|
## 4. La chaîne de secours
|
||
|
|
|
||
|
|
Trois maillons, aucun ne dépendant d'une porte web ouverte :
|
||
|
|
|
||
|
|
```
|
||
|
|
1. SSO Keycloak → LDAP ← la voie normale
|
||
|
|
2. sudo via SSH occ / grafana-cli / forgejo admin ← Keycloak ou LDAP en panne
|
||
|
|
3. console Proxmox de la VM ← SSH inaccessible
|
||
|
|
```
|
||
|
|
|
||
|
|
Un accès de secours qu'on ne sait pas emprunter n'existe pas : les commandes exactes sont
|
||
|
|
dans le tableau ci-dessus, et les mots de passe locaux vivent dans la voûte unique de
|
||
|
|
l'instance.
|
||
|
|
|
||
|
|
## 5. Ce qui reste à faire
|
||
|
|
|
||
|
|
- **Prometheus et Loki** exposent une interface sans SSO. `oauth2-proxy` est déjà éprouvé
|
||
|
|
devant Icinga Web 2 : le patron existe, il reste à l'appliquer.
|
||
|
|
- **Aucune preuve ne garde cette directive.** C'est le même risque que les intégrations
|
||
|
|
universelles avant leur inversion : une règle qu'aucune garde ne vérifie finit par ne
|
||
|
|
plus être vraie. Le remède symétrique serait qu'un rôle **déclare sa position**
|
||
|
|
(`web-sso` / `ldap-direct` / `sans-auth-humaine`, plus son accès de secours) et qu'une
|
||
|
|
preuve refuse une interface humaine sans SSO ni secours déclaré.
|