CORRECTION DE COMPTE D ABORD. J avais annonce cinq groupes sans sonde. La mesure en donne VINGT-SEPT : j avais compte ceux que j avais en tete, pas ceux que le depot contient. Il en reste vingt-deux. LES CINQ, PAR ORDRE DE DEGAT SILENCIEUX. autorite (step_ca) — la plus urgente : nos certificats vivent 24 h, une AC muette ne casse rien aujourd hui et casse TOUT demain, d un coup, sur les 21 machines. Elle surveille aussi l expiration de la RACINE, que personne ne regarde parce qu elle vit des annees (relevee a 3642 jours). base (postgresql) — une VRAIE requete, pas pg_isready : celui-ci dit que le port repond, pas que la base sert. Plus le compte des connexions : a saturation, chaque application tombe sans que la base ait l air morte. annuaire (openldap) — elle COMPTE les entrees. Un annuaire vide repond success a tout : le mensonge des sauvegardes vides, vert et sans contenu. zones (powerdns) — un autoritatif sans zone repond NXDOMAIN a tout, ce qui se lit comme « ce nom n existe pas ». edge (nginx) — elle valide la configuration SUR DISQUE : nginx sert la derniere valide, et une configuration cassee ne se voit qu au prochain demarrage, souvent des mois plus tard. Les cinq eprouvees vertes sur le sain puis rouges PAR PARAMETRE, sans toucher a un service. Etat : 20 sondes sur 19 roles, 23 services distincts, 70 instances, 67 au vert. Les trois autres sont connues : deux sauvegardes sans donnee a emporter, et Loki en delai de stabilisation apres redeploiement. make prouver : CONFORME, 64 OK, 0 echec, 0 saute. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
309 lines
11 KiB
YAML
309 lines
11 KiB
YAML
---
|
|
- name: Exiger le mot de passe admin LDAP (Vault)
|
|
ansible.builtin.assert:
|
|
that:
|
|
- serveur_openldap_admin_password | length > 0
|
|
fail_msg: "serveur_openldap_admin_password est requis (a fournir via Ansible Vault)."
|
|
|
|
- name: Installer debconf-utils (requis par le module debconf, fournit debconf-get-selections)
|
|
ansible.builtin.apt:
|
|
name: debconf-utils
|
|
state: present
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
|
|
- name: Preconfigurer slapd (debconf)
|
|
ansible.builtin.debconf:
|
|
name: slapd
|
|
question: "{{ item.question }}"
|
|
vtype: "{{ item.vtype }}"
|
|
value: "{{ item.value }}"
|
|
loop:
|
|
- { question: "slapd/no_configuration", vtype: "boolean", value: "false" }
|
|
- { question: "slapd/domain", vtype: "string", value: "{{ serveur_openldap_domaine }}" }
|
|
- { question: "shared/organization", vtype: "string", value: "{{ serveur_openldap_organisation }}" }
|
|
- { question: "slapd/backend", vtype: "select", value: "MDB" }
|
|
- { question: "slapd/purge_database", vtype: "boolean", value: "true" }
|
|
- { question: "slapd/move_old_database", vtype: "boolean", value: "true" }
|
|
- { question: "slapd/allow_ldap_v2", vtype: "boolean", value: "false" }
|
|
loop_control:
|
|
label: "{{ item.question }}"
|
|
|
|
- name: Preconfigurer le mot de passe admin slapd (debconf)
|
|
ansible.builtin.debconf:
|
|
name: slapd
|
|
question: "{{ item }}"
|
|
vtype: password
|
|
value: "{{ serveur_openldap_admin_password }}"
|
|
loop:
|
|
- slapd/password1
|
|
- slapd/password2
|
|
no_log: true
|
|
|
|
- name: Installer OpenLDAP
|
|
ansible.builtin.apt:
|
|
name: "{{ serveur_openldap_paquets }}"
|
|
state: present
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
|
|
- name: Activer et demarrer slapd
|
|
when: not ansible_check_mode
|
|
ansible.builtin.systemd:
|
|
name: "{{ serveur_openldap_service }}"
|
|
enabled: true
|
|
state: started
|
|
|
|
- name: Creer les unites organisationnelles de base
|
|
community.general.ldap_entry:
|
|
dn: "ou={{ item }},{{ serveur_openldap_base_dn }}"
|
|
objectClass: organizationalUnit
|
|
server_uri: "ldapi:///"
|
|
bind_dn: "{{ serveur_openldap_admin_dn }}"
|
|
bind_pw: "{{ serveur_openldap_admin_password }}"
|
|
loop: "{{ serveur_openldap_ou }}"
|
|
loop_control:
|
|
label: "ou={{ item }}"
|
|
no_log: true
|
|
|
|
# --- Politique de mot de passe (overlay ppolicy) ------------------------------
|
|
# Sans cet overlay, `pwdReset` n'existe pas dans le schema : `amorcage_acces` ne peut
|
|
# pas forcer le changement du jeton d'amorcage, et rien ne contraint la qualite ni ne
|
|
# verrouille apres des echecs. Voir docs/autorisation.md §3.
|
|
- name: Ppolicy — Charger le module
|
|
community.general.ldap_attrs:
|
|
dn: "cn=module{0},cn=config"
|
|
attributes:
|
|
olcModuleLoad: "ppolicy"
|
|
state: present
|
|
server_uri: "ldapi:///"
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
# Le DN de la base varie (`olcDatabase={1}mdb` en general, mais l'index n'est pas
|
|
# garanti) : on le LIT au lieu de le supposer.
|
|
- name: Ppolicy — Trouver la base mdb
|
|
community.general.ldap_search:
|
|
dn: "cn=config"
|
|
scope: onelevel
|
|
filter: "(olcDatabase={1}mdb)"
|
|
attrs:
|
|
- dn
|
|
server_uri: "ldapi:///"
|
|
register: serveur_openldap_base_mdb
|
|
changed_when: false
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
- name: Ppolicy — Retenir le DN de la base
|
|
ansible.builtin.set_fact:
|
|
serveur_openldap_mdb_dn: >-
|
|
{{ (serveur_openldap_base_mdb.results | first).dn }}
|
|
when:
|
|
- serveur_openldap_ppolicy_actif | bool
|
|
- (serveur_openldap_base_mdb.results | default([]) | length) > 0
|
|
|
|
- name: Ppolicy — Résoudre la politique (déclaration unique)
|
|
ansible.builtin.include_role:
|
|
name: resoudre_politique_mdp
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
- name: Ppolicy — Creer l unite des politiques
|
|
community.general.ldap_entry:
|
|
dn: "ou=policies,{{ serveur_openldap_base_dn }}"
|
|
objectClass: organizationalUnit
|
|
server_uri: "ldapi:///"
|
|
bind_dn: "{{ serveur_openldap_admin_dn }}"
|
|
bind_pw: "{{ serveur_openldap_admin_password }}"
|
|
no_log: true
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
# L'overlay AVANT la politique : `olcPPolicyDefault` reference une entree qui doit
|
|
# exister, mais l'overlay doit etre en place pour que le schema pwd* soit connu.
|
|
# L'ordre inverse echouerait des deux cotes.
|
|
- name: Ppolicy — Activer l overlay sur la base
|
|
community.general.ldap_entry:
|
|
dn: "olcOverlay=ppolicy,{{ serveur_openldap_mdb_dn }}"
|
|
objectClass:
|
|
- olcOverlayConfig
|
|
- olcPPolicyConfig
|
|
attributes:
|
|
olcOverlay: "ppolicy"
|
|
olcPPolicyDefault: "cn=default,ou=policies,{{ serveur_openldap_base_dn }}"
|
|
olcPPolicyHashCleartext: "{{ 'TRUE' if serveur_openldap_ppolicy_hash_cleartext | bool else 'FALSE' }}"
|
|
olcPPolicyUseLockout: "{{ 'TRUE' if serveur_openldap_ppolicy_use_lockout | bool else 'FALSE' }}"
|
|
server_uri: "ldapi:///"
|
|
when:
|
|
- serveur_openldap_ppolicy_actif | bool
|
|
- serveur_openldap_mdb_dn is defined
|
|
|
|
- name: Ppolicy — Creer la politique par defaut
|
|
community.general.ldap_entry:
|
|
dn: "cn=default,ou=policies,{{ serveur_openldap_base_dn }}"
|
|
objectClass:
|
|
- pwdPolicy
|
|
- person
|
|
- top
|
|
attributes: >-
|
|
{{ {'cn': 'default', 'sn': 'default'}
|
|
| combine(resoudre_politique_mdp_ldap, serveur_openldap_ppolicy_extra) }}
|
|
server_uri: "ldapi:///"
|
|
bind_dn: "{{ serveur_openldap_admin_dn }}"
|
|
bind_pw: "{{ serveur_openldap_admin_password }}"
|
|
no_log: true
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
# `ldap_entry` ne fait que CREER : l'entree restait figee a ce qu'elle valait le
|
|
# jour de sa creation, et toute modification ulterieure de la declaration etait
|
|
# ignoree en silence. Constate le 2026-08-08 — le depot annoncait
|
|
# `pwdMustChange: TRUE`, le serveur portait `FALSE` (corrige a la main apres la
|
|
# boucle de changement de mot de passe du 2026-08-07), et une reconstruction
|
|
# from-zero aurait ressuscite le defaut. Il faut donc RECONCILIER en plus.
|
|
- name: Ppolicy — Reconcilier la politique par defaut
|
|
community.general.ldap_attrs:
|
|
dn: "cn=default,ou=policies,{{ serveur_openldap_base_dn }}"
|
|
attributes: "{{ resoudre_politique_mdp_ldap | combine(serveur_openldap_ppolicy_extra) }}"
|
|
state: exact
|
|
server_uri: "ldapi:///"
|
|
bind_dn: "{{ serveur_openldap_admin_dn }}"
|
|
bind_pw: "{{ serveur_openldap_admin_password }}"
|
|
no_log: true
|
|
when: serveur_openldap_ppolicy_actif | bool
|
|
|
|
# Meme raison : l'overlay non plus n'etait pose qu'a la creation. Son DN porte un
|
|
# index d'ordre (`{0}`, `{1}`…) attribue par slapd — on le LIT, on ne le devine pas.
|
|
- name: Ppolicy — Trouver le DN de l overlay
|
|
community.general.ldap_search:
|
|
dn: "{{ serveur_openldap_mdb_dn }}"
|
|
scope: onelevel
|
|
filter: "(olcOverlay=*ppolicy)"
|
|
attrs:
|
|
- dn
|
|
server_uri: "ldapi:///"
|
|
register: serveur_openldap_overlay_ppolicy
|
|
changed_when: false
|
|
when:
|
|
- serveur_openldap_ppolicy_actif | bool
|
|
- serveur_openldap_mdb_dn is defined
|
|
|
|
- name: Ppolicy — Reconcilier les reglages de l overlay
|
|
community.general.ldap_attrs:
|
|
dn: "{{ (serveur_openldap_overlay_ppolicy.results | first).dn }}"
|
|
attributes:
|
|
olcPPolicyDefault: "cn=default,ou=policies,{{ serveur_openldap_base_dn }}"
|
|
olcPPolicyHashCleartext: "{{ 'TRUE' if serveur_openldap_ppolicy_hash_cleartext | bool else 'FALSE' }}"
|
|
olcPPolicyUseLockout: "{{ 'TRUE' if serveur_openldap_ppolicy_use_lockout | bool else 'FALSE' }}"
|
|
state: exact
|
|
server_uri: "ldapi:///"
|
|
when:
|
|
- serveur_openldap_ppolicy_actif | bool
|
|
- (serveur_openldap_overlay_ppolicy.results | default([]) | length) > 0
|
|
|
|
# --- TLS (LDAPS + STARTTLS) via le certificat step_ca depose par client_pki ---
|
|
- name: TLS — creer le repertoire pont lisible par openldap
|
|
ansible.builtin.file:
|
|
path: "{{ serveur_openldap_tls_dir }}"
|
|
state: directory
|
|
owner: openldap
|
|
group: openldap
|
|
mode: "0750"
|
|
when: serveur_openldap_tls_actif | bool
|
|
|
|
- name: TLS — deployer le script de synchronisation du certificat
|
|
ansible.builtin.template:
|
|
src: setops-slapd-cert-sync.sh.j2
|
|
dest: /usr/local/sbin/setops-slapd-cert-sync
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
when: serveur_openldap_tls_actif | bool
|
|
|
|
- name: TLS — deployer les unites de synchronisation (service + path)
|
|
ansible.builtin.template:
|
|
src: "{{ item.s }}"
|
|
dest: "{{ item.d }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
loop:
|
|
- { s: "setops-slapd-cert-sync.service.j2", d: "/etc/systemd/system/setops-slapd-cert-sync.service" }
|
|
- { s: "setops-slapd-cert-sync.path.j2", d: "/etc/systemd/system/setops-slapd-cert-sync.path" }
|
|
loop_control:
|
|
label: "{{ item.d | basename }}"
|
|
when: serveur_openldap_tls_actif | bool
|
|
|
|
- name: TLS — synchroniser le certificat maintenant (si client_pki l'a depose)
|
|
ansible.builtin.command: /usr/local/sbin/setops-slapd-cert-sync
|
|
changed_when: false
|
|
when:
|
|
- serveur_openldap_tls_actif | bool
|
|
- not ansible_check_mode
|
|
|
|
- name: TLS — activer la surveillance du certificat (renouvellement)
|
|
ansible.builtin.systemd:
|
|
name: setops-slapd-cert-sync.path
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
when:
|
|
- serveur_openldap_tls_actif | bool
|
|
- not ansible_check_mode
|
|
|
|
- name: TLS — verifier que le certificat pont est en place
|
|
ansible.builtin.stat:
|
|
path: "{{ serveur_openldap_tls_dir }}/cert.pem"
|
|
register: serveur_openldap_cert_pont
|
|
when: serveur_openldap_tls_actif | bool
|
|
|
|
- name: TLS — avertir si le certificat n'est pas encore disponible
|
|
ansible.builtin.debug:
|
|
msg: >-
|
|
client_pki n'a pas encore depose de certificat sur ce noeud
|
|
({{ serveur_openldap_tls_source_cert }}). TLS slapd NON configure : deploie
|
|
l'integration client_pki sur ce noeud, puis relance le deploiement.
|
|
when:
|
|
- serveur_openldap_tls_actif | bool
|
|
- not ansible_check_mode
|
|
- not (serveur_openldap_cert_pont.stat.exists | default(false))
|
|
|
|
- name: TLS — configurer slapd (olcTLS* dans cn=config)
|
|
community.general.ldap_attrs:
|
|
dn: cn=config
|
|
server_uri: ldapi:///
|
|
attributes:
|
|
olcTLSCACertificateFile: "{{ serveur_openldap_tls_dir }}/ca.pem"
|
|
olcTLSCertificateFile: "{{ serveur_openldap_tls_dir }}/cert.pem"
|
|
olcTLSCertificateKeyFile: "{{ serveur_openldap_tls_dir }}/key.pem"
|
|
state: exact
|
|
when:
|
|
- serveur_openldap_tls_actif | bool
|
|
- not ansible_check_mode
|
|
- serveur_openldap_cert_pont.stat.exists | default(false)
|
|
notify: Redemarrer slapd
|
|
|
|
- name: TLS — exposer LDAPS (SLAPD_SERVICES)
|
|
ansible.builtin.lineinfile:
|
|
path: /etc/default/slapd
|
|
regexp: '^SLAPD_SERVICES='
|
|
line: 'SLAPD_SERVICES="{{ serveur_openldap_services }}"'
|
|
when:
|
|
- serveur_openldap_tls_actif | bool
|
|
- serveur_openldap_cert_pont.stat.exists | default(false)
|
|
notify: Redemarrer slapd
|
|
|
|
# --- Sonde de supervision (docs/supervision-conception.md) --------------------------
|
|
# Le role qui possede la verite depose sa propre sonde ; le porteur (`client_sante`) la
|
|
# fait tourner et pousse le verdict, sans savoir ce qu'elle mesure.
|
|
- name: Assurer le repertoire des sondes de supervision
|
|
ansible.builtin.file:
|
|
path: /usr/local/lib/setops/sondes
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
|
|
- name: Deposer la sonde « annuaire »
|
|
ansible.builtin.template:
|
|
src: sonde-annuaire.sh.j2
|
|
dest: /usr/local/lib/setops/sondes/annuaire.sh
|
|
owner: root
|
|
group: root
|
|
mode: "0750"
|