D-87 : ce que l hebergeur n a pas le droit de VOIR

Question posee : quels roles ne pas embarquer dans le site ? La table de
mutualisation existait et repondait presque — mais une de ses lignes
CONTREDISAIT ce qui tourne.

Elle disait « observabilite | oui | l hebergeur surveille ses locataires ».
Or chaque ecosysteme a son propre Icinga, et celui du site ne voit que ses
sept machines. L implementation avait raison, la doctrine avait tort.

Et cette case autorisait ce que la ligne du dessous interdit. LES JOURNAUX
CONTIENNENT DU CONTENU — un mot de passe dans un message d erreur, une
donnee metier dans une trace, qui a fait quoi et quand. Un hebergeur qui
ingere les journaux de son locataire en sait PLUS que s il detenait son
annuaire : l annuaire dit qui existe, les journaux disent ce qu ils font.

Decoupee en trois : disponibilite oui (une VM tombee est un fait de la
fabric), metriques oui avec reserve (elles disent quand et combien, ce qui
suffit a lire l activite d une organisation), journaux NON.

ET LA LIGNE PKI EST TRANCHEE : NON. Une AC intermediaire signee par l hote
lui donnerait le pouvoir d emettre des certificats valides pour les noms
du locataire — donc de se presenter comme n importe lequel de ses
services, devant les propres machines du locataire, qui les accepteraient
puisque c est ce que la chaine de confiance leur demande. Meme pouvoir que
l annuaire, sous une forme moins visible : aucune trace cote locataire.
Une PKI par ecosysteme, jamais derivee de l hote.

LE REVERS, MESURE ET ASSUME : le site n a ni client_journal ni
client_metrique, aucun loki ni prometheus. A refuser de voir ceux des
locataires, il s est prive des siens. Le remede n est pas d assouplir la
regle mais de lui donner sa propre pile.

Verifie par ailleurs : rien d intime n est au site aujourd hui. La
frontiere etait tenue en pratique avant d etre ecrite au net.

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
This commit is contained in:
Daniel Allaire 2026-09-10 04:05:28 -04:00
parent 6e46ace4de
commit 5880b22d5a
4 changed files with 118 additions and 5 deletions

View file

@ -1,5 +1,63 @@
# CHANGELOG — Set-OPS
## 2026-09-10 (4) — Ce que l'hebergeur n'a pas le droit de VOIR (D-87)
Question posee : *« quels roles ne dois-je pas embarquer dans le site ? »*
La table de mutualisation de `filiation-emancipation.md` existait deja et repondait presque.
Mais mise a l'epreuve, **une de ses lignes contredisait ce qui tourne**.
### La ligne qui se contredisait
| observabilite | oui | l'hebergeur surveille ses locataires |
Or chaque ecosysteme a son propre Icinga, et celui du site ne voit que ses **sept**
machines (mesure). L'implementation avait raison, la doctrine avait tort.
Et surtout : cette case autorisait ce que la ligne du dessous interdit. **Les journaux
contiennent du CONTENU** — un mot de passe dans un message d'erreur, une donnee metier dans
une trace, qui a fait quoi et quand. Un hebergeur qui ingere les journaux de son locataire
en sait **plus** que s'il detenait son annuaire : *l'annuaire dit qui existe, les journaux
disent ce qu'ils font.*
Decoupee en trois :
disponibilite (est-ce debout ?) oui une VM tombee est un fait de la fabric
metriques (charge, disque) oui, reserve disent quand et combien, pas quoi
journaux NON contiennent le contenu
### Et la ligne PKI, « a trancher », est tranchee : non
Elle notait qu'*une AC intermediaire signee par l'hote est possible*. Elle l'est
techniquement — et c'est precisement ce qu'il ne faut pas faire.
Une intermediaire signee par l'hote lui donne le pouvoir d'emettre des certificats
**valides pour les noms du locataire**. Il peut alors se presenter comme n'importe lequel
de ses services, devant les propres machines du locataire — qui les accepteront, puisque
c'est exactement ce que la chaine de confiance leur demande de faire.
Meme pouvoir que l'annuaire, sous une forme **moins visible** : rien dans la configuration
du locataire, aucune trace de son cote, et la verification passe.
**Une PKI par ecosysteme, jamais derivee de l'hote.** C'est deja ce qui tourne ; la ligne
cesse de laisser la porte entrouverte.
### Le revers, mesure et assume
Le site ne porte **ni `client_journal` ni `client_metrique`**, et aucun `loki` ni
`prometheus`. Ses sept machines n'expedient rien nulle part : **l'hebergeur ne peut pas
lire ses propres journaux**.
C'est la consequence directe de la frontiere — a refuser de voir ceux des locataires, il
s'est prive des siens. Le remede n'est pas d'assouplir la regle, c'est de lui donner **sa
propre pile**, sans aucun lien avec celle d'un tenant.
### Ce que la mesure a confirme par ailleurs
Rien d'intime n'est au site aujourd'hui. `openldap`, `keycloak`, `oauth2_proxy`, `loki`,
`nextcloud`, `collabora`, `dovecot`, `rspamd`, `web_frontal`, `web_dorsal` : tous
**tenant seulement**. La frontiere etait tenue en pratique avant d'etre ecrite au net.
## 2026-09-10 (3) — Les cinq sondes qui manquaient le plus
**20 sondes sur 19 roles. 23 services distincts, 70 instances, 67 au vert.**

