Set-OPS-Public/roles/serveur_icinga/tasks/main.yml
Daniel Allaire 42becd0c02
Some checks are pending
verifier / verifier (push) Waiting to run
paquets tiers : passer par le cache du controleur, plus par Internet
Trois depots tiers etaient en HTTPS, et client_artefacts pose
Acquire::https::Proxy DIRECT — sans quoi le cache du site refuse les tunnels et
aucun depot tiers n est joignable. La ligne est juste ; sa consequence ne l avait
pas ete vue : ces trois depots CONTOURNENT le cache, et chaque VM neuve allait
les chercher sur Internet a sa naissance.

step-cli et alloy sont poses par des integrations UNIVERSELLES. Sans lien, une
machine neuve n obtenait ni son client d autorite ni ses metriques — elle n
entrait dans aucun flux chiffre. Dernier obstacle a une reconstruction hors
ligne, et il tenait dans un mot.

make cacher-paquets tire les 21 deb aux versions epinglees, empreinte SHA256
verifiee depuis l index du depot. Le role partage paquets_tiers les depose et les
installe EN UN SEUL appel a apt — il sait resoudre un ensemble de fichiers locaux
qui se dependent, la ou paquet par paquet echouerait sur l ordre (Icinga en
apporte dix-sept). Six roles branches ; chacun retombe sur le depot distant pour
ce que le cache n a PAS fourni, et rien d autre.

Eprouve pour de vrai : packages.smallstep.com renvoye vers 127.0.0.1, step-cli
desinstalle, cache local efface. Le role rejoue installe 0.30.6-1 depuis le cache
et la machine obtient ses certificats. Zero echec.

Deux defauts de mon propre outil, trouves en le construisant : Smallstep sert son
index NON COMPRESSE (404 sur .gz) donc step-cli n etait jamais mis en cache ; et
un depot injoignable faisait continue AVANT d incrementer le total, si bien que
le script rapportait 20 sur 20 alors qu il en manquait un. Une garde qui ne peut
pas echouer ne garde rien — troisieme fois cette semaine. Corrige puis eprouve en
le faisant echouer.

Reste hors ligne : NTP externe, et l expedition des alertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 08:22:14 -04:00

250 lines
10 KiB
YAML

