rotation : vault_openldap_admin, quatre consommateurs et deux pieges
`ldappasswd` ne peut pas le changer : `cn=admin` n'est pas une entree de la base mais le rootDN declare dans cn=config. Le mot de passe vit dans `olcRootPW` et se modifie par un bind EXTERNAL. L'echec etait sans degat — l'ancien fonctionnait toujours, verifie avant de continuer. Keycloak stocke le mot de passe de LIAISON dans sa base et le masque : la reconciliation d'hier couvrait l'URL, les DN et le mode, pas `bindCredential`. Tourner le secret aurait coupe Keycloak de l'annuaire. Comme la valeur est masquee, la reconciliation passe par une empreinte. Verifie consommateur par consommateur : synchro LDAP de Keycloak (qui prouve la liaison), carte LDAP de Postfix, Dovecot actif. Les trois rejouent a changed=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
35602546eb
commit
4642ffec0a
4 changed files with 55 additions and 1 deletions
23
CHANGELOG.md
23
CHANGELOG.md
|
|
@ -2,6 +2,29 @@
|
|||
|
||||
## 2026-08-06 — le chemin nord-sud devient dérivable
|
||||
|
||||
### `vault_openldap_admin` — quatre consommateurs et deux pièges
|
||||
|
||||
Le secret le plus délicat de la liste : Keycloak, Dovecot, Postfix et Icinga Web 2 s'y lient
|
||||
tous.
|
||||
|
||||
**Premier piège : `ldappasswd` ne peut pas le changer.** `cn=admin` n'est pas une entrée de
|
||||
la base mais le **rootDN** déclaré dans `cn=config` — la commande répond « No such object ».
|
||||
Le mot de passe vit dans `olcRootPW` et se modifie par un bind `EXTERNAL`. L'échec était sans
|
||||
dégât : l'ancien fonctionnait toujours, vérifié avant de continuer.
|
||||
|
||||
**Second piège : Keycloak stocke le mot de passe de liaison dans sa base, et le masque.** La
|
||||
réconciliation ajoutée hier couvrait l'URL, les DN et le mode — pas `bindCredential`. Tourner
|
||||
le secret aurait coupé Keycloak de l'annuaire, et plus personne n'aurait pu se connecter.
|
||||
Comme on ne peut pas comparer une valeur masquée, la réconciliation passe par une **empreinte**
|
||||
— même mécanisme que les comptes de secours.
|
||||
|
||||
**Vérifié, consommateur par consommateur** : synchronisation LDAP de Keycloak (qui prouve la
|
||||
liaison), carte LDAP de Postfix, Dovecot actif. Les trois rejouent à `changed=0`.
|
||||
|
||||
Six secrets tournés depuis hier ; chacun a d'abord demandé de **construire la capacité de le
|
||||
faire**. C'est le motif de fond de ces deux jours : le dépôt savait créer, pas changer.
|
||||
|
||||
|
||||
### `vault_forgejo_oidc` — le secret exposé ne vaut plus rien
|
||||
|
||||
Il avait fui dans une sortie de diagnostic. Le faire tourner a d'abord demandé de rendre la
|
||||
|
|
|
|||
|
|
@ -212,7 +212,20 @@ s'authentifier pour poser la nouvelle valeur. L'ordre est donc inversé :
|
|||
```
|
||||
|
||||
C'est une **procédure**, pas un redéploiement. La même contrainte vaut pour tout secret qui
|
||||
est aussi la clé de son propre changement — `vault_openldap_admin` en est un.
|
||||
est aussi la clé de son propre changement.
|
||||
|
||||
**`vault_openldap_admin` en est un, avec deux pièges de plus.** Il ne se change pas par
|
||||
`ldappasswd` : `cn=admin` n'est pas une entrée de la base mais le **rootDN** déclaré dans
|
||||
`cn=config`. Le mot de passe vit dans `olcRootPW`, et se modifie par un bind `EXTERNAL` :
|
||||
|
||||
```
|
||||
slappasswd -h '{SSHA}' -s <nouveau> puis ldapmodify -Y EXTERNAL sur olcDatabase={1}mdb
|
||||
```
|
||||
|
||||
Et il a **quatre consommateurs** : Keycloak (dans sa base), Dovecot, Postfix, Icinga Web 2
|
||||
(fichiers de configuration). Les trois derniers suivent au redéploiement ; Keycloak stocke le
|
||||
mot de passe de liaison et le masque — sa réconciliation passe donc par une empreinte, comme
|
||||
les comptes de secours.
|
||||
|
||||
**Et une vérification n'est pas un message de succès.** `grafana-cli` annonçait
|
||||
« Admin password changed successfully » en écrivant dans une base qui n'était pas celle du
|
||||
|
|
|
|||
|
|
@ -116,3 +116,7 @@ serveur_keycloak_ldap_edit_mode: "WRITABLE"
|
|||
# Compte d'amorcage dont le changement de mot de passe doit etre EXPLICITE dans
|
||||
# Keycloak. Vide = aucun alignement. Voir roles/amorcage_acces (D-67).
|
||||
serveur_keycloak_amorcage_uid: "{{ amorcage_acces_uid | default('sysadmin') }}"
|
||||
|
||||
# Empreinte du mot de passe de LIAISON LDAP applique — Keycloak le masque, on ne
|
||||
# peut donc pas le comparer. Permet sa rotation. Voir tasks/federation-ldap.yml.
|
||||
serveur_keycloak_marqueur_bind: "/etc/keycloak/.setops-bind-sha256"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,20 @@
|
|||
# `|| true` en fin de chaine : avec `pipefail`, un grep sans correspondance
|
||||
# tuerait le script entier. Et l'extraction ne s'ancre pas sur `$` — la ligne
|
||||
# se termine par un guillemet, pas par la valeur.
|
||||
# Le mot de passe de LIAISON ne se compare pas : Keycloak le masque (`****`).
|
||||
# On memorise donc son empreinte, comme pour les comptes de secours. Sans
|
||||
# cela, faire tourner `vault_openldap_admin` couperait Keycloak de
|
||||
# l'annuaire — la federation garderait l'ancienne valeur, et plus personne
|
||||
# ne pourrait se connecter.
|
||||
EMPREINTE_VOULUE="{{ serveur_keycloak_ldap_bind_password | hash('sha256') }}"
|
||||
EMPREINTE_POSEE=$(cat {{ serveur_keycloak_marqueur_bind }} 2>/dev/null || true)
|
||||
if [ "$EMPREINTE_POSEE" != "$EMPREINTE_VOULUE" ]; then
|
||||
"$KC" update components/"$FEDID" -r {{ serveur_keycloak_realm }} \
|
||||
-s "config.bindCredential=[\"$LDAP_BIND_PW\"]" >/dev/null
|
||||
printf '%s\n' "$EMPREINTE_VOULUE" > {{ serveur_keycloak_marqueur_bind }}
|
||||
chmod 600 {{ serveur_keycloak_marqueur_bind }}
|
||||
CHANGED=1
|
||||
fi
|
||||
MODE_ACTUEL=$("$KC" get components/"$FEDID" -r {{ serveur_keycloak_realm }} 2>/dev/null \
|
||||
| sed -n 's/.*"editMode" : \[ "\([A-Z_]*\)".*/\1/p' | head -1 || true)
|
||||
if [ "$URL_ACTUELLE" != "{{ serveur_keycloak_ldap_url }}" ] \
|
||||
|
|
|
|||
Loading…
Reference in a new issue