feat(minio) — un compte de service par app consommatrice, borné à son bucket #21
Merged
arcodange
merged 6 commits from 2026-07-26 10:46:45 +02:00
arcodange/minio-comptes-de-service into main
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7074a94d7e |
docs(minio) — le raisonnement part dans l'ADR, le code garde ce qui protège
Helm Charts / Detect changed charts (push) Successful in 22s
Helm Charts / Detect changed charts (pull_request) Successful in 16s
MinIO / Auth with gitea for vault (push) Failing after 8m33s
MinIO / Tofu - minio IAC (push) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m31s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Les décisions de conception (qui déclare, qui détient, pourquoi les octets ne passent pas par l'API) vivent désormais dans `factory/doc/adr/20260726-stockage-objet-minio.md`. Le code ne garde que ce qu'un relecteur ne peut pas deviner et qui l'empêcherait de casser quelque chose : l'absence VOLONTAIRE de s3:GetObject/PutObject dans la politique du provisionneur, l'absence VOLONTAIRE de basic-auth sur l'ingress S3, le caractère inconditionnel de la règle Vault, et l'avertissement sur les noms d'actions MinIO non éprouvés. Chaque fichier pointe l'ADR. 283 → 230 lignes sur minio/iac. tofu fmt propre, tofu validate réussi sur les deux racines. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
ec71571b98 |
refactor(minio) — chacun son périmètre : les buckets se déclarent depuis le dépôt de l'app
Helm Charts / Detect changed charts (push) Successful in 16s
Helm Charts / Detect changed charts (pull_request) Successful in 16s
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
MinIO / Auth with gitea for vault (push) Failing after 8m31s
MinIO / Tofu - minio IAC (push) Has been skipped
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
Hashicorp Vault / Auth with gitea for vault (push) Has been cancelled
Hashicorp Vault / Tofu - Vault IAC (push) Has been cancelled
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Les buckets sont à déclarer dans le repo de kadans-api. On ne va pas modifier le repo tools à chaque changement d'application. Chacun son périmètre. Tools peut proposer un module pour standardiser la déclaration de buckets à la limite, mais c'est tout. » (fondateur, 26/07) C'est une erreur de fond de ma part : j'avais fait de `tools` le PROPRIÉTAIRE de déclarations qui appartiennent aux applications. À ce rythme, chaque nouveau bucket de n'importe quelle app devenait une PR sur l'infra partagée. CE QUI CHANGE. `consumers.tf` disparaît, et la liste de buckets du chart se vide. À la place, un module réutilisable `iac/modules/minio_app` : une app lui donne son nom et ses buckets, et reçoit des buckets privés, un compte de service qui ne peut rien toucher d'autre, et ses clés dans `kvv2/minio/<app>`. L'OBSTACLE, ET SA RÉPONSE. Déclarer ses buckets depuis son propre dépôt suppose des droits d'ADMINISTRATION sur MinIO. Confier le root serait absurde : il lit et écrit tous les objets de toutes les apps. `tools` fournit donc un compte PROVISIONNEUR aux droits minimaux — créer un bucket, une politique, un compte de service — et AUCUN droit sur les objets. Une app compromise pourrait créer des buckets (une nuisance), pas lire les vidéos d'une autre. Le root, lui, ne sort toujours pas de ce pipeline. Le rôle CI de chaque app gagne la lecture de `kvv2/data/minio/provisioner` dans `app_policy` — générique, et c'est exactement le genre de standardisation qui appartient au dépôt commun. ⚠ CE QUE JE N'AI PAS PU PROUVER : les noms d'actions d'administration MinIO de la politique du provisionneur viennent de la documentation, pas d'un essai — je n'ai pas d'identifiants admin en main. Le premier `apply` les confirmera ou les corrigera. C'est le seul point non vérifié de cette PR, et il est signalé dans le code à l'endroit exact. tofu fmt propre · tofu validate réussi sur minio/iac ET hashicorp-vault/iac. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
0e1b6e1062 |
refactor(minio) — lever la restriction « un seul bucket par app »
Helm Charts / Detect changed charts (pull_request) Successful in 17s
Helm Charts / Detect changed charts (push) Successful in 16s
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been cancelled
Helm Charts / Library charts tool (push) Has been cancelled
MinIO / Tofu - minio IAC (push) Has been cancelled
MinIO / Auth with gitea for vault (push) Has started running
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Pourquoi sommes-nous restreints sur les buckets ? » (fondateur, 26/07) — parce
que JE l'avais décidé, pour rendre tout dérivable d'un seul nom. Rien ne
l'imposait, et la restriction aurait mordu au pas suivant : l'ADR-018 de Kadans
prévoit DEUX paliers de transfert (aperçu 240p régénérable, travail 360p à
garder), donc deux cycles de vie, donc potentiellement deux buckets aux
politiques de purge différentes.
Chaque bucket déclare désormais son app (`app: kadans`). C'est toujours la SEULE
déclaration, au même endroit — mais le nom du bucket redevient libre, et
`kadans-videos` retrouve un nom qui dit ce qu'il contient.
Le compte de service devient par APP et non par bucket : une seule clé, autorisée
sur tous ses buckets et eux seuls. Ajouter un bucket à une app existante ne crée
donc aucune nouvelle clé — le compte existant gagne l'accès. Le secret porte
`MINIO_BUCKETS` (tous) en plus de `MINIO_BUCKET` (le premier), pour que l'app
n'ait pas à les redéclarer de son côté.
Un bucket sans `app:` est ignoré plutôt que de faire échouer le plan : il n'aura
simplement pas de compte de service, ce qui se voit immédiatement et ne casse
rien d'existant.
Vérifié sur le VRAI fichier, pas en théorie : le groupement rend bien
{"kadans" = ["kadans-videos"]}, et avec un second bucket de la même app,
{"kadans" = ["kadans-videos", "kadans-apercus"]} — le cas ADR-018 exact.
tofu fmt propre, tofu validate réussi.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
|
||
|
|
287e3dcf1e |
refactor(minio) — le BUCKET est la seule déclaration : plus de liste à tenir
Helm Charts / Detect changed charts (push) Successful in 14s
Helm Charts / Detect changed charts (pull_request) Successful in 14s
Helm Charts / Application charts pgcat (push) Has been cancelled
Helm Charts / Library charts tool (push) Has been cancelled
MinIO / Tofu - minio IAC (push) Has been cancelled
MinIO / Auth with gitea for vault (push) Has been cancelled
MinIO / Auth with gitea for vault (pull_request) Failing after 8m31s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Je ne vois pas le mal à donner la permission de lire sur un chemin qui n'existe pas. Je préfère ne pas m'embêter avec consumers ou autre. » (fondateur, 26/07) `var.consumers` disparaît. Le plan LIT `values.yaml` du chart — le même fichier qu'Helm consomme — et provisionne un compte de service par bucket. Créer un bucket EST la déclaration : il devient impossible d'avoir un bucket sans son compte, ou un compte sans son bucket. Une liste de plus aurait été une liste à tenir synchronisée, donc une liste à oublier. La convention qui rend ça possible : UN BUCKET PAR APP, NOMMÉ COMME ELLE. Le bucket passe donc de `kadans-videos` à `kadans`. Il est VIDE aujourd'hui — le renommer maintenant ne coûte rien ; dans un mois ce serait une migration. Tout en découle sans être écrit ailleurs : le compte `<app>-app` borné à ce seul bucket, le secret `kvv2/minio/<app>`, et la lecture que `app_policy` accorde déjà à toute app sur `kvv2/data/minio/<son nom>`. Vérifié plutôt que supposé : `yamldecode` lit bien ce values.yaml, ancres YAML comprises (testé en isolation avant d'écrire le plan). tofu fmt propre, tofu validate réussi. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
91a0f09b49 |
refactor(vault) — lire ses identifiants MinIO devient une propriété de la plateforme
Helm Charts / Detect changed charts (pull_request) Successful in 15s
Helm Charts / Detect changed charts (push) Successful in 15s
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m35s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m36s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Retour fondateur : « je pensais que tools#21 contribuerait à app_policy pour une policy kvv2/minio/<app name> ». Il a raison, et mon choix initial était le plus faible des deux. Mon objection — ne donner le droit qu'aux apps qui en ont besoin — ne tient pas à l'examen : la règle porte le NOM de l'app, donc elle ne peut jamais exposer que ses propres clés. Il n'y a aucun privilège à préserver. Une app qui ne stocke rien lit un chemin qui n'existe pas : une règle inerte, pas un droit. Son argument, lui, porte : savoir lire ses propres identifiants de stockage est une propriété de la PLATEFORME, pas une exception par application. Et `kv_read_paths` est documenté comme la trappe pour un secret appartenant à une AUTRE app (les creds GCS de Longhorn pour l'ERP) — y ranger un motif standard l'aurait rendu invisible et aurait obligé à le redéclarer à chaque app. La règle passe donc dans `app_policy`, en prod ET pour chaque instance non-prod (symétrie stricte), sur deux chemins : le document `kvv2/data/minio/<app>` et ses descendants. Un cran plus loin que la demande : la règle est INCONDITIONNELLE, sans drapeau. Conséquence — déclarer un consommateur MinIO se fait désormais à UN SEUL endroit, `var.consumers` du pipeline minio. Aucune synchronisation à tenir entre deux fichiers, donc rien à oublier. Le `kv_read_paths` que j'avais ajouté à kadans est retiré : il faisait double emploi. tofu fmt propre · tofu validate réussi sur hashicorp-vault/iac. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
4ca4a05370 |
feat(minio) — un compte de service par app consommatrice, borné à son bucket
Helm Charts / Detect changed charts (push) Successful in 57s
MinIO / Auth with gitea for vault (push) Failing after 8m34s
MinIO / Tofu - minio IAC (push) Has been skipped
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m33s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 1m1s
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« On peut adopter ce pattern à toutes les apps qui pourraient avoir besoin de MinIO, et ainsi modifier les app roles / app policy générique. » (fondateur, 26/07) Bonne nouvelle : les modules centraux n'ont PAS eu à changer. `kv_read_paths` existe déjà dans `app_policy` et fait exactement ça — l'ERP s'en sert pour lire les creds GCS de Longhorn. Le motif générique était donc à moitié construit ; il manquait la moitié MinIO. CE QUI EST AJOUTÉ : `minio/iac/consumers.tf` provisionne, pour chaque app déclarée dans `var.consumers`, une politique MinIO bornée à SON bucket (GetObject/PutObject/DeleteObject sur les objets, ListBucket sur le bucket seul — ni les autres buckets, ni l'administration), un compte de service, et écrit ses clés dans `kvv2/minio/<app>`. POURQUOI LES CLÉS VIVENT CHEZ MINIO ET PAS CHEZ L'APP : seul ce pipeline possède les identifiants ROOT. Si chaque app créait son propre compte de service, il faudrait donner ce root à chaque rôle CI — c'est-à-dire à tout le monde. Ici il ne sort jamais d'ici, et l'app ne reçoit qu'une clé qui ne peut rien lire d'autre que son bucket. Un compte de service qui fuite ne donne accès qu'aux objets qu'il gérait déjà. Ajouter une app = trois lignes déclaratives, documentées au README : son bucket dans values.yaml, son entrée dans `var.consumers`, son `kv_read_paths` au tfvars central. Aucun module à toucher. Le provider parle à `s3.arcodange.fr` — l'endpoint PUBLIC, parce que le runner CI n'est pas dans le LAN et que `.lab` ne s'y résout pas. C'est l'exposition HTTPS mergée ce matin qui rend ce plan applicable. ⚠ Erreur attrapée par le validateur, et corrigée : je relisais `kvv2/minio/config` alors que `local.config` de main.tf porte déjà les identifiants root — une lecture qui aurait créé une dépendance circulaire avec l'écriture faite par ce même plan. Vérifié : `tofu fmt` propre, `tofu validate` réussi (avec TERRAFORM_VAULT_AUTH_JWT posé — sans lui, le provider Vault échoue déjà sur main, ce n'est pas mon fait). Je n'ai lancé AUCUN apply : c'est le workflow qui le fera, et la revue t'appartient. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |