Set-OPS-Public/roles/resoudre_annuaire
Daniel Allaire b4e3520561 annuaire : un compte de service par consommateur, et la porte se ferme
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
2026-09-13 13:36:38 -04:00
..
defaults annuaire : un compte de service par consommateur, et la porte se ferme 2026-09-13 13:36:38 -04:00
tasks annuaire : un compte de service par consommateur, et la porte se ferme 2026-09-13 13:36:38 -04:00
README.md docs : un README par rôle (12 manquants) + carte remise à l'état du code 2026-07-29 11:32:06 -04:00

resoudre_annuaire

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.

Prérequis

  • domaine_interne défini ; voûte déverrouillée (ANSIBLE_VAULT_PASSWORD_FILE).