Commit graph

18 commits

Author SHA1 Message Date
018d55ec6c supervision : le site rapporte aussi — et deux corrections pour que ca MARCHE
7 machines du site deployees, 0 echec au playbook — et CINQ rapports sur
sept en TimeoutError. Un playbook vert ne prouve pas qu une chose
fonctionne ; 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
la source — et les paquets mouraient ENTRE les deux. La frontiere filtre
l inter-zones du site et ne resout que les roles que les machines PORTENT
AU PLAN ; une integration universelle n y figure pas, elle est derivee.
pair: client_sante produisait donc une regle est-ouest correcte et AUCUNE
regle a la frontiere. Le pair devient serveur_debian — le vocabulaire du
depot pour « tout noeud », que le generateur traite deja comme tel, et
exact au sens strict. Six regles creees, zero retiree, une par patte de
zone.

2. LE RAPPORTEUR S ACCUSAIT LUI-MEME. Pendant l heure de blocage,
setops-sante.service a echoue ; une fois debloque, cinq machines ont
rapporte CRITIQUE en citant leur propre rapporteur, et systemd garde l
etat failed jusqu a un reset-failed. Sa propre unite est desormais exclue
du compte — non par complaisance : 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.

ETAT FINAL : 7/7 au site, 14/14 au tenant, tous OK. Controle negatif
rejoue sur les deux flottes.

make prouver : CONFORME, 63 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 20:48:36 -04:00
6d23121dc2 supervision : systemctl --failed entre dans Icinga (role client_sante)
CE QU IL FERME. openipmi.service echouait a chaque demarrage sur les
quatorze machines depuis le 2026-09-02, et systemctl --failed rendait ZERO
partout : non parce qu elles allaient bien, mais parce qu aucune n avait
redemarre depuis. Il a fallu qu un humain redemarre une machine pour que
le defaut existe aux yeux de quelqu un. Un controle qui ne peut echouer
qu au demarrage ne mesure rien tant que rien ne demarre.

PASSIF, ET A DUREE DE VIE. Un controle actif ne voit pas la machine MUETTE.
Ici c est le noeud qui parle, et le ttl de son envoi fait la fraicheur :
sans nouvelle, Icinga perime le service tout seul. Le silence alerte autant
que l echec. Le minuteur declenche AU DEMARRAGE autant que toutes les 15
min : les echecs de cette famille naissent au boot.

CRITIQUE DES LA PREMIERE UNITE, jamais un seuil — une unite en echec est
soit un vrai probleme soit du bruit a retirer, et un seuil ferait vivre le
bruit. Les tolerances se nomment une par une, vide par defaut.

CONTROLE NEGATIF. Unite factice sur obs-01, etat relu dans IcingaDB :
CRITICAL, et le verdict NOMME l unite. Les treize autres OK. Apres
nettoyage : 14/14 OK.

UN CONFLIT EVITE. setops-sauvegardes.conf definissait les object Host ; un
second fichier de controle aurait redefini les memes, et Icinga refuse un
objet en double — la configuration entiere aurait ete rejetee, donc AUCUNE
supervision, en voulant en ajouter. Les hotes vivent maintenant dans
setops-hotes.conf, definis une fois.

