Consolider : binding annuaire (resoudre_annuaire) — keycloak/dovecot/postfix
Rôle utilitaire partagé resoudre_annuaire (comme resoudre_base) : dérive la connexion OpenLDAP du domaine_interne + un hôte surchargeable, au lieu de répéter ldaps://id-ldap-01... dans chaque rôle. Facts uri/port/base_dn/ users_dn/bind_dn/bind_password (secret no_log). Migrés + prouvés (config neutre, changed=0) : keycloak (fédération, testmail token 200), dovecot + postfix (flux courriel livré de bout en bout). Piège : les defaults d'un rôle inclus ne persistent pas hors de son exécution — publier via set_fact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
3c1cd3e90e
commit
0a0563c226
9 changed files with 100 additions and 13 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -3,6 +3,19 @@
|
|||
## 2026-07-03
|
||||
|
||||
### Ajouté
|
||||
- **Consolidation — binding `annuaire` (`resoudre_annuaire`) + retrait de la cruft.**
|
||||
*Cruft* : supprimés les 8 dossiers-catégories inertes (`roles/{applications,backup,database,
|
||||
identity,monitoring,proxmox,storage,web}/`, README seuls) et les 5 playbooks-échafaudages `debug`
|
||||
sans rôle (nextcloud, collabora, client_supervision, web_frontal, web_dorsal) ; l'intention reste
|
||||
documentée dans `docs/catalogue-services.md`. *Binding annuaire* : nouveau rôle utilitaire partagé
|
||||
`resoudre_annuaire` (comme `resoudre_base`) qui **dérive** la connexion OpenLDAP du `domaine_interne`
|
||||
+ un hôte d'annuaire surchargeable — LE seul endroit où le nom d'hôte de l'annuaire est fixé, au lieu
|
||||
d'être répété. Facts `resoudre_annuaire_{uri,port,base_dn,users_dn,bind_dn,bind_password}` (secret
|
||||
déréférencé, `no_log`). **Migrés + prouvés (config neutre, `changed=0`)** : `serveur_keycloak`
|
||||
(fédération LDAP — testmail token HTTP 200), `serveur_dovecot` + `serveur_postfix` (flux courriel
|
||||
Postfix→LDAP→LMTP→Dovecot **livré de bout en bout**). Piège appris : les *defaults* d'un rôle inclus
|
||||
ne persistent pas hors de son exécution — publier via `set_fact`. Reste : les defaults LDAP dormants
|
||||
d'`icingaweb2` (mode SSO, LDAP inutilisé) et `client_ldap` (référence périmée `idm-01`).
|
||||
- **Rôle `serveur_oauth2_proxy` — passerelle SSO OIDC générique (Keycloak) + Icinga Web 2 au SSO.**
|
||||
oauth2-proxy (v7.15.3, binaire GitHub) place Keycloak **devant** n'importe quelle app sans OIDC
|
||||
natif : elle reçoit l'utilisateur authentifié via en-tête, en auth `external`. Rôle paramétrable
|
||||
|
|
|
|||
9
roles/resoudre_annuaire/defaults/main.yml
Normal file
9
roles/resoudre_annuaire/defaults/main.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
# Hôte qui sert l'annuaire (OpenLDAP). Surchargeable par instance (group_vars) — c'est
|
||||
# LE seul point où le nom d'hôte de l'annuaire est fixé, au lieu d'être répété dans chaque rôle.
|
||||
resoudre_annuaire_hote: "id-ldap-01"
|
||||
resoudre_annuaire_port: 636
|
||||
resoudre_annuaire_encryption: "ldaps"
|
||||
# Compte de service (bind) — secret déréférencé depuis la voûte dans le rôle consommateur.
|
||||
resoudre_annuaire_bind_cn: "admin"
|
||||
resoudre_annuaire_secret: "vault_openldap_admin"
|
||||
34
roles/resoudre_annuaire/tasks/main.yml
Normal file
34
roles/resoudre_annuaire/tasks/main.yml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
# Rôle utilitaire (pas un groupe déployable) : résout la connexion à l'annuaire (OpenLDAP)
|
||||
# de façon déclarative, dérivée du domaine interne + de l'hôte d'annuaire. Remplace le
|
||||
# câblage LDAP répété dans serveur_dovecot/postfix/keycloak/icingaweb2.
|
||||
#
|
||||
# Sorties (facts) :
|
||||
# resoudre_annuaire_fqdn — id-ldap-01.<domaine>
|
||||
# resoudre_annuaire_uri — ldaps://id-ldap-01.<domaine>
|
||||
# resoudre_annuaire_base_dn — dc=...,dc=...
|
||||
# resoudre_annuaire_users_dn — ou=people,dc=...
|
||||
# resoudre_annuaire_bind_dn — cn=admin,dc=...
|
||||
# resoudre_annuaire_bind_password — secret déréférencé depuis la voûte (no_log)
|
||||
- name: Exiger un domaine interne non vide
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- domaine_interne is defined
|
||||
- domaine_interne | length > 0
|
||||
fail_msg: "domaine_interne doit être défini pour résoudre l'annuaire."
|
||||
|
||||
# set_fact (pas les defaults) pour que ces valeurs persistent dans le rôle consommateur
|
||||
# après include_role (les defaults du rôle inclus ne fuient pas hors de son exécution).
|
||||
- name: Dériver la connexion à l'annuaire
|
||||
ansible.builtin.set_fact:
|
||||
resoudre_annuaire_fqdn: "{{ resoudre_annuaire_hote }}.{{ domaine_interne }}"
|
||||
resoudre_annuaire_uri: "{{ resoudre_annuaire_encryption }}://{{ resoudre_annuaire_hote }}.{{ domaine_interne }}"
|
||||
resoudre_annuaire_port: "{{ resoudre_annuaire_port }}"
|
||||
resoudre_annuaire_base_dn: "dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
resoudre_annuaire_users_dn: "ou=people,dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
resoudre_annuaire_bind_dn: "cn={{ resoudre_annuaire_bind_cn }},dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
|
||||
- name: Déréférencer le mot de passe de bind (Vault)
|
||||
ansible.builtin.set_fact:
|
||||
resoudre_annuaire_bind_password: "{{ lookup('vars', resoudre_annuaire_secret) }}"
|
||||
no_log: true
|
||||
|
|
@ -21,11 +21,8 @@ serveur_dovecot_vmail_base: "/var/vmail"
|
|||
serveur_dovecot_mail_path: "{{ serveur_dovecot_vmail_base }}/%{user | username}"
|
||||
|
||||
# --- Annuaire/auth LDAP (vers serveur_openldap) ---
|
||||
serveur_dovecot_ldap_uris: "ldaps://id-ldap-01.{{ domaine_interne }}:636"
|
||||
serveur_dovecot_ldap_base: "dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
# Compte de service pour la recherche (bind DN). En bac à sable : l'admin LDAP.
|
||||
serveur_dovecot_ldap_bind_dn: "cn=admin,{{ serveur_dovecot_ldap_base }}"
|
||||
serveur_dovecot_ldap_bind_password: "{{ vault_openldap_admin | default('') }}"
|
||||
# Connexion à l'annuaire (uris, base, bind_dn, bind_password) : fournie par le rôle partagé
|
||||
# resoudre_annuaire (voir tasks/main.yml « Adopter la connexion annuaire »).
|
||||
# Filtre de connexion : utilisateur = adresse courriel (attribut mail).
|
||||
serveur_dovecot_ldap_filter: "(&(objectClass=inetOrgPerson)(mail=%{user}))"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
---
|
||||
- name: Resoudre l'annuaire (role partage)
|
||||
ansible.builtin.include_role:
|
||||
name: resoudre_annuaire
|
||||
|
||||
- name: Adopter la connexion annuaire pour Dovecot
|
||||
ansible.builtin.set_fact:
|
||||
serveur_dovecot_ldap_uris: "{{ resoudre_annuaire_uri }}:{{ resoudre_annuaire_port }}"
|
||||
serveur_dovecot_ldap_base: "{{ resoudre_annuaire_base_dn }}"
|
||||
serveur_dovecot_ldap_bind_dn: "{{ resoudre_annuaire_bind_dn }}"
|
||||
serveur_dovecot_ldap_bind_password: "{{ resoudre_annuaire_bind_password }}"
|
||||
no_log: true
|
||||
|
||||
- name: Exiger le mot de passe de bind LDAP (Vault)
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
|
|
|
|||
|
|
@ -26,10 +26,8 @@ serveur_keycloak_admin_password: "{{ vault_keycloak_admin | default('') }}" # r
|
|||
serveur_keycloak_ldap_federation: true
|
||||
serveur_keycloak_realm: "chezlepro"
|
||||
serveur_keycloak_ldap_nom: "openldap"
|
||||
serveur_keycloak_ldap_url: "ldaps://id-ldap-01.{{ domaine_interne }}:636"
|
||||
serveur_keycloak_ldap_users_dn: "ou=people,dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
serveur_keycloak_ldap_bind_dn: "cn=admin,dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
serveur_keycloak_ldap_bind_password: "{{ vault_openldap_admin | default('') }}"
|
||||
# Connexion à l'annuaire (url, users_dn, bind_dn, bind_password) : fournie par le rôle
|
||||
# partagé resoudre_annuaire (voir tasks/main.yml « Adopter la connexion annuaire »).
|
||||
serveur_keycloak_ldap_username_attr: "uid"
|
||||
serveur_keycloak_ldap_uuid_attr: "entryUUID"
|
||||
serveur_keycloak_ldap_object_classes: "inetOrgPerson"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,20 @@
|
|||
serveur_keycloak_db_host: "{{ resoudre_base_db_host }}"
|
||||
no_log: true
|
||||
|
||||
- name: Resoudre l'annuaire (role partage)
|
||||
ansible.builtin.include_role:
|
||||
name: resoudre_annuaire
|
||||
when: serveur_keycloak_ldap_federation | bool
|
||||
|
||||
- name: Adopter la connexion annuaire pour Keycloak
|
||||
ansible.builtin.set_fact:
|
||||
serveur_keycloak_ldap_url: "{{ resoudre_annuaire_uri }}:{{ resoudre_annuaire_port }}"
|
||||
serveur_keycloak_ldap_users_dn: "{{ resoudre_annuaire_users_dn }}"
|
||||
serveur_keycloak_ldap_bind_dn: "{{ resoudre_annuaire_bind_dn }}"
|
||||
serveur_keycloak_ldap_bind_password: "{{ resoudre_annuaire_bind_password }}"
|
||||
no_log: true
|
||||
when: serveur_keycloak_ldap_federation | bool
|
||||
|
||||
- name: Installer le JRE
|
||||
ansible.builtin.apt:
|
||||
name: "{{ serveur_keycloak_java_paquet }}"
|
||||
|
|
|
|||
|
|
@ -19,10 +19,8 @@ serveur_postfix_mailstore_hote: ""
|
|||
serveur_postfix_lmtp_port: 24
|
||||
|
||||
# --- Annuaire LDAP (validation domaines/boîtes/alias) ---
|
||||
serveur_postfix_ldap_serveur: "ldaps://id-ldap-01.{{ domaine_interne }}:636"
|
||||
serveur_postfix_ldap_base: "ou=people,dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
serveur_postfix_ldap_bind_dn: "cn=admin,dc={{ domaine_interne.split('.') | join(',dc=') }}"
|
||||
serveur_postfix_ldap_bind_password: "{{ vault_openldap_admin | default('') }}"
|
||||
# Connexion à l'annuaire (serveur, base, bind_dn, bind_password) : fournie par le rôle partagé
|
||||
# resoudre_annuaire (voir tasks/main.yml « Adopter la connexion annuaire »).
|
||||
|
||||
# --- Milter rspamd (antispam + DKIM) — si rspamd est co-localisé (nœud edge-mta) ---
|
||||
serveur_postfix_rspamd_milter: false
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
---
|
||||
- name: Resoudre l'annuaire (role partage)
|
||||
ansible.builtin.include_role:
|
||||
name: resoudre_annuaire
|
||||
|
||||
- name: Adopter la connexion annuaire pour Postfix
|
||||
ansible.builtin.set_fact:
|
||||
serveur_postfix_ldap_serveur: "{{ resoudre_annuaire_uri }}:{{ resoudre_annuaire_port }}"
|
||||
serveur_postfix_ldap_base: "{{ resoudre_annuaire_users_dn }}"
|
||||
serveur_postfix_ldap_bind_dn: "{{ resoudre_annuaire_bind_dn }}"
|
||||
serveur_postfix_ldap_bind_password: "{{ resoudre_annuaire_bind_password }}"
|
||||
no_log: true
|
||||
|
||||
- name: Exiger le mot de passe de bind LDAP (Vault)
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
|
|
|
|||
Loading…
Reference in a new issue