vigie : vues métier par clientèle interne, dérivées du plan

- metier: sur chaque sonde (47) ; catalogue des vues et services dans
  serveur_icingaweb2 ; vues Mes outils / Services rendus / Exploitation
- contrôles calculés comme serveur_icinga (sauvegardes, socle, matériel,
  frontière) ; vue vide non posée ; ancien exemple supervision retiré
- CHANGELOG 71

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-10-04 02:26:11 -04:00
parent 055aed665e
commit 5340220192
43 changed files with 344 additions and 0 deletions

View file

@ -1,5 +1,47 @@
# CHANGELOG — Set-OPS
## 2026-10-04 (71) — Vues métier dans la vigie : une par clientèle interne, dérivées
**Demande de l'exploitant** : que le module Business Process d'Icinga offre des vues
d'ensemble à différentes clientèles internes. Choisi avec lui : personnel, direction,
exploitation ; au site et chez les locataires ; dérivées du plan. Catalogue validé avant
d'écrire.
**Constat** : le seul processus existant (`supervision`, écrit à la main dans les group_vars
des deux locataires) visait un hôte `icinga` et des contrôles (`load`, `procs`, `swap`, `ssh`)
qui n'existent plus. Il ne pouvait rien montrer de juste. **Retiré.**
**Fait** :
- chaque sonde déclare son service métier dans le `meta/supervision.yml` de son rôle
(`metier:`, 47 sondes, 38 rôles) ;
- `serveur_icingaweb2` porte le catalogue (`serveur_icingaweb2_bpm_vues`, `_services`) :
titres, clientèles, regroupement « fondations » et socle par machine ;
- `bpm-membres.json.j2` calcule les contrôles de chaque service avec la même dérivation que
`serveur_icinga` (hôtes du rôle et de `client_sante`, condition `seulement_si`), plus ce qui
ne vient pas des rôles : sauvegardes (les deux modèles, lus chez `client_backup`), `sante`
et `ping4` de chaque machine, `materiel` des hyperviseurs, pattes de la frontière ;
- `bpm-vue.conf.j2` écrit `setops-<vue>.conf`. Une vue sans service n'est pas posée, et
« Mes outils » n'existe que là où des personnes se connectent : pas au site.
**Trois vues** : **Mes outils** (personnel — se connecter, courriel, fichiers, édition,
sites web, sans nom de machine) ; **Services rendus** (direction — un voyant par service,
sûreté des données, « Fondations techniques ») ; **Exploitation** (tout, déplié jusqu'au
contrôle et à la machine).
**Éprouvé** : chaque contrôle nommé comparé à ce qu'Icinga surveille vraiment — site 152,
Chezlepro 183 : aucun absent, aucun service laissé hors vue. Trois défauts trouvés ainsi et
corrigés : la condition `seulement_si` passée par `| bool` (« frontiere » devenait faux,
`journaux-frontiere` disparaissait) ; les sauvegardes écrites « l'un ou l'autre » alors que
le site porte les deux modèles ; l'edge classé « sites web publics » (c'est la passerelle des
services internes : il fabriquait une vue « Mes outils » au site). Puis chaque vue évaluée par
le module (`icingacli businessprocess process check`) au site et chez les deux locataires,
sans erreur. Ce qu'elles disent aujourd'hui, et c'est juste : au site, socle en
avertissement (gandalf, matériel) ; chez les deux locataires, sûreté des données en
avertissement (sauvegarde VIDE de `web-dorsal-01`) ; chez Chezlepro, socle (correctif redis
de `edge-mta-01`).
**Validation** : `ansible-lint` (0 violation), `make verifier` conforme (83/83).
## 2026-10-04 (70) — Un tableau de synthèse, au site et chez les locataires
**Demande de l'exploitant** : la seconde moitié de « rendre les tableaux plus parlants » — un

View file

@ -19,6 +19,7 @@
# precedent : ce qui AUGMENTE est une perte en cours, ce qui stagne est une cicatrice.
sondes:
- nom: journaux
metier: socle
ttl: 5400
raison: >-
Les journaux de cette machine partent-ils vraiment vers Loki ? Alloy peut tourner,

View file

@ -17,6 +17,7 @@
# donc DECLARES sans objet, dans une liste qu'une machine de metal peut vider.
sondes:
- nom: metriques
metier: socle
# Six fois la periode du porteur (15 min) : cinq passages peuvent manquer avant
# qu'Icinga ne perime. On ne crie pas pour un hoquet, on crie pour un silence.
ttl: 5400

