diff --git a/CHANGELOG.md b/CHANGELOG.md index 2daa094..d81b147 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,38 @@ ## 2026-08-06 — le chemin nord-sud devient dérivable +### Le courriel interne, et l'annuaire qui ne désignait personne + +`infra-mail-01` (Dovecot) et `edge-mta-01` (Postfix + rspamd) déployées — **dix-neuf +playbooks d'affilée sans un échec**. Neuf VM debout. + +``` +Postfix → Dovecot:24 ouvert +lmtp_tls_security_level = verify zéro-confiance sur le LMTP +mynetworks = … 10.27.0.0/16 le supernet dérivé, à l'œuvre +virtual_mailbox_maps → ldaps://idm-01 liaison établie +``` + +C'est la seconde branche de la directive d'authentification : LDAP **direct** pour les +protocoles qui ne parlent pas OIDC, sans passer par Keycloak. + +**`resoudre_annuaire` fixait `id-ldap-01` en dur** — une machine qui n'existe dans aucun plan. +Postfix ne pouvait pas se lier : `Unable to bind to ldaps://id-ldap-01.chezlepro.internal:636 +(Can't contact LDAP server)`. + +L'intention du rôle était pourtant juste, et son commentaire le disait : *« 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 »*. Un seul point de +vérité — mais **écrit** au lieu d'être dérivé. Une valeur unique et fausse vaut mieux qu'une +valeur répétée et fausse ; elle reste fausse. + +Le plan le déclare (`applications.openldap.hote: idm-01`) : c'est de là qu'elle vient +désormais. Septième occurrence du même motif aujourd'hui. + +**Ce qui n'est pas prouvé** : aucun compte n'existe dans LDAP — l'approvisionnement des +utilisateurs n'est pas une étape d'infrastructure. Tout ce qui précède la boîte aux lettres est +vérifié ; la remise elle-même attend un compte. + + ### Le SSO fonctionne — quatre défauts, un seul motif `obs-01` et `mon-01` déployées : Loki, Prometheus, Grafana d'un côté ; Icinga, Icinga Web 2 et diff --git a/roles/resoudre_annuaire/defaults/main.yml b/roles/resoudre_annuaire/defaults/main.yml index d714132..cc70457 100644 --- a/roles/resoudre_annuaire/defaults/main.yml +++ b/roles/resoudre_annuaire/defaults/main.yml @@ -1,6 +1,10 @@ --- -# 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. +# Hôte qui sert l'annuaire (OpenLDAP) — DÉRIVÉ du plan (`applications.openldap.hote`), +# pas écrit. Un seul point de vérité valait mieux que la répétition dans chaque rôle, mais +# une valeur écrite finit par ne plus désigner personne : `id-ldap-01` ne correspondait à +# aucune machine du plan (l'annuaire vit sur `idm-01`), et Postfix ne pouvait pas se lier. +# Constaté le 2026-08-07. Le repli ci-dessous ne sert que si le plan est muet. +resoudre_annuaire_app: "openldap" resoudre_annuaire_hote: "id-ldap-01" resoudre_annuaire_port: 636 resoudre_annuaire_encryption: "ldaps" diff --git a/roles/resoudre_annuaire/tasks/main.yml b/roles/resoudre_annuaire/tasks/main.yml index 525e390..a1648ec 100644 --- a/roles/resoudre_annuaire/tasks/main.yml +++ b/roles/resoudre_annuaire/tasks/main.yml @@ -17,6 +17,16 @@ - domaine_interne | length > 0 fail_msg: "domaine_interne doit être défini pour résoudre l'annuaire." +- name: Charger le registre des applications (hôte de l'annuaire) + ansible.builtin.include_vars: + file: "{{ setops_plan_dir }}/applications.yml" + failed_when: false + +- name: Dériver l'hôte de l'annuaire depuis le plan + ansible.builtin.set_fact: + resoudre_annuaire_hote: "{{ (applications | default({})).get(resoudre_annuaire_app, {}).get('hote') }}" + when: ((applications | default({})).get(resoudre_annuaire_app, {}).get('hote') | default('')) | length > 0 + # 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