PostgreSQL : servir le cert step-ca (TLS vérifiable), non-bloquant
Zéro-confiance flux PG, côté serveur : cert-sync (owned postgres, motif .path comme Dovecot/Postfix) + ssl_cert/key/ca_file pointant sur le cert step-ca au lieu du snakeoil. Garde-fou : ssl non activé si le cert n'est pas en place. Reload robuste (instance postgresql@NN-main, pas le wrapper). Prouvé sur data-sql-01 : cert servi = Set-OPS Internal CA (vérif root_ca ok), keycloak/forgejo toujours 200 (TLS reste optionnel, rien de cassé). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
b6952759f5
commit
5aa7fcafdb
6 changed files with 133 additions and 0 deletions
|
|
@ -36,3 +36,12 @@ serveur_postgresql_comptes: []
|
|||
serveur_postgresql_bases: []
|
||||
# - nom: keycloak
|
||||
# proprietaire: keycloak
|
||||
|
||||
# --- TLS via le certificat d'hote step_ca (client_pki requis sur le noeud) ---
|
||||
# Cote serveur : PostgreSQL sert le cert step_ca (verifiable contre root_ca), au lieu
|
||||
# du snakeoil auto-signe. Non-bloquant : le TLS reste optionnel tant que pg_hba ne le force pas.
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,79 @@
|
|||
group: postgres
|
||||
mode: "0755"
|
||||
|
||||
# --- TLS : synchroniser le cert step_ca AVANT d'activer ssl (ordre critique) ---
|
||||
- name: TLS — assurer le repertoire des certificats (postgres)
|
||||
ansible.builtin.file:
|
||||
path: "{{ serveur_postgresql_tls_dir }}"
|
||||
state: directory
|
||||
owner: postgres
|
||||
group: postgres
|
||||
mode: "0700"
|
||||
when: serveur_postgresql_tls_actif | bool
|
||||
|
||||
- name: TLS — deployer le script de synchronisation du certificat
|
||||
ansible.builtin.template:
|
||||
src: setops-postgresql-cert-sync.sh.j2
|
||||
dest: /usr/local/sbin/setops-postgresql-cert-sync
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
when: serveur_postgresql_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-postgresql-cert-sync.service.j2", d: "/etc/systemd/system/setops-postgresql-cert-sync.service" }
|
||||
- { s: "setops-postgresql-cert-sync.path.j2", d: "/etc/systemd/system/setops-postgresql-cert-sync.path" }
|
||||
loop_control:
|
||||
label: "{{ item.d | basename }}"
|
||||
when: serveur_postgresql_tls_actif | bool
|
||||
|
||||
- name: TLS — activer la surveillance du certificat (path)
|
||||
ansible.builtin.systemd:
|
||||
name: setops-postgresql-cert-sync.path
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
when:
|
||||
- serveur_postgresql_tls_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: TLS — synchroniser le certificat maintenant
|
||||
ansible.builtin.command: /usr/local/sbin/setops-postgresql-cert-sync
|
||||
changed_when: false
|
||||
when:
|
||||
- serveur_postgresql_tls_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: TLS — verifier la presence du certificat synchronise
|
||||
ansible.builtin.stat:
|
||||
path: "{{ serveur_postgresql_tls_dir }}/{{ item }}"
|
||||
register: serveur_postgresql_tls_stat
|
||||
loop:
|
||||
- server.crt
|
||||
- server.key
|
||||
when:
|
||||
- serveur_postgresql_tls_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: TLS — garde-fou, refuser d'activer ssl sans certificat en place
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- item.stat.exists
|
||||
fail_msg: "Certificat PG absent ({{ item.item }}) — ssl non active pour ne rien casser."
|
||||
loop: "{{ serveur_postgresql_tls_stat.results | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
when:
|
||||
- serveur_postgresql_tls_actif | bool
|
||||
- not ansible_check_mode
|
||||
|
||||
- name: Deployer la configuration Set-OPS
|
||||
ansible.builtin.template:
|
||||
src: 99-setops.conf.j2
|
||||
|
|
|
|||
|
|
@ -2,6 +2,13 @@
|
|||
listen_addresses = '{{ serveur_postgresql_ecoute | join(",") }}'
|
||||
port = {{ serveur_postgresql_port }}
|
||||
password_encryption = '{{ serveur_postgresql_methode_auth }}'
|
||||
{% if serveur_postgresql_tls_actif | default(false) %}
|
||||
# TLS via le certificat d'hote step_ca (synchronise par setops-postgresql-cert-sync).
|
||||
ssl = on
|
||||
ssl_cert_file = '{{ serveur_postgresql_tls_dir }}/server.crt'
|
||||
ssl_key_file = '{{ serveur_postgresql_tls_dir }}/server.key'
|
||||
ssl_ca_file = '{{ serveur_postgresql_tls_dir }}/root.crt'
|
||||
{% endif %}
|
||||
{% for cle, valeur in serveur_postgresql_parametres.items() %}
|
||||
{{ cle }} = '{{ valeur }}'
|
||||
{% endfor %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
# Géré par Set-OPS (rôle serveur_postgresql). Ne pas éditer à la main.
|
||||
# Surveille le certificat step_ca : au renouvellement (client_pki), resynchronise
|
||||
# vers PostgreSQL et le recharge.
|
||||
[Unit]
|
||||
Description=Set-OPS — surveille le certificat step_ca de PostgreSQL
|
||||
|
||||
[Path]
|
||||
PathChanged={{ serveur_postgresql_tls_source_cert }}
|
||||
Unit=setops-postgresql-cert-sync.service
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Géré par Set-OPS (rôle serveur_postgresql). Ne pas éditer à la main.
|
||||
[Unit]
|
||||
Description=Set-OPS — synchronise le certificat step_ca vers PostgreSQL
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/sbin/setops-postgresql-cert-sync
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
# Géré par Set-OPS (rôle serveur_postgresql). Ne pas éditer à la main.
|
||||
# Synchronise le certificat step_ca (déposé par client_pki, root:root) vers un
|
||||
# emplacement lisible par postgres, puis recharge. PostgreSQL lit en tant que
|
||||
# 'postgres' et REFUSE une clé accessible au groupe/monde → owner postgres, 0600.
|
||||
# Idempotent ; appelé au déploiement ET au renouvellement (unité .path).
|
||||
set -eu
|
||||
|
||||
SRC_CERT="{{ serveur_postgresql_tls_source_cert }}"
|
||||
SRC_KEY="{{ serveur_postgresql_tls_source_cle }}"
|
||||
SRC_CA="{{ serveur_postgresql_tls_source_ca }}"
|
||||
DST="{{ serveur_postgresql_tls_dir }}"
|
||||
|
||||
[ -f "$SRC_CERT" ] && [ -f "$SRC_KEY" ] || exit 0
|
||||
|
||||
install -o postgres -g postgres -m 0644 "$SRC_CERT" "$DST/server.crt"
|
||||
install -o postgres -g postgres -m 0600 "$SRC_KEY" "$DST/server.key"
|
||||
[ -f "$SRC_CA" ] && install -o postgres -g postgres -m 0644 "$SRC_CA" "$DST/root.crt"
|
||||
|
||||
# Reload (SIGHUP) : PostgreSQL recharge ses fichiers TLS sans coupure.
|
||||
# ATTENTION : 'postgresql' est un wrapper Debian (reload = no-op) ; il faut recharger
|
||||
# la ou les INSTANCES de cluster (postgresql@NN-main), sinon le nouveau cert n'est pas pris.
|
||||
for u in $(systemctl list-units --plain --no-legend 'postgresql@*' 2>/dev/null | awk '{print $1}'); do
|
||||
systemctl reload "$u" 2>/dev/null || true
|
||||
done
|
||||
Loading…
Reference in a new issue