Set-OPS-Public/docs/audit/reference-avant-reconstruction-2026-08-08.md

133 lines
6.4 KiB
Markdown
Raw Normal View History

# État de référence — avant reconstruction from-zero
> Figé le 2026-08-08, écosystème **chezlepro** (index 17, 14 VM), avant destruction et
> rejeu complet du plan. **Ce document existe pour que « identique » soit prouvable
> plutôt que ressenti.** Toute divergence après reconstruction se lit contre lui.
## Les cinq devis, avant
```
identite CONFORME : le réel correspond au déclaré (1 compte(s) dans l'annuaire).
certificats CONFORME : aucun certificat servi n'est en fin de vie.
expositions CONFORME : toute exposition déclarée répond, des deux points de vue.
postgresql CONFORME : chiffrement imposé, et aucun réseau hors du supernet dérivé.
courriel CONFORME : la chaîne tient, de la résolution LDAP à la boîte.
```
## Ce que la flotte porte
```
backup-01 10.27.18.21 1 service(s) metier
collab-01 10.27.21.21 3 service(s) metier
data-sql-01 10.27.18.11 2 service(s) metier
edge-mta-01 10.27.16.21 2 service(s) metier
forge-01 10.27.21.11 1 service(s) metier
idm-01 10.27.17.11 3 service(s) metier
infra-dns-01 10.27.19.11 1 service(s) metier
infra-edge-01 10.27.16.11 2 service(s) metier
infra-mail-01 10.27.19.31 2 service(s) metier
infra-pki-01 10.27.19.21 2 service(s) metier
mon-01 10.27.20.21 6 service(s) metier
obs-01 10.27.20.11 2 service(s) metier
web-dorsal-01 10.27.21.41 2 service(s) metier
web-frontal-01 10.27.21.31 2 service(s) metier
```
## Ce qui sera perdu et devra être refait à la main
| Objet | Conséquence | Geste de reprise |
|---|---|---|
| **Clé racine de l'AC** (`/etc/step-ca/secrets/root_ca_key`) | la racine installée dans le navigateur devient inutile ; tous les certificats changent | `make ca-racine` + réinstaller, en comparant l'empreinte (§6.3) |
| **Mot de passe du compte `sysadmin`** | l'annuaire est recréé vide, puis amorcé | relever le jeton d'amorçage en voûte (§6.1) et le changer |
| **Contenu applicatif** (dépôts Forgejo, fichiers Nextcloud, courriels, tableaux Grafana) | non sauvegardé, non reconstructible par le code | aucun — assumé : c'est un POC |
> Ce qui **survit** : les deux voûtes et `~/.config/setops-vault-pass` vivent hors dépôt
> et hors cluster ; le code est sur `eregion.chezlepro.ca` (192.168.12.201), machine
> distincte du tenant. Rien de ce qui est nécessaire au rejeu n'est dans les 14 VM.
---
## Après reconstruction — 2026-08-09
Écosystème détruit (14 VM, disques compris) puis **rejoué depuis le plan seul**. Aucune
sauvegarde restaurée : ni LDAP, ni base, ni certificat, ni fichier.
```
identite CONFORME
certificats CONFORME
expositions CONFORME
postgresql CONFORME
courriel CONFORME
```
**Cinq sur cinq, identiques à la référence.** C'est la première fois que le dépôt peut dire
que le système reconstruit est celui que le plan décrit — au lieu de dire que le dépôt est
cohérent avec lui-même.
### Les six défauts que seul un rejeu depuis zéro pouvait montrer
| # | Défaut | Pourquoi il dormait |
|---|---|---|
| 1 | `amorcage_acces_courriel` jamais déclaré par le tenant | le compte existait déjà, le garde-fou n'avait jamais eu à se déclencher |
| 2 | rôles de realm créés **après** leur attachement aux groupes | un passage précédent les avait créés |
| 3 | claim de groupes posé **avant** les clients OIDC | les clients existaient déjà |
| 4 | écriture Keycloak annulée par le collecteur de transactions | la synchro LDAP complète ne se rejoue pas en exploitation |
| 5 | `grafana-cli` lancé avant que Grafana ait fini de démarrer | le service tournait depuis toujours |
| 6 | port d'Alloy (12345) en collision avec le SASL de Dovecot | Alloy tenait le port ; c'est **Dovecot** qui échouait, en silence |
Trois défauts d'ordre, deux courses de premier démarrage, un conflit de port. **Aucun
n'était visible à un redéploiement**, et aucun aux 31 preuves statiques — elles lisent le
dépôt, pas la machine.
Le sixième mérite d'être relu : le conflit existait depuis toujours, mais dans l'autre
sens. Alloy tenait `12345` et l'écoute SASL de Dovecot échouait sans que personne ne le
voie. La reconstruction a inversé l'ordre de démarrage et rendu visible un défaut qui
était là depuis le début.
### Ce qui a dû être refait à la main
- **La base de Grafana** : le premier démarrage, interrompu par le défaut nº 5, avait
laissé un schéma à moitié migré (`no such column: with_credentials`). Base mise de côté,
recréée par Grafana — 95 s pour lier son port, ce qui explique la course.
- **Rien d'autre.** Ni certificat, ni compte, ni zone DNS, ni base de données.
---
## Idempotence de la flotte — référence du 2026-08-09
Mesure faite après la seconde reconstruction, en rejouant `make deployer-tout` sur une
flotte intacte. Le dépôt n'avait jamais fait ce test à l'échelle de la flotte.
```
plays taches ok changed sautees
rejeu depuis zero 61 2152 924 443
2e passage 30 2249 17 ...
3e passage (apres) 30 2266 0 227
```
**Zéro tâche `changed`, zéro échec.**
Et ce zéro n'est pas du silence : **plus de tâches se sont exécutées au passage à vide
qu'au rejeu** (2266 contre 2152). Elles ont toutes tourné, et toutes trouvé le système
conforme. Un zéro obtenu avec moins de tâches aurait signifié l'inverse — des rôles qui ne
font plus leur travail.
### Ce que les 17 du deuxième passage cachaient
| Tâche | Ce que c'était vraiment |
|---|---|
| 13× `Activer et demarrer node_exporter` | **le service était mort** — tué par `SIGHUP` à chaque renouvellement de certificat |
| 2× Prometheus | liste de cibles non ordonnée (`intersect` rend un ensemble) |
| 2× Forgejo | **le dépôt faisait tourner le secret JWT du service** à chaque déploiement |
Deux des trois n'étaient pas des défauts d'idempotence : c'étaient des **pannes**, qu'un
compte de `changed` a rendues visibles. La collecte de métriques s'arrêtait toutes les
24 heures sur les quatorze hôtes, et les jetons OAuth2 de la forge étaient invalidés à
chaque passage. Ni l'une ni l'autre ne se signalait autrement.
### À quoi sert ce chiffre
Il devient la **ligne de base**. Un déploiement futur qui rapporte `changed` sur une flotte
non modifiée signale quelque chose : soit une dérive du système, soit un rôle qui a cessé
d'être idempotent. Tant que le fond était à 17, ce signal était noyé.