diff --git a/CHANGELOG.md b/CHANGELOG.md index e3fbfa9..fd0edb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,9 +79,42 @@ portee identique : ce compte ne peut deja que poser un resultat passif, sur des NOMMES. Le filtre passe de `sauvegarde: *` / `sauvegarde` a ces deux-la plus `sante`. Aucun pouvoir nouveau. -### Non fait +### Le SITE : fait, et il a fallu deux corrections pour que ca MARCHE -Le SITE n'a pas recu `client_sante`. Sept machines, meme role, meme raison. +7 machines, 0 echec au deploiement — et **cinq rapports sur sept en `TimeoutError`**. + +*Un playbook vert ne prouve pas qu'une chose fonctionne.* `make site-appliquer +GROUPE=client_sante` rendait 7/7, 0 echec, sur un flux qui ne passait pas. Seul l'essai +de bout en bout l'a dit. + +**1. Le pair de la frontiere.** Le role client declarait son `egress` 5665, la politique +de sortie etait `accept`, la regle d'entree de l'hote autorisait bien la source — et les +paquets mouraient ENTRE les deux. La frontiere filtre le trafic inter-zones du site et ne +connait que ce que le registre lui dit ; or elle ne resout que les roles que les machines +PORTENT AU PLAN. Une integration universelle n'y figure pas : elle est derivee, pas +declaree. `pair: client_sante` produisait donc une regle est-ouest correcte et AUCUNE +regle a la frontiere. + +Le pair est desormais `serveur_debian` — le vocabulaire du depot pour « tout noeud », que +le generateur de frontiere traite deja comme tel, et qui est exact au sens strict : tout +noeud rapporte sa sante. Six regles creees, zero retiree, une par patte de zone. Le meme +piege explique pourquoi le flux `client_backup` juste au-dessus ne suffisait pas seul : +c'est `serveur_backup`, role REEL, qui ouvrait la porte pour le depot. + +**2. Le rapporteur s'accusait lui-meme.** Pendant l'heure ou le pare-feu bloquait, +`setops-sante.service` a echoue — et une fois debloque, cinq machines ont rapporte +CRITIQUE en citant... leur propre rapporteur. Le blocage corrige, l'accusation restait : +systemd garde l'etat `failed` jusqu'a un `reset-failed`. Un rapporteur qui trebuche une +fois s'accuserait indefiniment. + +Sa propre unite est donc exclue du compte, et ce n'est pas se menager : **sa sante est +deja mesuree, et mieux, par la FRAICHEUR de ses envois**. S'il ne peut plus parler, le +`ttl` perime le service — ce qui se voit precisement quand il ne peut PAS ecrire, alors +que sa propre unite en echec ne se voit que quand il le peut. Se compter soi-meme, c'est +mesurer deux fois la meme chose, dont une fois mal. + +**Etat final** : **7/7 au site, 14/14 au tenant**, tous OK. Controle negatif rejoue sur +les deux flottes. ## 2026-09-09 (3) — Le redemarrage a tenu, et il a montre autre chose diff --git a/docs/audit/preuve-2026-09-09.md b/docs/audit/preuve-2026-09-09.md index 05d7e06..f37ab26 100644 --- a/docs/audit/preuve-2026-09-09.md +++ b/docs/audit/preuve-2026-09-09.md @@ -21,7 +21,7 @@ | P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. | | P07 | GUI (node --check) | AFF-033 | ✅ OK | JS du GUI : syntaxe valide (node --check), 1 nom(s) surveille(s) sans reference orpheline. | | P08 | Orchestration (couches + graphe) | AFF-070 | ✅ OK | Orchestration coherente : 41 groupes classes, aucun cycle, aucune arete en arriere. | -| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 39 rôles, 100 flux, schéma + matrice OK. | +| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 39 rôles, 101 flux, schéma + matrice OK. | | P10 | Handlers <-> notify | AFF-034, AFF-035 | ✅ OK | Tout notify pointe vers un handler du meme role (49 roles). | | P11 | Syntaxe des playbooks (--syntax-check) | AFF-083 | ✅ OK | serveur_resolveur_site | | P12 | Existence des runbooks cites | AFF-010, AFF-011, AFF-012, AFF-083 | ✅ OK | 17/17 runbooks/registres cites presents. | @@ -37,7 +37,7 @@ | P22 | Plan de recette a jour (genere du wiki) | AFF-002 | ✅ OK | Plan de recette à jour (22 sections). | | P23 | Underlay sans collision avec la plage tenant | AFF-103 | ✅ OK | Underlay conforme : 13 reseau(x), aucune collision avec la plage tenant. | | P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | note : serveur_powerdns declare un port `derive` que le plan du site ne resout pas — aucune regle emise. | -| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 3 tenant(s), 50 groupe(s), 80 regle(s). | +| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 3 tenant(s), 50 groupe(s), 82 regle(s). | | P26 | Integrations universelles : aucun hote laisse de cote | AFF-108 | ✅ OK | 14 hote(s) x 6 integration(s) universelle(s) : aucune lacune, aucune recopie (0 exemption(s) derivee(s) du service rendu). | | P27 | Propriete des intrants : hebergeur et tenant separes | AFF-109 | ✅ OK | 8 cle(s) de cluster chez l'hebergeur, aucune recopiee dans les group_vars du tenant. | | P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 3 pool(s) Proxmox, 34 VM placee(s), aucun nom ni VMID en collision. | @@ -55,14 +55,14 @@ | P40 | Parente : l'ecosysteme sait de quoi il descend | — | ✅ OK | Parente coherente : 4 depot(s), tous retrouves, tous porteurs d'un remote. | | P41 | Resolution d'instance : une seule, partagee | — | ✅ OK | Resolution unique : 54 script(s) passent par `inventory_rules`, 3 exemption(s) nommee(s). | | P42 | L'edge porte les noms qu'il publie | — | ✅ OK | 4 edge(s) emettent un certificat portant les noms publies (OPS-Chezlepro-lab/principal, OPS-Chezlepro/principal, OPS-Technolibre/principal, OPS-Patient0/product | -| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 7 machine(s) du plan retrouvees, 104 regle(s) du site. | +| P43 | Frontiere : le devis voit les machines du site | — | ✅ OK | Devis de la frontiere : 7 machine(s) du plan retrouvees, 110 regle(s) du site. | | P44 | Integrations : le serveur avant ses clients | — | ✅ OK | 5 integration(s) appliquent leur serveur avant leurs clients. | | P45 | Pare-feu Proxmox : arme sur les VNet SDN, jamais ailleurs | — | ✅ OK | Le pare-feu Proxmox ne s'arme que sur un VNet SDN (4 cas evalues, dont un qui doit rendre VRAI). | | P46 | Plancher /etc/hosts : un seul role en decide | — | ✅ OK | Un seul maitre du plancher — roles/hosts_statiques/tasks/main.yml : manage_etc_hosts: false ; et le gabarit maitre est pose (roles/hosts_statiques/templates/hos | | P47 | Zones inverses : couvrir l'occupe, et rien de plus | — | ✅ OK | Les zones inverses couvrent l'occupe et rien de plus (5 cas evalues, dont un site a quatre zones et un tenant a une). | | P48 | La carte d'orientation designe ce qui existe, et compte juste | — | ✅ OK | La carte designe 89 chemin(s) qui existent, et ses 7 chiffres correspondent a la mesure. | -| P49 | Registre des flux : la matrice d'audit est a jour | — | ✅ OK | Le registre des flux reproduit exactement ce que les `meta/flux.yml` declarent (118 lignes). | -| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 169 regles `pass`), tous non consignes et tous motives. | +| P49 | Registre des flux : la matrice d'audit est a jour | — | ✅ OK | Le registre des flux reproduit exactement ce que les `meta/flux.yml` declarent (119 lignes). | +| P50 | Silences : un refus muet est declare, place en dernier, et motive | — | ✅ OK | 2 silence(s) declare(s), tous en sequence > 1 (la plus haute des 175 regles `pass`), tous non consignes et tous motives. | | P51 | Collections : toutes declarees, toutes epinglees | — | ✅ OK | 3 collection(s) et 2 bibliotheque(s) Python declarees et epinglees : ansible.posix==1.6.2, community.general==10.3.0, community.postgresql==3.10.2 | | P52 | Materialiser n'exige pas d'entrer dans le tenant | — | ✅ OK | `creer-vm` confirme par l'agent invite (API des hyperviseurs, deja utilisee pour creer), sans exiger d'entrer dans le tenant. | | P53 | L'interne refuse a voix haute, la bordure se tait | — | ✅ OK | L'interne parle, la bordure se tait — 15 ruleset(s) nftables refusent a voix haute ; pare-feu est-ouest en REJECT, source unique ; frontiere muette (actions : b | diff --git a/docs/registre-flux.md b/docs/registre-flux.md index d1a0174..709a0ef 100644 --- a/docs/registre-flux.md +++ b/docs/registre-flux.md @@ -47,6 +47,7 @@ | `serveur_icinga` | ingress | 5665 | tcp | localhost | clair | API Icinga 2 consommée en local par Icinga Web 2 co-localisé. | | `serveur_icinga` | ingress | 5665 | tcp | client_backup | tls-requis | Rapport passif de chaque detenteur d'etat sur SON depot distant : le depot du site heberge du chiffre et ne peut pas le juger. | | `serveur_icinga` | ingress | 5665 | tcp | serveur_backup | tls-requis | Le depot de sauvegarde depose ses resultats passifs (portee : process-check-result sur « sauvegarde: * »). | +| `serveur_icinga` | ingress | 5665 | tcp | serveur_debian | tls-requis | Rapport passif de sante de chaque noeud (unites systemd en echec). | | `serveur_icinga` | egress | 5432 | tcp | serveur_postgresql | tls-requis | Base relationnelle du moteur Icinga (verify-full). | | `serveur_icingaweb2` | ingress | 8080 | tcp | edge | clair | Interface web servie via l'edge (TLS terminé à l'edge ; SSO possible via oauth2-proxy). | | `serveur_icingaweb2` | egress | 636 | tcp | serveur_openldap | tls-requis | Authentification des utilisateurs sur l'annuaire (LDAPS). | @@ -115,4 +116,4 @@ - **starttls** : 6 flux - **tls** : 10 flux - **tls-cible** : 2 flux -- **tls-requis** : 34 flux +- **tls-requis** : 35 flux diff --git a/roles/client_sante/templates/setops-sante.sh.j2 b/roles/client_sante/templates/setops-sante.sh.j2 index 5b10a2b..9c86bf3 100644 --- a/roles/client_sante/templates/setops-sante.sh.j2 +++ b/roles/client_sante/templates/setops-sante.sh.j2 @@ -47,8 +47,21 @@ rapporter() { # $1=code $2=texte # `--plain` et `--no-legend` : la sortie doit etre analysable, pas jolie. Sans eux, # systemd insere une puce « ● » en tete de ligne, qui devient le premier champ. +# SA PROPRE UNITE EST EXCLUE, ET CE N'EST PAS SE MENAGER. +# +# Mesure du 2026-09-09 sur le site : le pare-feu a bloque les rapports pendant une heure, +# `setops-sante.service` a donc echoue, et cinq machines se sont mises a rapporter +# CRITIQUE en citant... leur propre rapporteur. Le blocage corrige, l'accusation restait : +# systemd garde l'etat `failed` jusqu'a un `reset-failed`. Un rapporteur qui trebuche une +# fois s'accuserait indefiniment. +# +# La sante du rapporteur est DEJA mesuree, et mieux : par la FRAICHEUR de ses envois. S'il +# ne peut plus parler, Icinga perime le service tout seul (`ttl`) — ce qui se voit +# precisement quand il ne peut PAS ecrire, alors que sa propre unite en echec ne se voit +# que quand il le peut. Se compter soi-meme, c'est mesurer deux fois la meme chose, dont +# une fois mal. mapfile -t echecs < <(systemctl list-units --state=failed --plain --no-legend 2>/dev/null \ - | awk '{print $1}') + | awk '{print $1}' | grep -vx 'setops-sante.service') {% if client_sante_unites_tolerees %} # UNITES TOLEREES, NOMMEES UNE PAR UNE. Jamais un motif large : un filtre qui cache une diff --git a/roles/serveur_icinga/meta/flux.yml b/roles/serveur_icinga/meta/flux.yml index 2f1533a..d048fda 100644 --- a/roles/serveur_icinga/meta/flux.yml +++ b/roles/serveur_icinga/meta/flux.yml @@ -30,6 +30,40 @@ flux: chiffrement: tls-requis partage: true raison: "Le depot de sauvegarde depose ses resultats passifs (portee : process-check-result sur « sauvegarde: * »)." + # LE RAPPORT DE SANTE : TOUS les noeuds, pas seulement les detenteurs d'etat. + # + # Le declarer ici n'est pas une redondance avec `client_sante/meta/flux.yml`. Les deux + # faces sont necessaires, et l'oubli s'est paye le 2026-09-09 : le role client etait + # deploye, sa face EGRESS declaree, la politique de sortie etait `accept`, la regle + # d'entree de l'hote autorisait bien la source — et cinq machines sur sept rendaient + # `TimeoutError`. Les paquets mouraient ENTRE les deux, a la frontiere, qui filtre le + # trafic inter-zones et ne connait que ce que le registre lui dit. + # + # `make site-appliquer GROUPE=client_sante` avait pourtant rendu 7/7, 0 echec : un + # deploiement REUSSI sur un flux qui ne passait pas. Seul l'essai de bout en bout l'a + # dit — un playbook vert ne prouve pas qu'une chose fonctionne. + # + # LE PAIR EST `serveur_debian`, PAS `client_sante`, ET C'EST LA LE POINT. + # + # La frontiere ne connait que les roles que les machines PORTENT AU PLAN. Une + # integration universelle n'y figure pas : elle est derivee, pas declaree. Ecrire + # `pair: client_sante` produisait donc une regle est-ouest correcte et AUCUNE regle a + # la frontiere — d'ou les cinq `TimeoutError` sur sept. Le meme piege explique pourquoi + # le flux `client_backup` juste au-dessus ne suffit pas seul : c'est `serveur_backup`, + # role REEL du site, qui ouvre la porte. + # + # `serveur_debian` est le vocabulaire du depot pour « tout noeud » — le socle que + # chaque machine porte — et le generateur de frontiere le traite deja comme tel. C'est + # exact au sens strict : tout noeud rapporte sa sante. + # + # `partage: true` : plusieurs pairs entrent par le meme port, la regle est mutualisee. + - sens: ingress + port: 5665 + protocole: tcp + pair: serveur_debian + chiffrement: tls-requis + partage: true + raison: "Rapport passif de sante de chaque noeud (unites systemd en echec)." - sens: egress port: 5432 protocole: tcp