View file

@ -28,7 +28,7 @@ README de rôles). Cette page comble ces deux trous.
| documents | 40 | `docs/*.md` |
| pièces d'audit | 41 | `docs/audit/*` |
| unités de wiki | 27 | `wiki/*.md` |
| décisions en vigueur | 83 | lignes `\| **D-nn** \|` de `decisions-architecture.md` |
| décisions en vigueur | 84 | lignes `\| **D-nn** \|` de `decisions-architecture.md` |
| décisions renversées | 3 | lignes `\| **D-nn** —` du même document |
## 1. À lire d'abord (dans l'ordre)

View file

@ -60,6 +60,7 @@ sont les seules vérifiables.
| **D-84** | **Le plan de contrôle reste gelé — c'est la CARTE DES SEUILS qui était fausse** | La question « et si on retirait le gel ? » a mis à l'épreuve les cinq seuils de `positionnement.md`, et deux ne tenaient pas. **RBAC** : couvert depuis que trois classes d'acteurs aux pouvoirs disjoints existent — poste, runner de site, runners de tenant — séparés **cryptographiquement** (une voûte, une clé, 2026-08-28) et non par une table de permissions qu'une faille applicative contournerait ; adopter AWX pour ce besoin serait **régresser**. **IPAM** : sans objet par construction — rien ne s'alloue, tout dérive du seed, et P20/P21/P23/P28/P33 tiennent déjà ce qu'un IPAM vérifierait *a posteriori*. Les deux lignes sont retirées du tableau : les garder aurait fait adopter un outil pour un besoin déjà rempli. **Et un seuil manquait** — l'**émancipation** : le GUI est mono-utilisateur (`127.0.0.1` + jeton), or la trajectoire mène à plusieurs humains aux portées disjointes, sur des machines qui ne sont pas les nôtres. Ce seuil n'appelle pas AWX, il appelle une décision non prise. *Un seuil qu'on ne nomme pas est un seuil qu'on franchit sans le voir.* Corollaire consigné : le gel porte sur les **fonctions**, jamais sur les **vues** — montrer à l'écran ce que le moteur sait déjà ne franchit aucun seuil | `positionnement.md` §3, §4, §5 | — |
| **D-85** | **cloud-init naît avec la VM et ne lui survit pas** | cloud-init n'est pas un logiciel d'installation : c'est une **source de vérité externe**, qui se réveille à *chaque* démarrage et relit le lecteur attaché par l'hyperviseur — lequel peut redéfinir comptes, clés SSH autorisées, mots de passe et réseau. Sur une machine que le plan possède, c'est un **second maître** : le plan ne le décrit pas, `make valider` ne le mesure pas, et il parle en premier. Sa tâche est pourtant finie à la première seconde — c'est parce qu'il a **réussi** à poser l'adresse et les clés qu'Ansible a pu entrer. **Trois moitiés, qui se défont séparément** : le **gabarit** le garde (sans lui un clone ne naît pas — P56) ; le **socle** ne l'installe plus (le garder produisait un va-et-vient à chaque déploiement : le socle installe, le durcissement retire, deux `changed` par passage) ; le **durcissement** le retire (`cloud_init_retrait`, en dernier). **Ce qui rend le retrait sûr est mesuré, pas supposé** (2026-09-09, `obs-01`) : `/etc/network/interfaces.d/50-cloud-init` n'appartient à aucun paquet — `dpkg -S` ne le trouve pas — et le `postrm` ne le nomme jamais, même en `purge`. L'adresse survit. Le rôle le **vérifie** malgré tout, avant et après : une VM qui perd ce fichier ne se plaint pas, elle repart sans adresse et plus personne ne peut entrer pour le constater. **⚠ CE QUE CETTE DÉCISION NE FERME PAS — et il faut le dire, sinon elle se lit comme une émancipation qu'elle n'est pas.** Retirer cloud-init **n'ôte aucun pouvoir à l'hébergeur**. `qemu-guest-agent` est au gabarit (P56 : il doit y être — c'est par lui que `creer-vm` confirme la matérialisation sans entrer chez le tenant), et l'API Proxmox expose sur son dos, sur toute VM vivante de la flotte, un pouvoir **strictement plus grand** que le lecteur cloud-init : `exec`, `file-write`, `file-read`, `set-user-password`, `shutdown` (relevé le 2026-09-09 sur `edge-mta-01`, jeton d'API du site). Ce que D-85 ferme est donc **précis et étroit** : (a) une réapplication **automatique, à chaque démarrage**, depuis un support que le plan ne possède pas et qu'aucune preuve ne lit ; (b) le code de cloud-init lui-même — un interpréteur Python complet, exécuté en root au démarrage, et ses ~29 dépendances. Elle ne ferme **pas** la mainmise de l'hyperviseur sur ses invités : celle-là est une propriété de la virtualisation, pas de cloud-init, et elle appelle sa propre décision — non prise. **Le seuil où le remplacer deviendrait juste** : le jour où une première seconde ne peut plus être amorcée par Proxmox (autre hyperviseur, métal nu, hébergeur sans API), le chemin par l'agent invite cesse d'être une réimplémentation d'un standard — que `positionnement.md` interdit — et devient **le chemin portable**. Tant que ce seuil n'est pas atteint, écrire soi-même l'amorçage serait échanger un standard éprouvé contre du code maison au moment le plus fragile, dont le mode de panne est le pire : une VM injoignable | `roles/cloud_init_retrait/`, `serveur_durci.yml`, `positionnement.md` | **P63** |
| **D-86** | **La supervision se déploie juste après la PKI, pas à la fin** | L'observabilité (`prometheus`, `loki`, `grafana`) et le **moteur** de supervision (`icinga`) passent en couche 4, immédiatement après `client_pki` ; les agents qui les nourrissent (`client_metrique`, `client_journal`, `client_sante`) en couche 5. **Le raisonnement** : ce qui se déploie ensuite l'est *sous l'œil* de la supervision — une unité qui casse se voit à la minute, pas à la fin. Une **reconstruction depuis zéro** est précisément le moment où l'on a le plus besoin de voir, et c'était le seul moment où l'on ne voyait rien. **Déplacer les serveurs sans les agents n'aurait rien changé** : ce sont les agents qui rapportent, et ils étaient en dernière couche. **Ce que ça a coûté en dépendances** : `serveur_postgresql` monte aussi (il n'exige rien lui-même, et `icinga` l'exige). **Ce qui reste tard, à dessein** : `icingaweb2` et `oauth2_proxy` réclament LDAP et Keycloak — c'est la CONSOLE, pas la mesure. L'interface humaine peut attendre. **Limite dite franchement** : les *notifications* dépendent de `client_smtp`, encore en dernière couche — pendant une reconstruction, l'état est mesuré et consultable, mais rien ne part par courriel avant la fin. **CE QUI REND CE DÉPLACEMENT POSSIBLE**, et qui n'est pas un détail : le DNS (`powerdns`, `resolveur`) reste en couche 6, donc *après* la supervision. Or `icinga` joint sa base par un **nom** (`data-sql-01.chezlepro.internal`), et `client_sante` pousse vers un **nom**. Ça tient parce que le **plancher `/etc/hosts`**, posé dès la couche 1 par `hosts_statiques`, porte déjà les 34 entrées de l'écosystème — vérifié. C'est exactement ce pour quoi il existe : *« il ne s'installe pas, il rend installable »*. Sans lui, cette décision serait impossible. **P08** valide l'ordre : aucune arête en arrière | `docs/couches-deploiement.yml`, `catalogue-services.md` §Ordre | **P08** |
| **D-87** | **Ce que l'hébergeur n'a pas le droit de VOIR** — l'observabilité découpée, la PKI tranchée | La question *« quels rôles ne dois-je pas embarquer dans le site ? »* a mis à l'épreuve la table de mutualisation de `filiation-emancipation.md`, et **une ligne contredisait ce qui tourne**. Elle disait « observabilité \| oui \| l'hébergeur surveille ses locataires » — or chaque écosystème a son propre Icinga, et celui du site ne voit que ses sept machines (mesuré). Surtout, elle autorisait en une case ce que la ligne du dessous interdit : **les journaux contiennent du contenu** — un mot de passe dans un message d'erreur, une donnée métier dans une trace. Un hébergeur qui ingère les journaux de son locataire en sait **plus** que s'il détenait son annuaire ; l'annuaire dit qui existe, les journaux disent ce qu'ils font. **Découpée en trois** : *disponibilité* oui (une VM tombée est un fait de la fabric), *métriques* oui avec réserve (elles disent quand et combien, ce qui suffit à lire l'activité d'une organisation), *journaux* **non**. **Et la ligne PKI, « à trancher », est tranchée : non.** Une AC intermédiaire signée par l'hôte lui donnerait le pouvoir d'émettre des certificats valides pour les noms du locataire, donc de se présenter comme n'importe lequel de ses services — devant les propres machines du locataire, qui les accepteraient, puisque c'est ce que la chaîne de confiance leur demande. Même pouvoir que l'annuaire, sous une forme **moins visible** : aucune trace côté locataire. Une PKI par écosystème, jamais dérivée de l'hôte. **Le revers, mesuré et assumé** : le site n'a NI `client_journal` NI `client_metrique`, aucun `loki` ni `prometheus` — à refuser de voir ceux des locataires, il s'est privé des siens. Le remède n'est pas d'assouplir la règle, c'est de lui donner sa propre pile | `filiation-emancipation.md` §mutualisable | — |
| **D-81** | **La forge du SITE fait autorité pour le génome.** Toute autre copie — y compris celle d'où le moteur a été poussé jusqu'ici — est un **miroir**. Le poste de l'exploitant ne route pas jusqu'à elle : c'est le **runner du site** qui publie, par `make genome-pousser` | un écosystème se reproduit depuis la forge de son site : c'est de là qu'il clone son moteur, ses plans, ses modèles. Si l'autorité est ailleurs, cette forge devient un cache qu'on croit à jour — et le 2026-08-26 elle était **quatre commits en arrière** sans que rien ne le signale, dont le correctif qui désarme le pare-feu Proxmox. **Un écosystème qui se reproduit depuis une forge en retard reproduit ses défauts.** Le poste n'a de patte que sur l'administration, et on ne perce pas de chemin pour lui : le runner existe pour ce travail | `playbooks/maintenance/genome_pousser.yml`, `scripts/genome_colis.py`, `Makefile` §genome-pousser | — |
| **D-13** | Un **hébergeur** sert plusieurs **tenants** et a son tenant par défaut | Chezlepro est les deux à la fois, ce qui masquait la distinction | `frontiere-opnsense.md` §2 | — |
| **D-14** | `underlay.yml` appartient à l'**hébergeur**, monté par symlink | ce sont ses commutateurs, ses câbles ; le moteur est générique, un tenant n'en possède pas | `sdn-evpn.md`, `underlay.yml.example` | — |

View file

@ -54,18 +54,72 @@ soi dès le premier jour.
## Ce qui est mutualisable, et ce qui ne l'est pas
> **Le critère, à deux tranchants.** Un rôle appartient au SITE s'il sert la **relation**
> avec les locataires, ou les machines du site elles-mêmes. Il appartient au TENANT s'il
> sert des **utilisateurs** ou des **applications**. À l'usage, ça se décide sur deux
> questions plus dures :
>
> 1. **Ce que le site ne doit pas pouvoir VOIR** — sinon l'hébergement n'est plus
> souverain, quelles que soient les intentions.
> 2. **Ce que le tenant doit pouvoir EMPORTER** — sinon l'émancipation est un mot.
| service | mutualisable | remarque |
|---|---|---|
| forge (génome) | oui | `serveur_ops_forge_externe` |
| source d'artefacts | oui | `client_artefacts` se désactive seul si aucune n'existe |
| sauvegarde | oui | `client_backup_cible` pointe déjà hors de l'écosystème |
| observabilité | oui | l'hébergeur surveille ses locataires |
| relais courriel | oui | |
| sauvegarde | oui | `client_backup_cible` pointe déjà hors de l'écosystème ; le site héberge du **chiffré côté client** et ne peut rien en juger |
| **disponibilité** (est-ce debout ?) | oui | c'est sa fabric : il doit savoir qu'une VM est tombée |
| **métriques** (charge, disque) | oui, avec réserve | révèlent des **rythmes d'activité**, pas du contenu |
| **journaux** | **non** | voir ci-dessous — plus intime que l'annuaire |
| relais courriel | oui | l'enveloppe transite ; le contenu appartient au locataire |
| DNS | partiellement | un sous-domaine délégué, pas la zone entière |
| **PKI** | à trancher | une AC intermédiaire signée par l'hôte est possible, mais l'AC **définit l'identité** de l'écosystème |
| **PKI** | **non** (tranché le 2026-09-10) | voir ci-dessous |
| **identité** (LDAP/SSO) | le plus intime | mutualiser l'annuaire, c'est confier ses gens |
| **la voûte** | **jamais** | les secrets ne se mutualisent pas, à aucun âge |
### Pourquoi « observabilité » a été découpée en trois
La ligne disait : *« observabilité | oui | l'hébergeur surveille ses locataires »*. Elle
était trop grossière, et elle **contredisait ce qui tourne** : chaque écosystème a son
propre Icinga, et celui du site ne voit que ses sept machines (mesuré le 2026-09-10).
Surtout, elle autorisait en une case ce que la ligne du dessous interdit. **Les journaux
contiennent du contenu** — un mot de passe dans un message d'erreur, une donnée métier dans
une trace, qui a fait quoi et quand. Un hébergeur qui ingère les journaux de son locataire
en sait **plus** que s'il détenait son annuaire : l'annuaire dit qui existe, les journaux
disent ce qu'ils font.
La disponibilité, elle, est légitime : une VM tombée est un fait de la **fabric**, que
l'hébergeur porte. Les métriques sont entre les deux — elles ne disent pas *quoi*, mais
elles disent *quand* et *combien*, ce qui suffit à lire l'activité d'une organisation.
### Pourquoi la ligne PKI est tranchée : **non**
Elle disait « à trancher », en notant qu'*une AC intermédiaire signée par l'hôte est
possible*. Elle l'est techniquement — et c'est précisément ce qu'il ne faut pas faire.
Une intermédiaire signée par l'hôte lui donne le pouvoir d'**émettre des certificats
valides pour les noms du locataire**. Il peut alors se présenter comme n'importe lequel de
ses services, y compris devant les propres machines du locataire, qui les accepteront sans
sourciller — c'est exactement ce que la chaîne de confiance leur demande de faire.
C'est le même pouvoir que l'annuaire, sous une forme **moins visible** : rien n'apparaît
dans la configuration du locataire, aucune trace côté locataire, et la vérification passe.
**Une PKI par écosystème, jamais dérivée de l'hôte.** C'est déjà ce qui tourne ; la ligne
ne fait que cesser de laisser la porte entrouverte.
### Le revers : le site n'a pas d'observabilité du tout
Mesure du 2026-09-10 : le site ne porte **ni `client_journal` ni `client_metrique`**, et
aucun `loki` ni `prometheus`. Ses sept machines n'expédient rien nulle part — l'hébergeur
ne peut pas lire ses propres journaux.
C'est la conséquence directe de la frontière : à refuser de voir ceux des locataires, il
s'est privé des siens. Le remède n'est pas d'assouplir la règle, c'est de lui donner **sa
propre pile** — un `loki` et un `prometheus` du site, pour les machines du site, sans
aucun lien avec ceux d'un tenant.
## L'insémination — le premier lien, et le seul que le SITE ait le droit d'avoir
Entre tenants, le zéro-confiance est le défaut : la frontière refuse tout ce qui n'est pas