Set-OPS-Public/playbooks/maintenance/devis-courriel.yml

119 lines
4.4 KiB
YAML
Raw Normal View History

devis PostgreSQL et courriel : la serie des devis de service est complete PostgreSQL — rend visibles deux defauts deja vecus ici : un reseau ECRIT dans pg_hba au lieu d'etre derive, et une ligne host en clair la ou il faut hostssl (verrou qui saute sans bruit, les clients verify-full continuant de marcher). Interroge pg_settings, jamais le fichier : un grep de postgresql.conf annonce ssl_cert_file=snakeoil alors que le serveur sert le certificat de l'AC — la valeur vient d'un conf.d que le grep ne voyait pas. L'instrument etait incomplet, pas la configuration. Courriel — chaque maillon interroge la ou il dit la verite : postmap -q pour la resolution LDAP de Postfix, doveadm user pour celle de Dovecot (le maillon exact ou la livraison avait bloque), vraies conversations SMTP/IMAP. Verifie aussi qu'une adresse INEXISTANTE ne resout pas — sinon la boite est un fourre-tout et le devis ne mesure plus rien. Trouve immediatement une divergence reelle : Dovecot connait la boite de sysadmin@chezlepro.internal, Postfix ne sait pas y router (query_filter (mail=%s), et l'attribut mail porte sysadmin@chezlepro.ca). Collision de roles : une identite ne porte qu'une adresse mail et on lui en demande deux — notification joignable hors du systeme, et cle de routage local. Arbitrage a rendre avant correction. Tests negatifs : PostgreSQL 3 ecarts nommes, code 1. Une variable morte trouvee dans une branche que le cas nominal n'emprunte jamais. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 08:53:49 -04:00
---
# Devis du courriel — RELEVE seul. Ne modifie rien (D-23).
#
# La chaine est longue — Postfix -> LDAP -> LMTP -> Dovecot -> IMAP — et chaque maillon
# peut casser sans que le suivant s'en apercoive. On interroge donc chaque maillon la
# ou il dit la verite : `postmap -q` pour la resolution LDAP de Postfix, `doveadm user`
# pour celle de Dovecot (c'est precisement la ou la livraison avait bloque), et une vraie
# conversation SMTP pour ce que le serveur accepte.
#
# make courriel-plan
- name: Devis du courriel — Postfix
hosts: serveur_postfix
become: true
gather_facts: false
tasks:
- name: Résoudre la connexion à l'annuaire
ansible.builtin.include_role:
name: resoudre_annuaire
- name: Choisir un compte réel comme sonde
community.general.ldap_search:
dn: "{{ resoudre_annuaire_users_dn }}"
scope: onelevel
filter: "(objectClass=inetOrgPerson)"
attrs: ["uid"]
server_uri: "{{ resoudre_annuaire_uri }}"
bind_dn: "{{ resoudre_annuaire_bind_dn }}"
bind_pw: "{{ resoudre_annuaire_bind_password }}"
register: devis_courriel_comptes
changed_when: false
no_log: true
delegate_to: "{{ groups['serveur_openldap'] | first }}"
- name: Retenir l'adresse sonde
ansible.builtin.set_fact:
devis_courriel_sonde: "{{ (devis_courriel_comptes.results | first).uid }}@{{ domaine_interne }}"
- name: Relever Postfix (résolution LDAP, portée du relais, dialecte SMTP)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -uo pipefail
echo "SONDE={{ devis_courriel_sonde }}"
echo "TROUVE=$(postmap -q '{{ devis_courriel_sonde }}' \
ldap:/etc/postfix/ldap-mailboxes.cf 2>/dev/null)"
# Une adresse qui n'existe pas DOIT rester sans reponse : sinon la boite est
# un fourre-tout et n'importe quel nom serait accepte.
echo "FANTOME=$(postmap -q 'nexistepas-{{ 999 | random }}@{{ domaine_interne }}' \
ldap:/etc/postfix/ldap-mailboxes.cf 2>/dev/null)"
echo "MYNETWORKS=$(postconf -h mynetworks)"
for P in 25 587; do
echo "PORT=$P"
exec 3<>/dev/tcp/127.0.0.1/$P || continue
read -r -t 5 _ <&3
printf 'EHLO devis.local\r\n' >&3
while read -r -t 5 L <&3; do
echo " $L"
[ "${L:3:1}" = " " ] && break
done
printf 'QUIT\r\n' >&3
exec 3<&- 3>&-
done
register: devis_courriel_postfix
changed_when: false
- name: Déposer le relevé Postfix
ansible.builtin.copy:
dest: "{{ playbook_dir }}/../../instance/devis-courriel.json.postfix"
mode: "0600"
content: >-
{{ {'hote': inventory_hostname, 'role': 'postfix',
'supernet': setops_supernet | default(''),
'brut': devis_courriel_postfix.stdout} | to_nice_json }}
delegate_to: localhost
become: false
- name: Devis du courriel — Dovecot
hosts: serveur_dovecot
become: true
gather_facts: false
tasks:
- name: Relever Dovecot (résolution userdb et dialecte IMAP)
ansible.builtin.shell:
executable: /bin/bash
cmd: |
set -uo pipefail
SONDE="{{ hostvars[groups['serveur_postfix'] | first]['devis_courriel_sonde'] }}"
echo "SONDE=$SONDE"
# `doveadm user` est le maillon exact ou la livraison avait bloque : c'est lui
# qui dit si Dovecot sait ou ecrire pour cette adresse.
echo "USERDB<<"
doveadm user "$SONDE" 2>&1 | head -12
echo ">>"
echo "PORT=143"
exec 3<>/dev/tcp/127.0.0.1/143 || exit 0
read -r -t 5 BANNIERE <&3
echo " $BANNIERE"
printf 'a CAPABILITY\r\n' >&3
while read -r -t 5 L <&3; do
echo " $L"
case "$L" in a\ *) break ;; esac
done
printf 'b LOGOUT\r\n' >&3
register: devis_courriel_dovecot
changed_when: false
- name: Déposer le relevé Dovecot
ansible.builtin.copy:
dest: "{{ playbook_dir }}/../../instance/devis-courriel.json.dovecot"
mode: "0600"
content: >-
{{ {'hote': inventory_hostname, 'role': 'dovecot',
'brut': devis_courriel_dovecot.stdout} | to_nice_json }}
delegate_to: localhost
become: false