---
# Recuperee UNE FOIS. Sans garde, chaque deploiement recontactait le serveur du
# fournisseur : cinq cles x quatorze hotes = soixante-dix allers-retours externes pour
# des cles deja installees, et autant d'occasions qu'un tiers lent fasse tomber le
# deploiement. Arbitrage rendu le 2026-08-09 : une plateforme souveraine ne depend pas
# de six serveurs etrangers pour redeployer ce qu'elle possede deja.
#
# CONSEQUENCE ASSUMEE : une rotation de cle amont n'est plus recuperee toute seule. Elle
# ne passe pas inapercue pour autant — `apt` refuse alors le depot, bruyamment. Pour
# forcer le rafraichissement : supprimer le fichier et rejouer le role.
- name: Cette ressource est-elle deja recuperee ? (Telecharger le trousseau de cles I)
ansible.builtin.stat:
path: "/tmp/icinga-archive-keyring.deb"
register: telecharger_le_trousseau_de_cles_icinga_present
- name: Telecharger le trousseau de cles Icinga
when: not telecharger_le_trousseau_de_cles_icinga_present.stat.exists
ansible.builtin.get_url:
url: "{{ serveur_icinga_keyring_url }}"
dest: "/tmp/icinga-archive-keyring.deb"
mode: "0644"
- name: Installer le trousseau de cles Icinga
ansible.builtin.apt:
deb: "/tmp/icinga-archive-keyring.deb"
state: present
- name: Ajouter le depot apt Icinga
ansible.builtin.apt_repository:
repo: "{{ serveur_icinga_depot_source }}"
filename: icinga
state: present
# LE CACHE DU CONTROLEUR D'ABORD, LE DEPOT DISTANT POUR LE RESTE (2026-09-03).
#
# Les depots tiers sont en HTTPS, et `client_artefacts` pose
# `Acquire::https::Proxy "DIRECT"` — ils CONTOURNENT donc le cache du site et sortent sur
# Internet a chaque construction de VM. `make cacher-paquets` les tire une fois, versions
# epinglees et empreintes verifiees ; ce role les depose depuis ce cache.
- name: Poser les paquets tiers depuis le cache du controleur
ansible.builtin.include_role:
name: paquets_tiers
vars:
paquets_tiers_noms: "{{ serveur_icinga_paquets }}"
- name: Installer Icinga 2, Icinga DB et Redis dedie
ansible.builtin.apt:
# CE QUE LE CACHE N'A PAS FOURNI, ET RIEN D'AUTRE. Les dependances Debian passent
# par le cache du site en HTTP ; seuls les paquets tiers non caches exigent Internet.
# Reinstaller ce que le cache vient de poser ferait un `update_cache` inutile — et
# hors ligne, il echouerait APRES un travail deja fait.
name: "{{ serveur_icinga_paquets | difference((paquets_tiers_disponibles | default({})).keys() | list) }}"
state: present
update_cache: true
when: (serveur_icinga_paquets
| difference((paquets_tiers_disponibles | default({})).keys() | list)) | length > 0
- name: Resoudre la base de donnees depuis le registre (role partage)
ansible.builtin.include_role:
name: resoudre_base
vars:
resoudre_base_groupe: "{{ serveur_icinga_groupe }}"
- name: Adopter les facts de base pour Icinga
ansible.builtin.set_fact:
serveur_icinga_entree: "{{ resoudre_base_entree }}"
serveur_icinga_db_password: "{{ resoudre_base_db_password }}"
serveur_icinga_db_host: "{{ resoudre_base_db_host }}"
no_log: true
# --- Identite TLS de l'API (5665) ---
# ON NE TOUCHE PAS A `NodeName` — et il n'y a rien a corriger ici.
#
# `icinga2 api setup` ECRIT lui-meme NodeName d'apres `hostname -f`, puis nomme ses
# certificats d'apres lui. Tant que `/etc/hosts` mettait le nom COURT en premier,
# `hostname -f` rendait « mon-01 » et le certificat devenait invérifiable en appelant par
# le nom complet. On a longuement tente d'aligner NodeName a la main, avant et apres
# `api setup` : efface a chaque fois.
#
# LA CAUSE ETAIT AILLEURS. Depuis que `hosts_statiques` place le FQDN en premier
# (2026-08-13), `hostname -f` rend le nom complet et Icinga s'emet spontanement un
# certificat CN et SAN = FQDN. Rien a forcer : il suffisait que la machine sache
# comment elle s'appelle.
- name: Configurer l'API Icinga 2
ansible.builtin.command:
cmd: icinga2 api setup
creates: /etc/icinga2/features-enabled/api.conf
notify: Redemarrer icinga2
- name: Activer la fonctionnalite icingadb dans Icinga 2
ansible.builtin.command:
cmd: icinga2 feature enable icingadb
creates: /etc/icinga2/features-enabled/icingadb.conf
notify: Redemarrer icinga2
- name: Activer et demarrer le Redis Icinga DB
when: not ansible_check_mode
ansible.builtin.systemd:
name: "{{ serveur_icinga_service_redis }}"
enabled: true
state: started
- name: Importer le schema Icinga DB dans PostgreSQL (une fois)
ansible.builtin.shell:
cmd: >-
PGPASSWORD='{{ serveur_icinga_db_password }}'
psql -h {{ serveur_icinga_db_host }} -U {{ serveur_icinga_entree.proprietaire }}
-d {{ serveur_icinga_entree.base }} -f {{ serveur_icinga_schema }}
&& touch /etc/icingadb/.schema-imported
creates: /etc/icingadb/.schema-imported
no_log: true
- name: Deployer la configuration Icinga DB
ansible.builtin.template:
src: config.yml.j2
dest: "{{ serveur_icinga_config }}"
owner: root
group: icingadb
mode: "0640"
no_log: true
notify: Redemarrer icingadb
# `icinga2 api setup` active la fonctionnalite EN MEME TEMPS qu'il pose les certificats,
# et sa garde `creates:` la saute des que le fichier existe. Consequence mesuree le
# 2026-08-12 : apres un nettoyage des certificats, l'API restait DESACTIVEE — icinga2
# demarrait, se declarait `active`, et n'ecoutait sur rien. Exiger l'activation
# separement rend l'etat independant de l'ordre des nettoyages.
- name: API — exiger que la fonctionnalite soit activee
ansible.builtin.command:
cmd: icinga2 feature enable api
creates: /etc/icinga2/features-enabled/api.conf
notify: Redemarrer icinga2
- name: API — durcir l'ApiListener (aucune config ni commande acceptee)
ansible.builtin.template:
src: api.conf.j2
dest: /etc/icinga2/features-available/api.conf
owner: root
group: nagios
mode: "0640"
notify: Redemarrer icinga2
# --- Supervision des sauvegardes ---
# La liste des detenteurs d'etat appartient a `client_backup`. On la LIT chez lui plutot
# que de la recopier : deux listes finissent toujours par diverger, et la divergence se
# lirait « tout va bien » des deux cotes.
- name: Lire la liste des detenteurs d'etat chez client_backup
ansible.builtin.include_vars:
file: "{{ role_path }}/../client_backup/vars/main.yml"
name: _catalogue_sauvegarde
- name: Adopter la liste des detenteurs d'etat
ansible.builtin.set_fact:
client_backup_groupes_etat: "{{ _catalogue_sauvegarde.client_backup_groupes_etat }}"
# UN ECOSYSTEME PEUT N'AVOIR AUCUN DEPOT A LUI, ET C'EST LE CAS NORMAL DEPUIS QU'ILS
# DEPOSENT CHEZ LEUR HEBERGEUR (2026-09-02).
#
# Cette assertion exigeait un hote `serveur_backup` dans l'ecosysteme. C'etait juste tant
# que le depot y vivait : il etait le seul a voir ce qui arrivait vraiment, et il
# rapportait pour tout le monde.
#
# Depuis la bascule vers le depot du SITE, l'ecosysteme n'en a plus. Le site, lui, ne
# peut pas ouvrir ces depots — restic chiffre chez le client. C'est donc chaque NOEUD qui
# verifie le sien (`client_backup/tasks/verifier.yml`) et rapporte ici. Ce qui reste
# exige, c'est le secret d'API : sans lui, personne ne peut rien rapporter.
- name: Exiger le secret d'API pour les rapports passifs (Vault)
ansible.builtin.assert:
that:
- serveur_icinga_api_motdepasse | length > 0
fail_msg: >-
vault_icinga_api_depot requis : sans lui, ni le depot ni les noeuds ne peuvent
rapporter l'etat de leurs sauvegardes, et personne ne les surveille.
- name: Deployer le compte d'API du depot de sauvegarde
ansible.builtin.template:
src: setops-api-users.conf.j2
dest: "{{ serveur_icinga_api_conf }}"
owner: root
group: nagios
mode: "0640"
no_log: true
notify: Redemarrer icinga2
- name: Deployer les objets de supervision des sauvegardes
ansible.builtin.template:
src: setops-sauvegardes.conf.j2
dest: "{{ serveur_icinga_setops_conf }}"
owner: root
group: nagios
mode: "0640"
notify: Redemarrer icinga2
- name: Valider la configuration Icinga 2 avant de la rendre vivante
ansible.builtin.command:
cmd: icinga2 daemon -C
changed_when: false
- name: Activer et demarrer Icinga 2 et Icinga DB
when: not ansible_check_mode
ansible.builtin.systemd:
name: "{{ item }}"
enabled: true
state: started
loop:
- "{{ serveur_icinga_service_icinga2 }}"
- "{{ serveur_icinga_service_icingadb }}"
# --- Publier l'AC vers le depot de sauvegarde ---
# Le depot rapporte l'etat des instantanes a cette API et doit VERIFIER le pair. Il lui
# faut donc cette AC — mais lui est un SERVICE et nous une APPLICATION : il se deploie
# AVANT nous, et exiger son attente inverserait le graphe des couches (refuse par P08 le
# 2026-08-12). C'est donc a NOUS de la lui porter, une fois que `icinga2 api setup` l'a
# creee. Sens correct : l'application rejoint le service, jamais l'inverse.
- name: Publier l'AC d'Icinga vers le depot de sauvegarde
when: groups['serveur_backup'] | default([]) | length > 0
ansible.builtin.slurp:
src: "{{ serveur_icinga_ca }}"
register: serveur_icinga_ca_contenu
- name: Deposer l'AC sur le depot de sauvegarde
when: groups['serveur_backup'] | default([]) | length > 0
ansible.builtin.copy:
content: "{{ serveur_icinga_ca_contenu.content | b64decode }}"
dest: "{{ serveur_icinga_ca_destination_depot }}"
owner: root
group: root
mode: "0644"
delegate_to: "{{ groups['serveur_backup'] | first }}"
# --- A QUI PARLER -------------------------------------------------------------
- name: Déclarer le destinataire des alertes
ansible.builtin.template:
src: setops-users.conf.j2
dest: /etc/icinga2/conf.d/setops-users.conf
owner: root
group: nagios
mode: "0640"
when: serveur_icinga_destinataire | length > 0
notify: Redemarrer icinga2
# DIRE CE QU'ON NE FAIT PAS. Sans destinataire, Icinga notifie `root@localhost` — une
# adresse que personne ne lit. Le silence alerterait alors dans le vide.
- name: Dire que personne ne recevra les alertes
ansible.builtin.debug:
msg: >-
`serveur_icinga_destinataire` n'est pas renseigne : les notifications iront a
`root@localhost`, que personne ne lit. La supervision VERRA les defauts sans
pouvoir les dire. Declarer l'adresse au plan.
when: serveur_icinga_destinataire | length == 0