From 204910edbf9ed0ca532d6ec674174ed7ba568d91 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Sat, 4 Jul 2026 20:46:53 -0400 Subject: [PATCH] =?UTF-8?q?Z=C3=A9ro-confiance=20PG=20:=20verrou=20hostssl?= =?UTF-8?q?=20+=20d=C3=A9tection=20de=20version=20robuste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pg_hba hostssl (serveur_postgresql_tls_force) : refuse les connexions non-TLS du réseau. Posé après validation des 3 clients en verify-full. - Fix : tls_dir sous /etc/postgresql collisionnait avec la détection de version (find|sort|last prenait 'tls') → filtre numérique ^[0-9]+$ + tls_dir déplacé sous /var/lib/postgresql/tls. Prouvé : non-TLS rejeté (« aucun chiffrement »), TLS accepté, 3 apps 200. Co-Authored-By: Claude Opus 4.8 --- CHANGELOG.md | 16 ++++++++++++++++ roles/serveur_postgresql/defaults/main.yml | 6 +++++- roles/serveur_postgresql/tasks/main.yml | 3 ++- .../serveur_postgresql/templates/pg_hba.conf.j2 | 3 ++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa4f27f..36f942a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,23 @@ ## 2026-07-04 +### Ajouté +- **Zéro-confiance : flux PostgreSQL entièrement chiffré et vérifié.** PG sert désormais son **cert + step-ca** (vérifiable contre root_ca) au lieu du snakeoil, et **refuse** toute connexion non-TLS + du réseau (`hostssl` dans pg_hba). Les 3 clients passent en **verify-full** : keycloak + (`db-url-properties sslmode=verify-full`), forgejo (`SSL_MODE=verify-full` + `PGSSLROOTCERT`), + IcingaDB (`tls: true` + `ca`). Prérequis posés : `client_pki` sur data-sql-01 (cert), et + **`root_ca.crt` en 0644** (cert public, requis par les clients TLS non-root). cert-sync PG + (motif `.path`, owned postgres) + reload de l'instance `postgresql@NN-main`. Vars : + `serveur_postgresql_tls_actif`/`_tls_force`, `serveur_*_db_sslmode`/`_ca`. Prouvé de bout en bout + (cert Set-OPS CA servi, apps 200, non-TLS rejeté « aucun chiffrement », TLS accepté). + ### Corrigé +- **PG : détection de version robuste (collision avec un répertoire non-numérique).** Placer le + `tls_dir` sous `/etc/postgresql/` faisait choisir `tls` comme « version » de cluster + (`find | sort | last`) → configs déployées au mauvais endroit (verrou hostssl inopérant). + Corrigé : détection filtrée aux dossiers **numériques** (`^[0-9]+$`) + `tls_dir` déplacé sous + `/var/lib/postgresql/tls`. - **Renouvellement de cert : recharger le VRAI consommateur (bug latent de flotte).** Le `cert-renewer@.service` (client_pki) renouvelait le cert sur disque mais son `ExecStartPost` rechargeait un service nommé *d'après le cert* (`%i` = FQDN), inexistant → **nginx (et postfix, diff --git a/roles/serveur_postgresql/defaults/main.yml b/roles/serveur_postgresql/defaults/main.yml index d9f09ca..4764a1b 100644 --- a/roles/serveur_postgresql/defaults/main.yml +++ b/roles/serveur_postgresql/defaults/main.yml @@ -44,4 +44,8 @@ serveur_postgresql_tls_actif: false serveur_postgresql_tls_source_cert: "/etc/step/certs/{{ ansible_fqdn | default(ansible_hostname) }}.crt" serveur_postgresql_tls_source_cle: "/etc/step/certs/{{ ansible_fqdn | default(ansible_hostname) }}.key" serveur_postgresql_tls_source_ca: "/etc/step/certs/root_ca.crt" -serveur_postgresql_tls_dir: "/etc/postgresql/tls" +serveur_postgresql_tls_dir: "/var/lib/postgresql/tls" + +# Verrou zero-confiance : hostssl dans pg_hba => refuse toute connexion NON-TLS. +# N'activer qu'apres avoir confirme que TOUS les clients sont en TLS (sinon coupure). +serveur_postgresql_tls_force: false diff --git a/roles/serveur_postgresql/tasks/main.yml b/roles/serveur_postgresql/tasks/main.yml index 55ae38a..637ba9f 100644 --- a/roles/serveur_postgresql/tasks/main.yml +++ b/roles/serveur_postgresql/tasks/main.yml @@ -17,7 +17,8 @@ ansible.builtin.set_fact: serveur_postgresql_version_effective: >- {{ serveur_postgresql_version - or (serveur_postgresql_clusters.files | map(attribute='path') | map('basename') | sort | last | default('')) }} + or (serveur_postgresql_clusters.files | map(attribute='path') | map('basename') + | select('match', '^[0-9]+$') | sort | last | default('')) }} - name: Refuser si aucun cluster PostgreSQL n'est present ansible.builtin.assert: diff --git a/roles/serveur_postgresql/templates/pg_hba.conf.j2 b/roles/serveur_postgresql/templates/pg_hba.conf.j2 index ee2a30e..89683e9 100644 --- a/roles/serveur_postgresql/templates/pg_hba.conf.j2 +++ b/roles/serveur_postgresql/templates/pg_hba.conf.j2 @@ -6,6 +6,7 @@ local all all peer host all all 127.0.0.1/32 {{ serveur_postgresql_methode_auth }} host all all ::1/128 {{ serveur_postgresql_methode_auth }} # Reseaux internes autorises (clients applicatifs). +# tls_force => hostssl : SEULES les connexions TLS sont acceptees (zero-confiance). {% for reseau in serveur_postgresql_reseaux_autorises %} -host all all {{ reseau }} {{ serveur_postgresql_methode_auth }} +{{ 'hostssl' if serveur_postgresql_tls_force | default(false) else 'host' }} all all {{ reseau }} {{ serveur_postgresql_methode_auth }} {% endfor %}