View file

@ -27,6 +27,7 @@
# contraire. La sonde compare donc les deux quand un service consomme le certificat.
sondes:
- nom: certificat
metier: socle
# 5400 s = une heure et demie, soit six fois la periode du porteur (15 min). Cinq
# passages peuvent manquer avant qu'Icinga ne perime : on ne crie pas pour un hoquet,
# on crie pour un silence.

View file

@ -9,12 +9,14 @@
# script, et P64 veut, a juste titre, que la declaration suive le role qui depose.
sondes:
- nom: disque
metier: socle
ttl: 5400
raison: >-
Reste-t-il de la place, et des inodes, sur chaque systeme de fichiers ? Seuls le
cache apt et les depots de sauvegarde etaient surveilles : un disque plein arretait
la base ou le courriel sans prevenir.
- nom: plancher
metier: socle
ttl: 5400
# Posee sous la condition du plancher (voir `setops-sondes.conf.j2`, 2026-09-28).
seulement_si: hosts_statiques_actif

View file

@ -2,10 +2,12 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: cache-apt
metier: paquets
ttl: 5400
raison: Le cache d'artefacts repond-il ? S'il se tait, TOUT apt de l'ecosysteme echoue — on agit dans
la minute.
- nom: cache-apt-volume
metier: paquets
ttl: 5400
raison: 'Reste-t-il de la place au cache ? Un cache plein cesse d''ecrire sans se plaindre, et l''echec
apparait chez les clients. Verdict distinct de la disponibilite : il appelle un billet, pas un reveil.'

View file

@ -21,6 +21,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: depot
metier: donnees
ttl: 5400
raison: 'Le depot accepte-t-il encore une ecriture ? Il ne juge pas le contenu — chiffre
cote client, il ne peut pas l''ouvrir. Il constate que l''endroit prend encore : en

View file

@ -27,6 +27,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: depot-locataires
metier: sauvegardes_locataires
ttl: 5400
raison: 'Les depots des locataires sont-ils toujours etanches, et reste-t-il de la
place devant eux ? Un mode qui glisse laisse un locataire lire ou effacer les

View file

@ -28,6 +28,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: cache-site-racine
metier: paquets
ttl: 5400
raison: 'Ce cache est-il toujours la RACINE de la chaine, et peut-il encore remplir ?
Un cache chaine sur lui-meme ou coupe de Debian repond parfaitement — il sert ce

View file

@ -15,6 +15,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: edition
metier: edition
ttl: 5400
raison: 'L''edition en ligne repond-elle ? `/hosting/discovery` est l''adresse que Nextcloud
interroge lui-meme pour savoir quels documents Collabora sait ouvrir. Sans elle, le

View file

@ -27,12 +27,14 @@
# correctif publie en exposition acceptee.
sondes:
- nom: correctifs
metier: socle
ttl: 5400
raison: >-
Des correctifs de securite attendent-ils d'etre appliques, et depuis quand ?
Set-OPS desarme les mises a jour automatiques et les applique au deploiement :
sans cette mesure, rien ne dit quand le geste est du.
- nom: horloge
metier: socle
ttl: 5400
raison: >-
L'heure est-elle disciplinee, et par la SOURCE DECLAREE ? Une machine peut etre

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: zones-publiques
metier: noms_publics
ttl: 5400
raison: 'Le serveur public sert-il TOUTES les zones de ses locataires ? Un secondaire qui n''a jamais
recu une zone repond REFUSED : pour Internet, ce domaine n''a plus de serveur de noms, pendant que le

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: boites
metier: courriel
ttl: 5400
raison: 'Dovecot repond-il, et sait-il encore RESOUDRE un utilisateur dans l''annuaire ? Un Dovecot
dont le lien LDAP est tombe accepte les connexions et refuse toutes les authentifications : le service

View file

@ -18,6 +18,7 @@
# laisse la meme trace qu'un audit en bonne sante pour qui ne regarde que `systemctl`.
sondes:
- nom: audit
metier: socle
ttl: 5400
# Posee par `auditd` seulement si `auditd_enabled` : Icinga ne l'attend qu'a ces
# conditions (voir `setops-sondes.conf.j2`, 2026-09-28).
@ -28,6 +29,7 @@ sondes:
prouvent pas qu'un demon collecte : le 2026-08-30, quinze machines ont eu les
deux apparences de la sante sans qu'une seule ligne soit ecrite.
- nom: connectivite
metier: socle
ttl: 180
# Attendue a la minute, et non au quart d'heure : c'est tout son interet. Voir le mode
# `minute` du porteur (`client_sante`).

