Set-OPS-Public/docs/authentification.md

140 lines
7.8 KiB
Markdown
Raw Normal View History

authentification : SSO Keycloak devant, secours par sudo, formulaire local fermé Directive : toute authentification web passe par Keycloak, LDAP est la source unique des comptes, chaque service garde un accès de secours par sudo sur l'hôte. Les trois sont indissociables — la chaîne service → Keycloak → LDAP est en série, donc sans secours une panne exclut tout le monde, y compris pour réparer. Portée : le web seulement ; IMAP/SMTP se lient à LDAP directement et SSH est en clé seule. Posture <rôle>_connexion_locale, false par défaut. Le compte local existe — il ne peut pas dépendre de Keycloak — mais son formulaire n'est plus proposé au repos : ouvert en permanence, il contourne la politique de mot de passe, le MFA et surtout la révocation centrale. Vérifié auprès de l'amont, puis par rendu réel des gabarits dans les deux postures : - Grafana GF_AUTH_DISABLE_LOGIN_FORM → ferme ; - Forgejo ENABLE_INTERNAL_SIGNIN + ENABLE_BASIC_AUTHENTICATION → ferme, API Basic comprise. N'existe que depuis la v10 (ticket amont 7476) ; le rôle épingle 10.0.0 et un assert refuse la fermeture en deçà, car le réglage serait ignoré sans erreur ; - Nextcloud hide_login_form → MASQUE seulement : ?direct=1 reste le chemin de secours documenté par l'amont. Écrit comme tel, sans prétendre à l'équivalence. Défaut attrapé par le rendu : la condition Forgejo sans `| bool` n'émettait rien dans aucune posture — une valeur en chaîne est vraie au sens Jinja, la connexion locale serait restée ouverte en silence. docs/authentification.md, décisions D-38 à D-41. ansible-lint (production) sans échec, 28 preuves OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:50:36 -04:00
# Authentification : Keycloak devant, LDAP dessous, `sudo` en secours
preuve : P34 — chaque document declare son lecteur (D-74) La refonte de ce matin posait une convention. Une convention qu'on n'outille pas tient tant que quelqu'un y pense : c'est le raisonnement de D-70, applique au corpus documentaire. Etat de depart mesure : 2 documents sur 34 declaraient leur lecteur. Les 32 autres disaient leur SUJET — ce qui avait enfoui le runbook de reprise le plus utile du depot au §6 de autorisation.md. Les 38 le declarent desormais, lecteur determine document par document et non colle au gabarit : l'exploitant (devis, migration de tenant, cycle de vie, gabarit d'or), le mainteneur (conceptions, registres, carte), le lecteur externe (ecosysteme-chezlepro), l'agent IA (MISE-A-JOUR-CODEX-CLAUDE). Deux exemptions DERIVEES, pas listees — un chemin en dur aurait vieilli a la premiere page ajoutee : un document qui s'annonce genere, et un fragment sans titre. Les 13 exemptes verifies un par un ; aucun document ecrit a la main n'est exempte par accident. La preuve ne lit que l'EN-TETE, ce qui empeche frontiere-opnsense.md et plan-et-generation.md — qui parlent de generation dans leur corps — d'etre exemptes a tort. Eprouvee dans les deux sens. Elle a echoue seule des sa premiere execution en nommant deux documents que mon inventaire avait manques (docs/audit/). Puis test negatif delibere : declaration retiree de meta-classe.md -> ECHEC la nommant ; restauree -> OK. Ce qu'elle ne teste pas : que le lecteur declare soit le BON. Ca se juge en revue ; elle garantit qu'on a du y penser. P01–P34. Comptes perimes corriges au passage (AGENTS.md et devis-services.md annoncaient encore 30 preuves). Verifie : prouver.py 0 (34 OK), plan-recette inchange. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 07:53:04 -04:00
> **Pour qui :** le **mainteneur** — la doctrine d'authentification, avant de brancher un service.
authentification : SSO Keycloak devant, secours par sudo, formulaire local fermé Directive : toute authentification web passe par Keycloak, LDAP est la source unique des comptes, chaque service garde un accès de secours par sudo sur l'hôte. Les trois sont indissociables — la chaîne service → Keycloak → LDAP est en série, donc sans secours une panne exclut tout le monde, y compris pour réparer. Portée : le web seulement ; IMAP/SMTP se lient à LDAP directement et SSH est en clé seule. Posture <rôle>_connexion_locale, false par défaut. Le compte local existe — il ne peut pas dépendre de Keycloak — mais son formulaire n'est plus proposé au repos : ouvert en permanence, il contourne la politique de mot de passe, le MFA et surtout la révocation centrale. Vérifié auprès de l'amont, puis par rendu réel des gabarits dans les deux postures : - Grafana GF_AUTH_DISABLE_LOGIN_FORM → ferme ; - Forgejo ENABLE_INTERNAL_SIGNIN + ENABLE_BASIC_AUTHENTICATION → ferme, API Basic comprise. N'existe que depuis la v10 (ticket amont 7476) ; le rôle épingle 10.0.0 et un assert refuse la fermeture en deçà, car le réglage serait ignoré sans erreur ; - Nextcloud hide_login_form → MASQUE seulement : ?direct=1 reste le chemin de secours documenté par l'amont. Écrit comme tel, sans prétendre à l'équivalence. Défaut attrapé par le rendu : la condition Forgejo sans `| bool` n'émettait rien dans aucune posture — une valeur en chaîne est vraie au sens Jinja, la connexion locale serait restée ouverte en silence. docs/authentification.md, décisions D-38 à D-41. ansible-lint (production) sans échec, 28 preuves OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:50:36 -04:00
> **Directive d'architecture du 2026-08-03.** Trois règles, décidées ensemble et
> volontairement indissociables — chacune crée le problème que la suivante résout.
1. **Toute authentification web passe par Keycloak.** Aucun service ne tient son propre
répertoire de comptes.
2. **LDAP est la source de vérité unique** des comptes d'un tenant. Keycloak le fédère ;
les protocoles qui ne parlent pas OIDC s'y lient directement.
3. **Chaque service garde un accès de secours**, atteint par `sudo` sur l'hôte.
## 1. Pourquoi les trois vont ensemble
La chaîne est en série : `service → Keycloak → LDAP`. C'est ce qui donne « une identité, un
mot de passe » — et c'est aussi trois points de panne alignés. Si LDAP tombe, plus personne
n'entre nulle part, y compris pour réparer.
La règle 3 n'est donc pas une entorse au SSO : c'est ce qui rend les deux premières
tenables. Sans elle, la panne d'un maillon devient une exclusion totale.
## 2. Portée : le web, et seulement le web
| Protocole | Chemin d'authentification | Pourquoi |
|---|---|---|
| **HTTP(S)** — interfaces humaines | **Keycloak** (OIDC natif, ou `oauth2-proxy` devant) | c'est là que la directive s'applique |
| **IMAP / SMTP** | **LDAP direct** (Dovecot, Postfix) | ces protocoles ne parlent pas OIDC ; le flux est prouvé de bout en bout |
| **SSH** | **clé publique** (`PasswordAuthentication no`) | pas de mot de passe du tout, donc rien à fédérer |
| **PostgreSQL, Redis** | secrets applicatifs en voûte | comptes de service, pas d'humains |
Ce qui est interdit partout, c'est qu'un service tienne **son propre répertoire d'humains**.
Le chemin varie ; la source ne varie pas.
## 3. La posture retenue : la porte de secours n'est pas annoncée
Le compte local de chaque service **existe** — il ne peut pas dépendre de Keycloak, sinon il
tomberait avec lui. Mais son formulaire de connexion **n'est pas proposé au repos**.
Ce n'est pas une préférence esthétique. Un formulaire local ouvert en permanence :
- contourne la politique de mot de passe et le MFA ;
- contourne surtout la **révocation centrale** — désactiver quelqu'un dans LDAP laisserait
son compte local valide, sans que rien ne le signale ;
- offre une cible de bourrage d'identifiants sur `admin`, en continu, pour un usage qui
devrait être exceptionnel.
Le coût de la fermeture est nul depuis qu'on a tranché que **`sudo` suffit** : `sudo` *est*
le mécanisme de réouverture.
### Ce que chaque service sait vraiment faire
Vérifié auprès de l'amont le 2026-08-03, puis par **rendu réel des gabarits** dans les deux
postures — pas seulement lu.
| Service | Réglage | Effet réel | Secours par `sudo` |
|---|---|---|---|
| **Grafana** | `GF_AUTH_DISABLE_LOGIN_FORM=true` | ferme le formulaire | `grafana-cli admin reset-admin-password` |
| **Forgejo** ≥ 10 | `ENABLE_INTERNAL_SIGNIN=false` + `ENABLE_BASIC_AUTHENTICATION=false` | ferme la connexion interne **et** l'API en Basic | `forgejo admin user change-password` |
| **Nextcloud** | `hide_login_form=true` | **masque seulement** | `occ user:resetpassword`, ou `…/login?direct=1` |
> **Nextcloud est une exception, et il faut la dire.** `hide_login_form` **masque** le
> formulaire ; `…/login?direct=1` y accède encore, et l'amont le documente comme voulu —
> c'est ainsi qu'un administrateur entre. La protection est donc de **ne plus l'annoncer**,
> pas de l'interdire. Le présenter comme équivalent à Grafana ou Forgejo donnerait un faux
> confort.
Le réglage s'appelle `<rôle>_connexion_locale` dans les trois rôles, et vaut `false` par
défaut. Le passer à `true` rouvre la porte, explicitement.
**Garde de version.** `ENABLE_INTERNAL_SIGNIN` n'existe **que depuis Forgejo v10** (suivi
amont, ticket 7476 : *« This option was added to Forgejo v10 »*). Sur une version
antérieure il serait ignoré **sans erreur** — le rôle croirait avoir fermé la porte. Un
`assert` refuse donc `connexion_locale: false` sous 10.0.0 plutôt que de laisser croire.
## 4. La chaîne de secours
Trois maillons, aucun ne dépendant d'une porte web ouverte :
```
1. SSO Keycloak → LDAP ← la voie normale
2. sudo via SSH occ / grafana-cli / forgejo admin ← Keycloak ou LDAP en panne
3. console Proxmox de la VM ← SSH inaccessible
```
Un accès de secours qu'on ne sait pas emprunter n'existe pas : les commandes exactes sont
dans le tableau ci-dessus, et les mots de passe locaux vivent dans la voûte unique de
l'instance.
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
## 5. La garde : chaque rôle déclare sa position
Une directive qu'aucune garde ne vérifie finit par ne plus être vraie. Chaque rôle
`serveur_*` porte donc un `meta/authentification.yml`, et **P29** le confronte à son code.
| Portée | Sens | Rôles |
|---|---|---|
| `web-sso` | authentification humaine web → Keycloak (`mecanisme: natif` ou `oauth2-proxy`) | 5 |
| `socle-identite` | **est** la chaîne d'identité, ne peut pas se déléguer à elle-même | keycloak, openldap |
| `ldap-direct` | protocole non-OIDC lié à LDAP | dovecot, postfix |
| `interne-sans-auth` | interface joignable **dans** le tenant sans authentification, non exposée | prometheus, loki |
documentation : la tournee des 74 documents, parce qu un balayage ne lit pas La revision a commence par un balayage par motifs — chemins morts, cibles make absentes, comptes derives. Il a trouve une trentaine d ecarts et rate presque tout le reste : un motif ne voit que ce qui s exprime en motif. make hote-planifier en est l exemple. La cible EXISTE, donc le controle passait au vert. C est une cible depreciee qui refuse et sort en 2, recommandee par AGENTS.md, et qui contredit la REGLE D OR du meme fichier trois ecrans plus haut. Il fallait lire pour la voir. 74 documents lus un par un. 66 corriges, 8 exacts. CE QUI ETAIT FRANCHEMENT FAUX AGENTS.md, la source d autorite, annoncait la flotte pas encore executee contre des VM reelles. Elle a ete rasee et remontee depuis zero trois fois. ecosysteme-chezlepro.md, le document montre a un client, portait la meme phrase : il se sous-vendait gravement. courriel-conception.md s ouvrait sur aucun role n est encore ecrit, au-dessus de son propre paragraphe 1 qui les nomme. autorisation.md se terminait sur rien n est construit alors qu il rapporte des mesures datees du role en fonctionnement. hebergeur-exploitation.md disait rien n est fait d un depot qui existe. filiation-emancipation.md se contredisait a deux ecrans de distance. DES MODELES DECRITS D APRES UN MONDE ANTERIEUR Le resolveur : cinq documents decrivaient un Unbound par VM en opt-in, trois le donnaient en exemple d integration FACULTATIVE — il est universel depuis le 2026-08-24. L adressage de nomenclature-vm.md : reseau unique, VLAN 11-15, VMID a cinq chiffres. Le nommage SDN de sdn-evpn.md contre le code : c est le wiki qui avait raison. CE QUI CASSE AU PREMIER ESSAI Le nom du gabarit dore etait faux a quatre endroits, dont la procedure qui le FABRIQUE et le critere R2 de l epreuve d operateur independant. preparer-un-site-hebergeur.md avertissait qu une VM faite a la main serait detruite : raser derive du plan, il ne la detruira jamais — le risque est l inverse. Un mot de passe d essai en clair dans un depot public. DEUX PREUVES ETENDUES, ET UNE QUI SE TROMPAIT ELLE-MEME P57 couvre les groupes : elle a signale aussitot 29 groupes annonces au-dessus d un tableau qui en cite 40. P29 confronte le tableau de authentification.md aux declarations reelles : 12 annonces, 21 reels. Et P57 imposait un chiffre faux — 56 preuves alors que le depot en porte 57, la conditionnelle vivant hors de tout comptage. Un garde-fou qui fait respecter une erreur ajoute l assurance a l erreur. CE QUI RESTE, ET QU AUCUNE PREUVE NE TIENT Deux comptes trouves a la main. Et une lacune reelle : rien ne garde les meta/acces.yml — ni qu un service web-sso en porte un, ni que le groupe qu il nomme existe. P29 tient les positions d authentification, personne ne tient les habilitations. make prouver : CONFORME, 56 OK, 0 echec, 1 saute. 0 lien mort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-06 16:18:23 -04:00
| `sans-auth-humaine` | aucun point d'authentification humaine | 21 |
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
La preuve refuse **l'oubli et le mensonge** : un rôle sans déclaration, une portée
inventée, un `web-sso` sans accès de secours ou sans posture de formulaire, un `web-sso
natif` sans réglage `<rôle>_connexion_locale` **défini dans `defaults`**, et une
déclaration que le code contredit.
preuves : trois gardes pour ce que ma lecture ne tiendra pas Une revision de documentation vieillit comme le reste. Ce qui tient, c est ce qu une machine verifie — et trois lacunes etaient nommees sans etre gardees. P58 HABILITATIONS. autorisation.md posait la regle (un service nomme un GROUPE, jamais une personne, D-66) et meta/acces.yml la portait ; rien ne la verifiait. P29 gardait les POSITIONS d authentification, personne ne gardait les DROITS. Le controle qui porte la preuve est un croisement : une entree porte_par: role-realm affirme que l habilitation voyage par un role de realm projete depuis un groupe LDAP. P58 le confronte a serveur_keycloak. Sans ca, un service annonce une habilitation que rien ne transporte, et l ecran reste vide sans que personne sache pourquoi. CE QU ELLE N EXIGE PAS, et c est le point le plus important : que les groupes nommes existent dans l annuaire. Ce serait contredire le regime du paragraphe 2 — le depot AMORCE un acces et se retire, les appartenances appartiennent a une personne. dev et personnel n existent dans aucun code, et ce n est pas un defaut. P59 ENUMERATIONS ANNONCEES. Les deux ecarts trouves a la main pendant la tournee — cinq portes annoncees devant une table de six, huit lignes renvoyees vers une fiche qui en compte dix — etaient d une forme que P57 ne voit pas. Ma premiere version a signale CINQ ecarts, et les cinq etaient du bruit : dans « reprise dans les deux devis : », le nombre qualifie autre chose que la liste. Cent pour cent de faux positifs — la preuve qui crie sur un cas sain et qu on apprend a ignorer. Resserree aux deux formes ou le nombre ne peut compter rien d autre. Etroite et vraie plutot que large et devineuse. P60 WIKI PUBLIE. Le wiki est publie DEPUIS le depot ; rien ne mesurait l ecart, et il s est creuse de VINGT-SEPT JOURS en silence. Deux unites jamais publiees, vingt et une differentes : pour qui lit la forge plutot que le depot, toute la revision n existait pas. Le harnais est STATIQUE, zero appel reseau — cloner la forge romprait la seule propriete qui fasse qu une preuve vaille hors de ce poste. La mesure passe donc par un TEMOIN que make wiki-publier depose. Amorce avec la valeur MESUREE : le wiki d eregion porte b6167f2, dont le message dit source: ac85278. Ce qu elle ne prouve pas : un temoin dit ce qui est PARTI, jamais ce qui est ARRIVE. LES TROIS SONT EPROUVEES DANS LES DEUX SENS Douze essais negatifs, douze refus : groupe non projete, acces.yml disparu, personne au lieu d un groupe, mecanisme invente, raison manquante, compte revenu a cinq, septieme porte ajoutee sans toucher au compte, renvoi croise fausse, temoin absent, temoin d un autre depot. Une garantie qu on n a jamais vu dire non n est pas une garantie, c est une habitude. ETAT : NON CONFORME, 58 OK, 1 echec, 1 saute. P60 est rouge, et c est le comportement voulu : le registre a le droit de perdre. Le retard qu elle signale est reel et anterieur a elle. Une commande le ferme, et elle vient ensuite. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 12:47:18 -04:00
**Et depuis le 2026-09-07, sa sœur `P58` garde les habilitations** — ce que P29 ne fait
pas : elle tient les *positions* (qui s'authentifie comment), pas les *droits* (qui obtient
quoi). Voir [`autorisation.md`](autorisation.md) §5.
documentation : la tournee des 74 documents, parce qu un balayage ne lit pas La revision a commence par un balayage par motifs — chemins morts, cibles make absentes, comptes derives. Il a trouve une trentaine d ecarts et rate presque tout le reste : un motif ne voit que ce qui s exprime en motif. make hote-planifier en est l exemple. La cible EXISTE, donc le controle passait au vert. C est une cible depreciee qui refuse et sort en 2, recommandee par AGENTS.md, et qui contredit la REGLE D OR du meme fichier trois ecrans plus haut. Il fallait lire pour la voir. 74 documents lus un par un. 66 corriges, 8 exacts. CE QUI ETAIT FRANCHEMENT FAUX AGENTS.md, la source d autorite, annoncait la flotte pas encore executee contre des VM reelles. Elle a ete rasee et remontee depuis zero trois fois. ecosysteme-chezlepro.md, le document montre a un client, portait la meme phrase : il se sous-vendait gravement. courriel-conception.md s ouvrait sur aucun role n est encore ecrit, au-dessus de son propre paragraphe 1 qui les nomme. autorisation.md se terminait sur rien n est construit alors qu il rapporte des mesures datees du role en fonctionnement. hebergeur-exploitation.md disait rien n est fait d un depot qui existe. filiation-emancipation.md se contredisait a deux ecrans de distance. DES MODELES DECRITS D APRES UN MONDE ANTERIEUR Le resolveur : cinq documents decrivaient un Unbound par VM en opt-in, trois le donnaient en exemple d integration FACULTATIVE — il est universel depuis le 2026-08-24. L adressage de nomenclature-vm.md : reseau unique, VLAN 11-15, VMID a cinq chiffres. Le nommage SDN de sdn-evpn.md contre le code : c est le wiki qui avait raison. CE QUI CASSE AU PREMIER ESSAI Le nom du gabarit dore etait faux a quatre endroits, dont la procedure qui le FABRIQUE et le critere R2 de l epreuve d operateur independant. preparer-un-site-hebergeur.md avertissait qu une VM faite a la main serait detruite : raser derive du plan, il ne la detruira jamais — le risque est l inverse. Un mot de passe d essai en clair dans un depot public. DEUX PREUVES ETENDUES, ET UNE QUI SE TROMPAIT ELLE-MEME P57 couvre les groupes : elle a signale aussitot 29 groupes annonces au-dessus d un tableau qui en cite 40. P29 confronte le tableau de authentification.md aux declarations reelles : 12 annonces, 21 reels. Et P57 imposait un chiffre faux — 56 preuves alors que le depot en porte 57, la conditionnelle vivant hors de tout comptage. Un garde-fou qui fait respecter une erreur ajoute l assurance a l erreur. CE QUI RESTE, ET QU AUCUNE PREUVE NE TIENT Deux comptes trouves a la main. Et une lacune reelle : rien ne garde les meta/acces.yml — ni qu un service web-sso en porte un, ni que le groupe qu il nomme existe. P29 tient les positions d authentification, personne ne tient les habilitations. make prouver : CONFORME, 56 OK, 0 echec, 1 saute. 0 lien mort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-06 16:18:23 -04:00
**Depuis le 2026-09-06, elle refuse aussi que ce tableau mente.** Les chiffres et les listes
de la troisième colonne sont confrontés aux déclarations réelles. Ils avaient cessé d'être
vrais sans que rien ne le signale : la ligne `sans-auth-humaine` annonçait 12 rôles, il y en
avait 21 — la preuve lisait les déclarations depuis le début, mais ne regardait pas ce que
le document en disait.
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
> **Les indices doivent être nommés.** Une première version cherchait les mots « ldap » et
> « oidc » dans le rôle. Le mot *LDAP*, présent dans un commentaire de `serveur_grafana`,
> suffisait alors à valider une déclaration `ldap-direct` mensongère. La preuve exige
> désormais une **variable du namespace du rôle** (`<rôle>_oidc`, `<rôle>_ldap`) ou une URI
> `ldap://` — ce qu'une phrase en prose ne produit pas.
Une valeur mérite d'être expliquée : `formulaire_local: aucun`. Elle distingue un service
qui **n'a pas de compte local du tout** — `oauth2-proxy` est une passerelle — de celui qui
en a un et l'a fermé. Sans elle, on écrirait « fermé », ce qui laisserait croire qu'une
porte a été close alors qu'il n'y en a jamais eu.
### Les lacunes sont comptées, pas masquées
`interne-sans-auth` ne fait pas échouer la preuve : c'est une lacune **assumée et nommée**.
Mais elle est comptée à chaque exécution, donc visible dans chaque rapport. La refuser
bloquerait le harnais sur une décision déjà prise ; la taire la ferait oublier.
Prometheus et Loki sont dans ce cas. À noter, contre une idée reçue de la veille : **ils ne
sont pas exposés publiquement** — aucun `expose` au plan. Seuls six groupes le sont
(collabora, forgejo, grafana, keycloak, nextcloud, oauth2-proxy). Le risque est donc
intra-tenant, pas frontalier — plus petit qu'annoncé, réel quand même. `oauth2-proxy` est
déjà éprouvé devant Icinga Web 2 : le patron existe, il reste à l'appliquer.