TROIS OBSTACLES. ${#tableau[@]} contient {# que Jinja lit comme un debut de
commentaire (remede : comment_start_string en tete du gabarit). Ma premiere
sonde a traduit un 403 « Missing permission: objects/query/service » en
« 0 service » — encore un echec qui ecrasait permission ; l etat se lit
dans IcingaDB. Et un echec apt transitoire sur mon-01, local et disparu au
second essai : mesure avant conclusion.

NON FAIT : le SITE n a pas recu client_sante.

make prouver : CONFORME, 63 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 20:32:08 -04:00
42becd0c02 paquets tiers : passer par le cache du controleur, plus par Internet
Some checks are pending
verifier / verifier (push) Waiting to run
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
6653f49f2e sauvegarde : la verification suit la cle, pas le depot
Some checks are pending
verifier / verifier (push) Waiting to run
serveur_backup verifiait pour tout le monde — juste tant que le depot vivait
dans l ecosysteme. Depuis qu ils deposent chez leur hebergeur, le site heberge
des octets chiffres COTE CLIENT : il ne peut ni les lire ni dire s ils valent
quelque chose. La verification revient donc au seul qui detient la cle, le noeud.

client_backup verifie SON depot distant — pas le fait d avoir lance sa
sauvegarde. Une unite verte sur un depot vide est ce qui a menti un mois.

serveur_icinga n exige plus un hote serveur_backup et se branche sur deux
modeles : depot local (services sur son hote, nommes sauvegarde: <noeud>) ou
pas de depot (services sur chaque noeud, nommes sauvegarde).

Le 404 qui n etait pas une absence : les noeuds recevaient  No objects found
alors que icinga2 object list montrait le service charge. Le filtre du compte
d API ne portait que la premiere forme de nom — c est la PERMISSION qui
refusait, avec les mots d une absence.

Aussi : ingress 5665 depuis client_backup, le pair ne nommait que
serveur_backup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-02 18:53:44 -04:00
cccb4e5b43 supervision : declarer a qui elle parle
Some checks are pending
verifier / verifier (push) Waiting to run
Icinga livre son exemple avec root@localhost — une adresse que personne ne lit.
Une supervision qui voit tout et n en parle a personne a le meme effet qu aucune
supervision, en plus couteux : elle rassure.

serveur_icinga_destinataire cree un utilisateur dans le groupe auquel les
notifications sont deja assignees (Icinga refuse deux objets de meme nom, on ne
peut pas redefinir l exemple ; on en ajoute un autre, l exemple reste muet).

Vide, aucun destinataire n est pose ET LE DEPLOIEMENT LE DIT — plutot que de
laisser croire qu une alerte partira.

Eprouve : message expedie par le relais du site, status=sent (250 2.0.0 Ok),
livre directement a mx.chezlepro.ca sans intermediaire ni dependance envers un
locataire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-02 17:48:19 -04:00
671fa1fc60 reconstruction d'un trait : 43 groupes, 0 echec, 37 minutes
Chezlepro rase puis reconstruit SANS UNE SEULE INTERVENTION. Les sept correctifs
de la nuit tiennent sur une flotte entierement neuve. Sept devis CONFORME,
prouver 36/36, make test 0, neuf sauvegardes reussies et cinq sans objet.

LA BATAILLE CONTRE NodeName N'AVAIT QU'UNE CAUSE. icinga2 api setup ecrit
NodeName d'apres `hostname -f`. Tant que /etc/hosts placait le nom court en
premier, hostname -f mentait et le certificat devenait inverifiable. Depuis que
le FQDN est en tete, Icinga s'emet spontanement un certificat CN et SAN = FQDN.
Il n'y avait rien a forcer : il suffisait que la machine sache comment elle
s'appelle.

Le contournement par le nom court est RETIRE — il etait devenu faux des que la
cause reelle a ete corrigee.

Ce que ca enseigne : trois heures passees a corriger un symptome visible (le nom
du certificat) alors que la cause vivait deux couches plus bas et affectait toute
la flotte. Le signe qui aurait du alerter : CHAQUE correction etait effacee au
passage suivant. Un correctif qu'on doit reposer sans cesse ne corrige pas.

Dette notee : le clone de mon-01 a depasse proxmox_clone_timeout (600 s) pendant
la generation de son ISO cloud-init. Quatre clones complets simultanes saturent
le stockage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 08:49:12 -04:00
f8a84b78d5 reconstruction from-zero : sept defauts, tous invisibles sur une flotte debout
Chezlepro reconstruit depuis zero en 10.17.x.x. Sept defauts sont tombes, et
AUCUN n'etait detectable autrement — c'est tout l'argument de la reconstruction
comme preuve.

  1. aucune route vers le tenant sur le poste (posee a la main, jamais persistee)
  2. backup-01 exigeait l'AC d'Icinga — dependance non declaree
  3. ma correction inversait les couches : REFUSEE PAR P08 avant d'entrer
  4. base Forgejo a moitie initialisee (sequelle de l'arret du n°2)
  5. /etc/hosts : nom court avant le FQDN -> hostname -f faux sur les 14 machines
  6. API Icinga jamais activee (garde `creates:` d'api setup)
  7. restic refuse tout le lot si un chemin declare manque

LE CINQUIEME DEPASSAIT ICINGA. hostname -f rend le PREMIER nom : toute la flotte
se croyait appelee « mon-01 ». Visible sur le certificat d'Icinga, mais le meme
piege attendait Postfix (myhostname), les journaux, les certificats. FQDN d'abord.

CE QU'ON NE CORRIGE PAS : icinga2 api setup REECRIT NodeName d'apres le nom court
et nomme ses certificats d'apres lui. Aligne avant, il est ecrase ; aligne apres,
les certificats portent le mauvais nom. On adopte sa convention : le depot appelle
l'API par le nom court, celui que le certificat porte.

serveur_icinga_node_name derive desormais de l'INVENTAIRE, pas d'ansible_fqdn —
un fait qui depend du resolveur et rendait « mon-01 » alors que le FQDN etait bon.

Le commentaire ecrit pour avertir qu'une sequence accolade-diese casse les
gabarits Jinja contenait cette sequence, et cassait le gabarit. Neuf hotes en
echec pour un avertissement mal redige.

Sept devis CONFORME, prouver 36/36, make test 0. Neuf sauvegardes reussies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 03:36:56 -04:00
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
f1a7e43645 supervision : c'est le DEPOT qui dit ou en sont les sauvegardes
Icinga ne surveillait rien : aucun objet Host ni Service de Set-OPS, seulement
la config Debian d'origine sur localhost.

Superviser setops-sauvegarde.service aurait reproduit le defaut du jour meme :
l'unite etait VERTE sur onze noeuds pendant qu'elle n'emportait rien. Le noeud
sait qu'il a LANCE sa sauvegarde, pas qu'elle est ARRIVEE. backup-01 evalue donc
ses depots et pousse un resultat passif par noeud vers l'API Icinga.

Trois criteres, parce qu'un seul suffit a mentir : l'instantane existe, il est
recent (26 h / 50 h), il contient au moins un fichier.

Le sens du flux est delibere : le depot parle a la supervision, jamais l'inverse
— compromettre mon-01 ne donne aucun acces aux sauvegardes.

Le ttl de 6 h fait la fraicheur : si le rapporteur se tait, Icinga perime les
services tout seul. C'est le silence qui a laisse le defaut vivre un mois.

Deux erreurs corrigees par la mesure :
  - --data-urlencode refuse en Bad Request (l'API veut du JSON) ; le flux, le TLS
    et l'auth marchaient, seule la charge etait perdue.
  - le seuil « vide » en octets signalait a tort idm-01 (2363 o) : un export LDIF
    d'un annuaire a un compte pese cela. « Vide » se mesure en FICHIERS. Et le
    verdict est un AVERTISSEMENT : la machine ne distingue pas « les donnees ont
    disparu » de « il n'y en a pas encore ».

Reserve assumee : curl -k — l'API presente le cert de sa propre AC, pas step-ca.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 21:39:05 -04:00
a0dc3da4a6 get_url : plus aucun sans garde — la dependance externe tombe a zero
Arbitrage de l'exploitant : garder aussi les cles de signature. Zero get_url
sans garde dans le depot, contre neuf ce matin.

Avant : 6 serveurs tiers x 14 hotes recontactes a chaque deploiement. Apres :
zero. Un deploiement de flotte ne depend plus d'aucun serveur etranger pour ce
que la machine possede deja.

Consequence assumee et ecrite dans chaque role : une rotation de cle amont
n'est plus recuperee seule. Elle ne passe pas inapercue pour autant — apt
refuse le depot, bruyamment — et le remede tient en une ligne. C'est un defaut
SONORE, pas silencieux ; toute la journee a consiste a transformer les seconds
en premiers.

Verifie sur backup-01 : changed=0, trois taches sautees. Reste a eprouver sur
un hote neuf, ou la garde doit laisser passer le telechargement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 14:05:25 -04:00
22ef279464 authentification : chaque rôle déclare sa position, gardé par P29
Une règle qu'aucune garde ne vérifie finit par ne plus être vraie — c'est ce qui
était arrivé aux 28 lignes d'intégration recopiées. Chaque rôle serveur_* porte
un meta/authentification.yml, confronté à son code par P29.

web-sso 5, socle-identite 2 (keycloak/openldap : ils SONT la chaîne d'identité),
ldap-direct 2, interne-sans-auth 2, sans-auth-humaine 12.

La preuve refuse l'oubli ET le mensonge. Éprouvée par sabotage sur sept cas :
déclaration supprimée, portée inventée, secours retiré, posture de formulaire
retirée, raison retirée, ldap-direct mensonger, réglage retiré des defaults.

Les deux derniers passaient dans la première version :

- le mensonge passait à cause d'un commentaire. Je cherchais le mot « ldap » dans
  le rôle, et serveur_grafana/defaults/main.yml contient « désactiver quelqu'un
  dans LDAP » : de la prose validait une déclaration fausse. La preuve exige
  maintenant un indice nommé — variable <rôle>_oidc / <rôle>_ldap, ou URI ldap://
- le réglage retiré passait parce que le gabarit citait encore la variable alors
  que plus rien ne lui donnait de valeur. La preuve lit defaults/main.yml en YAML
  et exige que la clé y soit définie, pas mentionnée.

Elle a aussi forcé une valeur : oauth2-proxy était déclaré « formulaire local
fermé » alors qu'il n'a aucun compte local. D'où formulaire_local: aucun, qui
distingue « il n'y en a jamais eu » de « il y en a un, il est fermé ».

Correction d'une note de la veille : Prometheus et Loki ne sont PAS exposés
publiquement (aucun expose au plan). Seuls six groupes le sont. Le risque est
intra-tenant, pas frontalier. Les deux lacunes sont comptées à chaque exécution,
pas masquées.

AFF-111, D-42. 29 preuves OK, ansible-lint (production) sur 375 fichiers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 17:05:43 -04:00
f05f505b88 Reconstruction propre : orchestrateur ordonné, registre des flux + pare-feu
Rend l'écosystème reconstructible en une commande (create+deploy idempotent) et
ajoute la couche « accès » (nftables least-privilege) au zéro-confiance.

Orchestrateur (phase 2) :
- docs/couches-deploiement.yml : registre des couches (socle → pki → services → apps → agents)
- scripts/orchestrer.py : tri par couche + topo intra-couche (graphe) → playbooks/site.yml ordonné
- Makefile : site / deployer-tout / flotte-creer / reconstruire / myDay (+ gardes CONFIRMER)
- docs/dependances-groupes.yml : graphe complété (keycloak→openldap, dovecot, postfix, icingaweb2, nextcloud)

Audit codé-en-dur (phase 1b) : labels/slug OIDC dérivés de l'intrant `organisation`
(serveur_forgejo/grafana/nextcloud) — le moteur ne porte plus de nom de tenant.

Registre des flux réseau (phase 0) :
- meta/flux.yml pour tous les rôles (29 rôles, 63 flux ; schéma + matrice validés)
- scripts/resoudre_flux.py : matrice d'audit (docs/registre-flux.md) + rulesets nftables résolus par hôte
- roles/nftables_baseline : déploie le ruleset résolu (moindre-privilège) quand activé, sinon repli

Correctifs : détection du coffre Vault (chemin production → inventaire réellement résolu).
Outillage : make wiki-publier (publication du wiki pédagogique dans Forgejo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 03:08:09 -04:00
5108a6c04d Références par FQDN partout : fin des IP codées en dur
Décision d'archi : FQDN pour toute référence inter-services (non ambigu en
fédération — data-sql-01 existe chez plusieurs tenants — + nom canonique TLS).

- resoudre_base : db_host renvoie le FQDN (hote.domaine_interne) → propagé à
  keycloak/forgejo/icinga (ils en dérivent tous). Résolu par le plancher.
- client_journal : loki_url dérivé du groupe serveur_loki en FQDN (fin du
  10.0.14.11 périmé).
- nettoyage des defaults db_host IP morts (10.0.13.11, écrasés par resoudre_base).

Aucune IP littérale ne subsiste dans les defaults des rôles. verify-full OK
(SAN FQDN). S'applique au prochain déploiement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 00:40:57 -04:00
d26651a432 Zéro-confiance : IcingaDB→PG en TLS vérifié (cert step-ca)
config.yml database : tls: true + ca: root_ca step-ca. root_ca déjà 0644
(fix client_pki). Prouvé sur sup-01 : icingadb actif, log 'pgsql+tls://',
aucune erreur TLS. 3e et dernier client BD sur verify-full.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 20:32:05 -04:00
889e9af97a DRY : rôle utilitaire partagé resoudre_base (résolution BD depuis le registre)
Le bloc copié-collé dans keycloak/forgejo/icinga (charger le registre,
filtrer par consommateur, déréférencer le secret via lookup('vars'),
résoudre hôte/port) extrait dans roles/resoudre_base (facts génériques,
no_log). Les 3 rôles l'incluent + adoptent les facts. Le secret ne quitte
toujours pas le rôle.

Fait « sur la preuve » : re-déploiement keycloak + forgejo failed=0,
idempotent, testmail token Keycloak HTTP 200. Ferme le reste de la Phase 2
des bindings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:57:06 -04:00
f82630de6c Rendre le dry-run (--check) fiable sur les rôles applicatifs
« Vérifier » échouait faussement sur un hôte frais : les tâches
« démarrer service » et les handlers restart/reload/validate touchent
un paquet que --check n'installe pas vraiment → service/fichier absent
→ faux fatal, qui bloquait le déploiement (le dry-run doit passer pour
débloquer « Déployer »).

Ajout de « when: not ansible_check_mode » sur ces tâches + handlers des
13 rôles serveur_* (29 gardes). Sautées en dry-run, inchangées en réel.
Validé : powerdns dry-run failed=0 ; ansible-lint 0 échec ; 19 playbooks
syntax-OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:01:53 -04:00
5d30a3a608 Dimensionner les ressources VM depuis les logiciels hébergés
Les cœurs/RAM/disque d'une VM sont estimés depuis l'empreinte des rôles
hébergés (roles/<rôle>/meta/empreinte.yml) sommée au socle SE, au lieu
d'hériter des specs du golden template. Le générateur écrit
proxmox_coeurs/memoire/disque_taille ; le clonage les passe à Proxmox
(omit si absent → aucune régression). Override par hôte dans le plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 10:07:04 -04:00
Alliance Boreale
3dd3f43ad8 Set-OPS — moteur d'ecosystemes numeriques souverains (Alliance Boreale) 2026-06-24 20:17:46 -04:00