View file

@ -27,6 +27,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: genome-servi
metier: forge
ttl: 5400
raison: 'Cette forge a-t-elle encore un genome a servir ? Une forge vide repond
parfaitement : son API marche, son Git est lisible, elle n''a simplement plus rien

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: forge
metier: forge
ttl: 5400
raison: La forge repond-elle a son API, et son depot Git est-il lisible ? Une forge qui sert sa page
d'accueil mais ne peut plus lire ses depots est une panne complete pour tout ce qui clone — et elle

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: tableaux
metier: supervision
ttl: 5400
raison: 'Grafana repond-il, sa base tient-elle, et ses SOURCES DE DONNEES aussi ? Un Grafana
dont la base est tombee sert encore sa page de connexion ; un Grafana dont la source Loki

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: moteur
metier: supervision
ttl: 5400
raison: 'L''etat des controles arrive-t-il encore jusqu''a la base ? On ne mesure ni le service ni
le port : on mesure la FRAICHEUR de ce que la base contient. Un moteur vert dont la synchronisation

View file

@ -118,6 +118,69 @@ serveur_icingaweb2_modules:
# les processus sont normalement édités via l'UI. Un contenu ici est géré par Ansible.
serveur_icingaweb2_bpm_processes: {}
# --- LES VUES METIER, DERIVEES (2026-10-04) --------------------------------------------
#
# Une vue d'ensemble par CLIENTELE INTERNE, construite seule : chaque sonde declare dans le
# `meta/supervision.yml` de son role le service metier auquel elle contribue (`metier:`) ;
# ce catalogue dit comment chaque service s'appelle et QUI le voit. Les vues ne retiennent
# que les services presents dans l'ecosysteme : un site sans courriel n'a pas de case
# « courriel », un locataire sans forge pas de case « forge ».
#
# Fichiers poses : `setops-<vue>.conf` dans le repertoire des processus. Le prefixe les
# distingue des processus ecrits a la main ou dans l'interface, que le role ne touche pas.
serveur_icingaweb2_bpm_vues:
personnel:
titre: "Mes outils"
# PAS DE PERSONNEL SANS COMPTES : la vue n'existe que la ou l'on se connecte. Au site,
# le seul « outil » trouve etait son relais de courriel — celui des alertes.
requiert: connexion
description: >-
Les outils du quotidien fonctionnent-ils ? Vert : tout marche. Rouge : un outil est en
panne, et la supervision le voit aussi.
direction:
titre: "Services rendus"
description: >-
Les services que l'organisation rend sont-ils rendus, et ses données sont-elles en
sûreté ? Un voyant par service, et un pour les fondations techniques.
exploitation:
titre: "Exploitation"
description: >-
Qu'est-ce qui casse, et où ? Chaque service se déplie jusqu'au contrôle Icinga et à la
machine en cause ; le socle se lit machine par machine.
# L'ORDRE EST CELUI DE L'AFFICHAGE. `fondation: true` : regroupe sous « Fondations
# techniques » dans la vue de la direction. `par_machine: true` : un sous-noeud par machine.
serveur_icingaweb2_bpm_services:
- {cle: connexion, titre: "Se connecter (compte unique)", vues: [personnel, direction, exploitation]}
- {cle: courriel, titre: "Courriel", vues: [personnel, direction, exploitation]}
- {cle: fichiers, titre: "Fichiers partagés", vues: [personnel, direction, exploitation]}
- {cle: edition, titre: "Édition en ligne", vues: [personnel, direction, exploitation]}
- {cle: web, titre: "Sites web publics", vues: [personnel, direction, exploitation]}
- {cle: noms_publics, titre: "Noms publics des locataires", vues: [direction, exploitation]}
- {cle: sauvegardes_locataires, titre: "Sauvegardes des locataires", vues: [direction, exploitation]}
- {cle: forge, titre: "Forge et génome", vues: [direction, exploitation]}
- {cle: paquets, titre: "Dépôt de paquets", vues: [direction, exploitation]}
- {cle: machines, titre: "Création des machines", vues: [direction, exploitation]}
- {cle: donnees, titre: "Sûreté des données", vues: [direction, exploitation]}
# L'EDGE N'EST PAS LE WEB PUBLIC : c'est la passerelle par laquelle on joint les services
# internes. Classe « sites web publics », il faisait apparaitre une vue « Mes outils » au
# site, qui n'a pas d'utilisateurs.
- {cle: acces, titre: "Passerelle d'accès (edge)", vues: [direction, exploitation], fondation: true}
- {cle: frontiere, titre: "Frontière (une patte par zone)", vues: [direction, exploitation], fondation: true}
- {cle: noms, titre: "Résolution des noms", vues: [direction, exploitation], fondation: true}
- {cle: confiance, titre: "Autorité de certification", vues: [direction, exploitation], fondation: true}
- {cle: base, titre: "Bases de données", vues: [direction, exploitation], fondation: true}
- {cle: supervision, titre: "Supervision", vues: [direction, exploitation], fondation: true}
- {cle: pilotage, titre: "Pilotage (console et runner)", vues: [direction, exploitation], fondation: true}
- {cle: socle, titre: "Socle des machines", vues: [direction, exploitation], fondation: true, par_machine: true}
# Les processus que le role a poses autrefois et qu'il retire (sans extension).
# `supervision` : l'exemple ecrit a la main dans les group_vars des locataires — il visait
# un hote `icinga` et des controles (`load`, `procs`, `swap`, `ssh`) qui n'existent plus.
serveur_icingaweb2_bpm_retires: [supervision]
# Le nom de l'ecosysteme en tete de chaque vue.
serveur_icingaweb2_bpm_nom: "{{ organisation | default(domaine_interne) }}"
# LES CODES QU'UNE CONSOLE SAINE PEUT RENDRE A UNE REQUETE NON AUTHENTIFIEE.
#
# 200 quand la racine se sert, 302 quand elle renvoie vers le formulaire de connexion,

