Set-OPS-Public/roles/serveur_backup/tasks/main.yml
Daniel Allaire 4dd4d3755d icinga : le pair est verifie — mais pas avec un certificat step-ca
Objectif : supprimer le `curl -k` du rapporteur. Fait, et la maniere a ete
imposee par la mesure.

SERVIR UN CERTIFICAT STEP-CA SUR L'API EST IMPOSSIBLE. Icinga le dit lui-meme :
« Our certificate will expire soon, but we own the CA. Renewing. » Il renouvelle
tout certificat expirant sous 30 jours ; les notres vivent 24 h ; possedant une
AC, il re-emet avec la sienne et ecrase le notre a chaque demarrage. Collision
entre deux politiques de PKI, et la notre n'est pas negociable.

Deux decouvertes en chemin, toutes deux par le garde-fou `icinga2 daemon -C`
ajoute au role, qui a ARRETE le deploiement avant de redemarrer la supervision :
  - cert_path/key_path/ca_path sont DEPRECIES depuis 2.8 ; les poser reveille un
    chemin de code herite qui exige en plus un objet Endpoint ;
  - l'identite de l'API est le CN du certificat. NodeName valait « mon-01 », donc
    le SAN aussi, alors qu'on appelle par le FQDN : aucune verification n'aurait
    pu reussir. NodeName est desormais aligne sur le FQDN.

A LA PLACE : Icinga garde son AC (domaine de confiance FERME, legitime) et
backup-01 verifie le pair contre CETTE AC, recuperee depuis mon-01 au
deploiement. Le pair est authentifie ; seule la racine differe.

Controle negatif — une verification qu'on ne teste pas est un ornement : avec la
mauvaise AC (step-ca), curl refuse (« unable to get local issuer certificate ») ;
avec la bonne, les neuf rapports passent.

Sous-AC step-ca ecartee : elle poserait sur l'hote de supervision une cle capable
d'EMETTRE pour n'importe quel nom, alors qu'on a choisi le sens du flux pour que
compromettre mon-01 ne donne rien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 08:33:50 -04:00

127 lines
4.2 KiB
YAML

---
- name: Exiger la clé publique de sauvegarde
ansible.builtin.assert:
that:
- serveur_backup_pubkey | length > 0
fail_msg: "serveur_backup_pubkey requis (clé publique de la paire de sauvegarde)."
- name: Créer l'utilisateur de sauvegarde
ansible.builtin.user:
name: "{{ serveur_backup_utilisateur }}"
home: "{{ serveur_backup_racine }}"
shell: /bin/bash
create_home: true
system: true
- name: Sécuriser la racine des dépôts
ansible.builtin.file:
path: "{{ serveur_backup_racine }}"
state: directory
owner: "{{ serveur_backup_utilisateur }}"
group: "{{ serveur_backup_utilisateur }}"
mode: "0700"
- name: Autoriser la clé SSH de sauvegarde
ansible.posix.authorized_key:
user: "{{ serveur_backup_utilisateur }}"
key: "{{ serveur_backup_pubkey }}"
state: present
# --- Vérification des dépôts et rapport passif vers Icinga ---
# La liste des détenteurs d'état appartient à `client_backup`. On la LIT chez lui : deux
# listes finissent toujours par diverger, et la divergence se lirait « tout va bien ».
- name: Lire la liste des détenteurs d'état chez client_backup
ansible.builtin.include_vars:
file: "{{ role_path }}/../client_backup/vars/main.yml"
name: _catalogue_sauvegarde
- name: Adopter la liste des détenteurs d'état
ansible.builtin.set_fact:
client_backup_groupes_etat: "{{ _catalogue_sauvegarde.client_backup_groupes_etat }}"
- name: Exiger de quoi rapporter à Icinga (Vault + hôte de supervision)
ansible.builtin.assert:
that:
- serveur_backup_icinga_motdepasse | length > 0
- serveur_backup_icinga_hote | length > 0
- serveur_backup_noeuds_attendus | length > 0
fail_msg: >-
vault_icinga_api_depot requis, un hôte du groupe `serveur_icinga` doit exister, et
au moins un nœud doit détenir de l'état. Sans cela, les sauvegardes ne seraient
surveillées par personne — c'est exactement le silence qui a laissé le défaut du
2026-07-03 vivre un mois.
- name: Installer curl et le mot de passe restic pour la vérification
ansible.builtin.apt:
name: [curl, restic]
state: present
- name: Créer le répertoire des secrets Set-OPS
ansible.builtin.file:
path: /etc/setops
state: directory
owner: root
group: root
mode: "0700"
- name: Déposer le mot de passe restic (lecture des dépôts)
ansible.builtin.copy:
content: "{{ vault_restic_password }}\n"
dest: /etc/setops/restic.pass
owner: root
group: root
mode: "0600"
no_log: true
- name: Déposer le mot de passe d'API Icinga
ansible.builtin.copy:
content: "{{ serveur_backup_icinga_motdepasse }}"
dest: /etc/setops/icinga-api.pass
owner: root
group: root
mode: "0600"
no_log: true
# L'API Icinga presente un certificat emis par l'AC d'Icinga (il refuse d'en servir un
# autre : il renouvelle tout ce qui expire sous 30 jours, or nos certificats vivent 24 h).
# On recupere donc CETTE AC pour verifier le pair — plutot que de sauter la verification.
- name: Récupérer l'AC d'Icinga depuis l'hôte de supervision
ansible.builtin.slurp:
src: "{{ serveur_backup_icinga_ca_source }}"
delegate_to: "{{ serveur_backup_icinga_hote }}"
register: serveur_backup_ca_icinga
- name: Déposer l'AC d'Icinga pour la vérification du pair
ansible.builtin.copy:
content: "{{ serveur_backup_ca_icinga.content | b64decode }}"
dest: "{{ serveur_backup_ca_verification }}"
owner: root
group: root
mode: "0644"
- name: Déployer le script de vérification
ansible.builtin.template:
src: verifier-sauvegardes.sh.j2
dest: /usr/local/sbin/setops-verifier-sauvegardes.sh
owner: root
group: root
mode: "0700"
- name: Déployer l'unité et le timer de vérification
ansible.builtin.template:
src: "{{ item.s }}"
dest: "/etc/systemd/system/{{ item.d }}"
owner: root
group: root
mode: "0644"
loop:
- { s: setops-verification.service.j2, d: setops-verification.service }
- { s: setops-verification.timer.j2, d: setops-verification.timer }
- name: Activer le timer de vérification
when: not ansible_check_mode
ansible.builtin.systemd:
name: setops-verification.timer
enabled: true
state: started
daemon_reload: true