Soumission courriel :587 interne (authentifiée) — boucle souveraine bouclée

Postfix (edge-mta) sert :587 (master.cf : STARTTLS + SMTP AUTH, seuls les
authentifiés relaient) ; SASL délégué à Dovecot (infra-mail, passdb LDAP)
via un auth-listener réseau (inet_listener sasl :12345). Interne seulement.

Prouvé (swaks) : testmail s'authentifie (235), Postfix accepte (250 queued),
courriel livré dans la boîte. Le courriel souverain fait recevoir ET envoyer.

Pièges : Dovecot 2.4 exige un nom de section inet_listener ; nouveau service
master.cf → restart (pas reload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-07-03 23:17:36 -04:00
parent 0681cdd72f
commit 457b89927b
6 changed files with 58 additions and 0 deletions

View file

@ -3,6 +3,17 @@
## 2026-07-03
### Ajouté
- **Soumission courriel `:587` interne (authentifiée) — la boucle souveraine est bouclée.**
Postfix (`edge-mta`) sert la **soumission `:587`** (bloc `master.cf` : STARTTLS requis, `SMTP AUTH`,
seuls les authentifiés relaient) ; l'auth SASL est **déléguée à Dovecot** (`infra-mail`, passdb LDAP
prouvé) via un **auth-listener réseau** (`service auth { inet_listener sasl }`, port 12345). Aucune
sortie internet : interne→interne uniquement (l'externe = déliverabilité, Étape B). **Prouvé** (swaks) :
`testmail` s'authentifie (`235 Authentication successful`), Postfix accepte (`250 queued`), et le
courriel est **livré dans la boîte** (LMTP→Dovecot). Le courriel souverain fait maintenant **recevoir
ET envoyer**. Vars : `serveur_dovecot_sasl_reseau`, `serveur_postfix_submission_actif`. Pièges :
Dovecot 2.4 exige un **nom** de section `inet_listener` ; ajouter un service `master.cf` (nouveau
listener) → handler **restart** (pas reload) ; et une config cassée peut bloquer un redéploiement si
la synchro cert/restart précède le template (corriger la config à la main pour débloquer).
- **Sauvegardes applicatives (logiques) — `serveur_backup` + `client_backup` (restic), Tier 0 prouvé.**
Choix : sauvegarder la **donnée d'état** (non régénérable) plutôt que les VM (reconstructibles par
le code + le template). Outil **restic** (chiffrement côté client, déduplication, rétention).

View file

@ -39,3 +39,9 @@ serveur_dovecot_postfix_socket_dir: "/var/spool/postfix/private"
# par LMTP réseau. À restreindre au nœud MTA par pare-feu (nftables) en prod.
serveur_dovecot_lmtp_reseau: true
serveur_dovecot_lmtp_port: 24
# --- Auth SASL réseau : pour la soumission :587 servie par un Postfix DISTANT (edge-mta).
# Dovecot vérifie le mot de passe (passdb LDAP prouvé) pour Postfix. À restreindre au MTA
# par pare-feu ; le trafic d'auth devrait être isolé/chiffré en prod.
serveur_dovecot_sasl_reseau: false
serveur_dovecot_sasl_port: 12345

View file

@ -55,6 +55,16 @@ service lmtp {
}
{% endif %}
{% if serveur_dovecot_sasl_reseau %}
# --- Auth SASL réseau (soumission :587 depuis le MTA distant edge-mta) ---
# À restreindre au nœud MTA par pare-feu.
service auth {
inet_listener sasl {
port = {{ serveur_dovecot_sasl_port }}
}
}
{% endif %}
# --- Sockets pour Postfix (remise LMTP + auth SASL) ---
# Seulement si Postfix est co-localisé (l'utilisateur postfix existe). Sinon Dovecot
# tourne en autonome (IMAP) ; les sockets seront ajoutés au déploiement de serveur_postfix.

View file

@ -18,6 +18,13 @@ serveur_postfix_reseaux_confiance: "127.0.0.0/8 [::1]/128"
serveur_postfix_mailstore_hote: ""
serveur_postfix_lmtp_port: 24
# --- Soumission :587 (clients authentifiés) ---
# SASL délégué à Dovecot (passdb LDAP prouvé) sur le nœud mail-store, via son auth réseau.
# Interne uniquement : STARTTLS requis, seuls les authentifiés relaient. Pas de sortie internet.
serveur_postfix_submission_actif: false
serveur_postfix_sasl_hote: "{{ serveur_postfix_mailstore_hote }}"
serveur_postfix_sasl_port: 12345
# --- Annuaire LDAP (validation domaines/boîtes/alias) ---
# 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 »).

View file

@ -4,3 +4,10 @@
name: "{{ serveur_postfix_service }}"
state: reloaded
when: not ansible_check_mode
# restart (pas reload) quand on ajoute un service master.cf (nouveau listener, ex. :587).
- name: Redémarrer postfix
ansible.builtin.systemd:
name: "{{ serveur_postfix_service }}"
state: restarted
when: not ansible_check_mode

View file

@ -158,6 +158,23 @@
mode: "0644"
notify: Recharger postfix
- name: Activer la soumission :587 (clients authentifiés, SASL Dovecot distant)
ansible.builtin.blockinfile:
path: /etc/postfix/master.cf
marker: "# {mark} SETOPS SUBMISSION 587"
block: |
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=inet:{{ serveur_postfix_sasl_hote }}:{{ serveur_postfix_sasl_port }}
-o smtpd_sasl_security_options=noanonymous
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
when: serveur_postfix_submission_actif | bool
notify: Redémarrer postfix
- name: Valider la configuration Postfix
ansible.builtin.command: postfix check
changed_when: false