View file

@ -27,6 +27,7 @@
# dans les plans (`vigie.<domaine>`).
sondes:
- nom: vigie
metier: supervision
ttl: 5400
raison: 'La vigie (Icinga Web 2) repond-elle, et lit-elle ce qu''elle doit montrer
(base du moteur, annuaire ou base des comptes, Redis) ? Si elle meurt, ou si elle

View file

@ -322,6 +322,101 @@
label: "{{ item.key }}"
when: serveur_icingaweb2_bpm_processes | length > 0
# --- LES VUES METIER, DERIVEES (2026-10-04) — voir defaults/main.yml -------------------
#
# Meme lecture que `serveur_icinga` : les `meta/supervision.yml` de tous les roles, sur le
# controleur. Les vues ne nomment ainsi que ce qu'Icinga surveille vraiment.
- name: Vues métier — relever les sondes que les rôles déclarent
ansible.builtin.find:
paths: "{{ role_path }}/.."
patterns: supervision.yml
recurse: true
depth: 3
delegate_to: localhost
become: false
register: serveur_icingaweb2_metas_supervision
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Vues métier — lire chaque déclaration
ansible.builtin.slurp:
src: "{{ item.path }}"
delegate_to: localhost
become: false
loop: "{{ serveur_icingaweb2_metas_supervision.files | default([]) }}"
loop_control:
label: "{{ item.path | dirname | dirname | basename }}"
register: serveur_icingaweb2_supervision_brute
when: "'businessprocess' in serveur_icingaweb2_modules"
# Les detenteurs d'etat appartiennent a `client_backup` : on les LIT chez lui, comme
# `serveur_icinga` — deux listes divergeraient, et la vue nommerait des sauvegardes
# qu'Icinga n'attend pas.
- name: Vues métier — lire la liste des détenteurs d'état chez client_backup
ansible.builtin.include_vars:
file: "{{ role_path }}/../client_backup/vars/main.yml"
name: serveur_icingaweb2_catalogue_sauvegarde
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Vues métier — assembler le registre des sondes et les sauvegardes attendues
ansible.builtin.set_fact:
serveur_icingaweb2_sondes: >-
{{ dict(serveur_icingaweb2_supervision_brute.results
| map(attribute='item.path') | map('dirname') | map('dirname') | map('basename')
| zip(serveur_icingaweb2_supervision_brute.results
| map(attribute='content') | map('b64decode') | map('from_yaml')
| map(attribute='sondes'))) }}
serveur_icingaweb2_bpm_hote_sauvegarde: "{{ (groups['serveur_backup'] | default([]) | first) | default('') }}"
serveur_icingaweb2_bpm_sauvegarde_attendue: >-
{{ (serveur_icingaweb2_catalogue_sauvegarde.client_backup_groupes_etat | default([])
| map('extract', groups) | select('defined') | flatten | unique | list)
| intersect(groups['client_backup'] | default([])) }}
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Vues métier — calculer les contrôles de chaque service
ansible.builtin.set_fact:
serveur_icingaweb2_bpm_membres: "{{ lookup('ansible.builtin.template', 'bpm-membres.json.j2') | from_json }}"
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Vues métier — retenir les vues qui ont au moins un service
ansible.builtin.set_fact:
serveur_icingaweb2_bpm_vues_posees: >-
{{ serveur_icingaweb2_bpm_vues | dict2items
| selectattr('key', 'in', serveur_icingaweb2_bpm_services
| selectattr('cle', 'in', serveur_icingaweb2_bpm_membres.keys() | list)
| map(attribute='vues') | flatten | unique | list)
| rejectattr('value.requiert', 'defined')
| map(attribute='key') | list
+ (serveur_icingaweb2_bpm_vues | dict2items
| selectattr('value.requiert', 'defined')
| selectattr('value.requiert', 'in', serveur_icingaweb2_bpm_membres.keys() | list)
| map(attribute='key') | list) }}
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Vues métier — poser chaque vue
ansible.builtin.template:
src: bpm-vue.conf.j2
dest: "{{ serveur_icingaweb2_config_dir }}/modules/businessprocess/processes/setops-{{ bpm_vue }}.conf"
owner: root
group: icingaweb2
mode: "0660"
loop: "{{ serveur_icingaweb2_bpm_vues_posees }}"
loop_control:
loop_var: bpm_vue
when: "'businessprocess' in serveur_icingaweb2_modules"
# UNE VUE QUI N'A PLUS DE SERVICE SE RETIRE, et l'ancien exemple avec elle. Seuls les
# fichiers que ce role a poses sont concernes : un processus cree dans l'interface garde
# son nom, et le role n'y touche jamais.
- name: Vues métier — retirer les vues vides et les processus abandonnés
ansible.builtin.file:
path: "{{ serveur_icingaweb2_config_dir }}/modules/businessprocess/processes/{{ item }}.conf"
state: absent
loop: >-
{{ (serveur_icingaweb2_bpm_vues.keys() | reject('in', serveur_icingaweb2_bpm_vues_posees | default([]))
| map('regex_replace', '^', 'setops-') | list)
+ serveur_icingaweb2_bpm_retires }}
when: "'businessprocess' in serveur_icingaweb2_modules"
- name: Déployer le vhost nginx local d'Icinga Web 2
ansible.builtin.template:
src: nginx.conf.j2

