Keycloak, Dovecot, Postfix et Icinga Web 2 se liaient TOUS avec cn=admin, le compte
d administration de la base. C est le rootDN : slapd lui fait contourner toutes les
ACL. Un seul secret, quatre services, tous les droits sur l arbre — pour ce qui est,
trois fois sur quatre, une simple lecture.
Et les droits livres par Debian etaient intacts : `to * by * read`. Sur ldap://, sans
s authentifier, une machine du reseau enumerait tous les comptes et toutes les
adresses. Des comptes a droits mesures n auraient rien valu tant que cette ligne
restait : on aurait ferme la porte en laissant la fenetre.
L indice etait deja dans le depot. `validatePasswordPolicy` existe parce que slapd
n applique pas ses controles de qualite au rootDN : la consequence etait compensee,
la cause intacte.
- ou=services, un compte par consommateur, secret propre en voute
- sept regles d acces posees EN ENTIER (state: exact) : l ordre est la regle, et
inserer c est parier sur ce que le paquet aura mis avant nous
- amorcage_acces garde le compte d administration, NOMME comme l exception : il ne
consomme pas l annuaire, il le provisionne depuis la socket locale
- la sonde passe de -x a -Y EXTERNAL : elle lisait en anonyme et aurait annonce un
annuaire VIDE sur un annuaire parfaitement sain
- la rotation du compte d administration devient possible (elle n etait posee qu a
l installation, par debconf : la voute et slapd divergeaient en silence)
Quatre marches payees en chemin :
1. un cinquieme appelant oublie, dont l echec etait masque par no_log — la garde
refuse desormais SANS no_log : elle nomme la cle absente, jamais son contenu
2. la federation Keycloak ne reecrivait son bindDn que si l URL ou le mode changeaient
— nouveau secret, ancien nom, error code 49
3. la rotation placee APRES les taches qui se lient en administrateur
4. ansible-vault et son tube : sortie non bloquante = echec silencieux, la voute
paraissait tournee et etait identique a l octet
P72 exige que tout role incluant resoudre_annuaire NOMME son compte, et qu aucun sauf
amorcage_acces ne nomme admin. Eprouvee dans les deux sens.
Verifie sur l infrastructure : chaque compte lit ce qu il doit, aucun ne voit les
autres, la lecture anonyme rend 0 entree, et les quatre services repondent (doveadm
user, postmap -q, decouverte OIDC 200, portier SSO 200).
vault_openldap_admin et vault_ldap_bind_postfix renouveles : les deux avaient transite
en clair par une session d exploitation. Les anciennes valeurs rendent Invalid
credentials (49).
make prouver : 71 OK, 0 echec, 1 saute. ansible-lint : 0 failure, profil production.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
Rôle utilitaire (pas un groupe déployable) : dérive la connexion à l'annuaire interne
(OpenLDAP) de façon déclarative, à partir du domaine_interne et de l'hôte d'annuaire.
Remplace le câblage LDAP qui était répété dans serveur_dovecot, serveur_postfix,
serveur_keycloak et serveur_icingaweb2. Un seul endroit fixe le nom de l'hôte
d'annuaire.
Usage
- name:Résoudre l'annuaire (rôle partagé)ansible.builtin.include_role:name:resoudre_annuaire- name:Adopter la connexion annuaire pour <service>ansible.builtin.set_fact:<service>_ldap_uri:"{{ resoudre_annuaire_uri }}"<service>_ldap_base_dn:"{{ resoudre_annuaire_base_dn }}"
Sorties (facts, persistent après include_role)
Fact
Exemple
resoudre_annuaire_fqdn
id-ldap-01.exemple.internal
resoudre_annuaire_uri
ldaps://id-ldap-01.exemple.internal
resoudre_annuaire_base_dn
dc=exemple,dc=internal
resoudre_annuaire_users_dn
ou=people,dc=exemple,dc=internal
resoudre_annuaire_bind_dn
cn=admin,dc=exemple,dc=internal
resoudre_annuaire_bind_password
Déréférencé de la voûte (no_log)
Variables
Variable
Défaut
Rôle
resoudre_annuaire_hote
id-ldap-01
Le point où le nom d'hôte est fixé (surchargeable par instance)
resoudre_annuaire_port
636
Port LDAPS
resoudre_annuaire_encryption
ldaps
Schéma de l'URI
resoudre_annuaire_bind_cn
admin
CN du compte de bind
resoudre_annuaire_secret
vault_openldap_admin
Nom de la variable de voûte
Notes
Les sorties sont posées en set_fact (pas en defaults) : les defaults d'un rôle inclus
ne survivent pas à la fin de son exécution, contrairement aux facts.
Le base DN est dérivé du domaine_interne (a.b → dc=a,dc=b) : aucun DN codé en dur.
Le rôle exige un domaine_interne non vide (assertion).
LDAPS suppose la confiance step_ca posée par client_pki sur le nœud consommateur.