View file

@ -0,0 +1,53 @@
{#- LES CONTROLES DE CHAQUE SERVICE METIER (2026-10-04) — rendu en JSON, lu par les taches.
Meme derivation que `serveur_icinga/templates/setops-sondes.conf.j2`, a la ligne pres :
chaque role, ses hotes (`groups[role]` et `client_sante`), ses sondes, et la condition
`seulement_si` lue dans l'inventaire ou dans les defauts du role qui la definit. Une vue
ne doit nommer que des services qu'Icinga a REELLEMENT : un noeud absent s'afficherait
« manquant », et une vue qui ment est pire qu'une vue absente.
Les sauvegardes ne viennent pas des roles mais de `setops-sauvegardes.conf.j2`, et leur
nom change avec le modele : `sauvegarde: <noeud>` sur le depot local (site), `sauvegarde`
sur chaque noeud (locataire). On reprend ses deux variables, calculees dans les taches.
-#}
{%- set m = namespace(d={}) -%}
{%- for role, sondes in (serveur_icingaweb2_sondes | default({})) | dictsort -%}
{%- for hote in ((groups[role] | default([])) | intersect(groups['client_sante'] | default([]))) | sort -%}
{%- for sonde in sondes if sonde.metier is defined -%}
{%- set condition = sonde.seulement_si | default('') -%}
{%- set ns = namespace(ok=true) -%}
{%- if condition -%}
{%- set defauts = lookup('file', role_path ~ '/../' ~ (sonde.defini_par | default(role)) ~ '/defaults/main.yml') | from_yaml -%}
{#- LE MEME TEST QU'ICINGA, pas `| bool` : une valeur comme « frontiere » est vraie
pour lui (non vide) et fausse pour `bool` — la sonde existait, la vue l'omettait. -#}
{%- set ns.ok = (hostvars[hote][condition] if hostvars[hote][condition] is defined else defauts.get(condition)) and true -%}
{%- endif -%}
{%- if ns.ok -%}
{%- set _ = m.d.setdefault(sonde.metier, []).append([hote, sonde.nom]) -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{%- endfor -%}
{%- for noeud in serveur_icingaweb2_bpm_sauvegarde_attendue | sort -%}
{#- `sauvegarde` existe TOUJOURS sur le noeud ; `sauvegarde: <noeud>` S'Y AJOUTE sur le
depot quand l'ecosysteme en a un (le site) — les deux, pas l'un ou l'autre. -#}
{%- if serveur_icingaweb2_bpm_hote_sauvegarde -%}
{%- set _ = m.d.setdefault("donnees", []).append([serveur_icingaweb2_bpm_hote_sauvegarde, "sauvegarde: " ~ noeud]) -%}
{%- endif -%}
{%- set _ = m.d.setdefault("donnees", []).append([noeud, "sauvegarde"]) -%}
{%- set _ = m.d.setdefault("donnees", []).append([noeud, "restauration"]) -%}
{%- endfor -%}
{#- LE SOCLE COMPLET DE CHAQUE MACHINE : `sante` (unites en echec, `setops-sante.conf.j2`,
sur tout le socle `serveur_debian`) et `ping4` (chaque hote supervise) ne viennent pas des
roles ; au site, le `materiel` des hyperviseurs et de la frontiere (`setops_materiel_hotes`). -#}
{%- for noeud in groups['serveur_debian'] | default([]) | sort -%}
{%- set _ = m.d.setdefault("socle", []).extend([[noeud, "sante"], [noeud, "ping4"]]) -%}
{%- endfor -%}
{%- for h in setops_materiel_hotes | default([]) -%}
{%- set _ = m.d.setdefault("socle", []).extend([[h.nom, "materiel"], [h.nom, "ping4"]]) -%}
{%- endfor -%}
{#- LES PATTES DE LA FRONTIERE (site) : une par zone, que Icinga joint par `ping4`. -#}
{%- for f in serveur_icinga_fabric | default([]) -%}
{%- set _ = m.d.setdefault("frontiere", []).append([f.nom, "ping4"]) -%}
{%- endfor -%}
{{ m.d | to_json }}

View file

@ -0,0 +1,44 @@
{#- UNE VUE METIER (2026-10-04) — `bpm_vue` (cle), sur les controles calcules par
`bpm-membres.json.j2`. Syntaxe : module businessprocess 2.5 (parseur « legacy ») —
`noeud = a & b`, `display <priorite>;<noeud>;<libelle>` (priorite 0 : libelle seul, pas
a la racine). -#}
{%- set vue = serveur_icingaweb2_bpm_vues[bpm_vue] -%}
{%- set membres = serveur_icingaweb2_bpm_membres -%}
{%- set services = serveur_icingaweb2_bpm_services | selectattr("vues", "contains", bpm_vue)
| selectattr("cle", "in", membres.keys() | list) | list -%}
{%- set regrouper = bpm_vue == "direction" -%}
### Business Process Config File ###
#
# Title : {{ serveur_icingaweb2_bpm_nom }} — {{ vue.titre }}
# Description : {{ vue.description }}
# Statetype : hard
#
# GENERE par Set-OPS (role serveur_icingaweb2, vue « {{ bpm_vue }} »). Ne pas editer :
# modifier le catalogue (serveur_icingaweb2_bpm_services) ou le `metier:` des sondes.
###################################
{% set rang = namespace(v=0) -%}
{% for s in services -%}
{% set controles = membres[s.cle] -%}
{% if s.par_machine | default(false) -%}
{% for hote in controles | map("first") | unique | sort -%}
machine_{{ s.cle }}_{{ hote }} = {{ controles | selectattr("0", "equalto", hote) | map("join", ";") | join(" & ") }}
display 0;machine_{{ s.cle }}_{{ hote }};{{ hote }}
{% endfor -%}
svc_{{ s.cle }} = {% for hote in controles | map("first") | unique | sort %}machine_{{ s.cle }}_{{ hote }}{{ " & " if not loop.last }}{% endfor %}
{% else -%}
svc_{{ s.cle }} = {{ controles | map("join", ";") | join(" & ") }}
{% endif -%}
{% if regrouper and s.fondation | default(false) -%}
display 0;svc_{{ s.cle }};{{ s.titre }}
{% else -%}
{% set rang.v = rang.v + 1 -%}
display {{ rang.v }};svc_{{ s.cle }};{{ s.titre }}
{% endif %}
{% endfor -%}
{% set fondations = services | selectattr("fondation", "defined") | selectattr("fondation") | list -%}
{% if regrouper and fondations | length > 0 -%}
fondations = {{ fondations | map(attribute="cle") | map("regex_replace", "^", "svc_") | join(" & ") }}
display {{ rang.v + 1 }};fondations;Fondations techniques
{% endif -%}

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: identite
metier: connexion
ttl: 5400
raison: Le realm sert-il sa decouverte OIDC, et Keycloak ATTEINT-IL l'annuaire ? La decouverte est la
porte par laquelle tout le SSO entre ; la federation LDAP est ce qui la rend utile. Un Keycloak dont

View file

@ -2,12 +2,14 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: ingestion
metier: supervision
ttl: 5400
raison: Loki est-il PRET a ingerer ? Un Loki qui ecoute mais dont l'ingesteur n'est pas pret accepte
les connexions et perd les journaux — la panne se voit des semaines plus tard, quand on cherche
une trace qui n'a jamais ete ecrite.
- nom: journaux-frontiere
metier: supervision
ttl: 5400
# Posee seulement la ou une frontiere est ecoutee : au SITE, pas chez un locataire,
# dont la frontiere appartient a l'hebergeur. Sans cette ligne, Icinga l'attendait

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: collaboration
metier: fichiers
ttl: 5400
raison: Nextcloud est-il installe, hors maintenance et sans migration en attente ? Ces trois etats
se lisent d'un coup dans `status.php`, et chacun rend le service inutilisable sans que la page d'accueil

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: edge
metier: acces
ttl: 5400
raison: 'L''edge ecoute-t-il, et sa configuration est-elle encore valide ? Un nginx dont la configuration
est cassee continue de servir l''ANCIENNE tant qu''on ne le recharge pas : il fonctionne, et le

View file

@ -14,6 +14,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: passerelle
metier: connexion
ttl: 5400
raison: 'La passerelle d''authentification repond-elle, et mene-t-elle vraiment a la page de connexion
de l''IdP pour son client ? Elle porte l''acces aux applications sans SSO natif — la vigie, la console. Quand elle meurt, les services derriere restent

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: annuaire
metier: connexion
ttl: 5400
raison: L'annuaire repond-il, et contient-il encore ses entrees ? Un annuaire vide repond parfaitement
a toutes les requetes — et plus personne ne s'authentifie nulle part. C'est le meme mensonge qu'une

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: runner
metier: pilotage
ttl: 5400
raison: 'Le poste d''exploitation peut-il encore agir ? Deux choses : ses depots sont-ils PROPRES
et sur leur branche (une modification locale fait diverger le runner du depot que tout le monde
@ -17,6 +18,7 @@ sondes:
# authentifier ne fait echouer personne — il ouvre la fabric. La sonde exige donc un
# REFUS sur une requete anonyme : c'est la seule facon de mesurer une serrure.
- nom: console-ops
metier: pilotage
ttl: 5400
# Posee seulement si le GUI est actif (voir `setops-sondes.conf.j2`, 2026-09-28).
seulement_si: serveur_ops_gui_actif

View file

@ -28,6 +28,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: pouvoir-materialiser
metier: machines
ttl: 5400
raison: 'Le runner du site peut-il encore materialiser, et son secret est-il toujours
protege ? La carte de la fabric, la voute du site et sa cle ne font tomber aucun
@ -35,12 +36,14 @@ sondes:
voute dechiffree en transit ne fait echouer aucun deploiement : Ansible la lit tres
bien, elle expose simplement tout.'
- nom: fabric
metier: machines
ttl: 5400
raison: >-
Le pare-feu Proxmox, le SDN, la frontiere et les acces WireGuard disent-ils encore ce
que le plan dit ? Le 2026-09-28, aucune VM des locataires n'avait son pare-feu actif
et rien ne le signalait ; les plans existaient, personne ne les jouait sans raison.
- nom: genome-a-jour
metier: pilotage
ttl: 5400
raison: >-
La forge du site porte-t-elle ce que le poste a publie ? Elle fait autorite, mais un

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: voute
metier: pilotage
ttl: 5400
raison: 'La voute de l''ecosysteme est-elle presente ET CHIFFREE la ou le runner la lit ? Une voute
en clair sur un runner est la fuite la plus discrete qui soit : rien ne casse, tout continue de

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: file-courriel
metier: courriel
ttl: 5400
raison: Combien de courriels attendent dans la file ? Une file qui monte est le premier signe d'une
remise qui ne se fait plus — et c'est un signe qu'on voit AVANT que quiconque se plaigne de ne rien

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: base
metier: base
ttl: 5400
raison: 'La base repond-elle a une VRAIE requete, et lui reste-t-il des connexions ? Un PostgreSQL
a court de connexions accepte encore le port et refuse tout le monde : chaque application tombe

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: zones
metier: noms
ttl: 5400
raison: 'L''autoritatif repond-il, et sert-il encore ses zones ? Un PowerDNS qui a perdu ses zones
repond NXDOMAIN a tout : la resolution interne s''effondre pendant que le service a l''air parfaitement

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: collecte
metier: supervision
ttl: 5400
raison: 'Toutes les cibles declarees sont-elles reellement collectees ? C''est la seule sonde qui
voit le cas SILENCIEUX : un noeud qui a cesse d''etre scrape ne peut pas s''en plaindre lui-meme,

View file

@ -17,6 +17,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: cache
metier: base
ttl: 5400
raison: 'Le cache repond-il, et sert-il encore ? Un Redis borne ne tombe pas quand il
est plein — il evicte. Les sessions se perdent une a une, les gens sont deconnectes

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: resolution
metier: noms
ttl: 5400
raison: 'Le resolveur repond-il POUR LA ZONE INTERNE ET pour un nom de l''Internet ? Les deux voies
sont distinctes : la zone interne vient de l''autoritatif local, le reste de la recursion. Une seule

View file

@ -26,6 +26,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: resolution-locataires
metier: noms
ttl: 5400
raison: 'Les locataires du site sont-ils toujours admis a resoudre ici ? Un supernet
absent de la liste d''autorisation ne provoque pas un refus : Unbound laisse tomber

View file

@ -14,6 +14,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: filtrage
metier: courriel
ttl: 5400
raison: 'Le filtrage du courrier repond-il, et ANALYSE-T-IL (GTUBE rejete) ? Un filtre muet ne bloque pas le courrier, il le
laisse passer : Postfix sans verdict delivre sans filtrer ou differe, et le service de

View file

@ -2,6 +2,7 @@
# Supervision derivee du role. Voir docs/supervision-conception.md.
sondes:
- nom: autorite
metier: confiance
ttl: 5400
raison: 'L''autorite de certification repond-elle ? C''est la sonde la plus urgente de l''ecosysteme
: nos certificats vivent 24 h. Une AC muette ne casse rien aujourd''hui — elle casse TOUT demain,

View file

@ -23,6 +23,7 @@
# peremption. Le silence alerte autant que l'echec.
sondes:
- nom: apps-servies
metier: web
ttl: 5400
raison: 'Chacune des webapps declarees repond-elle encore ? Une app ne tombe presque
jamais en « failed » — elle se coince : le processus vit, systemd la dit active, le
@ -30,6 +31,7 @@ sondes:
verra jamais ca.'
# SUR LE DORSAL DEPUIS LE 2026-09-29 : c'est lui qui porte les sites ; le frontal les relaie.
- nom: sites-servis
metier: web
ttl: 5400
raison: 'Chacun des sites statiques declares se sert-il encore ? Le contenu vient
d''un depot git : une branche renommee, un sous-dossier deplace ou un clone vide

View file

@ -7,6 +7,7 @@
# `sites-servis` a suivi les sites sur le dorsal le 2026-09-29.
sondes:
- nom: frontal
metier: web
ttl: 5400
raison: 'Le reverse proxy public tient-il, son WAF (ModSecurity + OWASP CRS) est-il
vraiment dans le chemin, et chaque exposition publique repond-elle a travers lui ?