Files
tools/minio/iac/modules/minio_app/README.md
T
arcodangeandClaude Fable 5.1 2502bc4813
Helm Charts / Detect changed charts (pull_request) Successful in 19s
Helm Charts / Library charts tool (pull_request) Skipped
Helm Charts / Application charts chart (pull_request) Skipped
Helm Charts / Application charts crowdsec (pull_request) Skipped
Helm Charts / Application charts grafana (pull_request) Skipped
Helm Charts / Application charts hashicorp-vault (pull_request) Skipped
Helm Charts / Application charts pgbouncer (pull_request) Skipped
Helm Charts / Application charts pgcat (pull_request) Skipped
Helm Charts / Application charts prometheus (pull_request) Skipped
Helm Charts / Application charts redis (pull_request) Skipped
Helm Charts / Application charts minio (pull_request) Successful in 9s
minio_app : le README dit ce que le compte de service peut faire d'un téléversement en parts (kadans#1033)
Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-07 08:23:11 +02:00

4.5 KiB

minio_app — déclarer ses buckets depuis SON dépôt

Chacun son périmètre : les buckets d'une application appartiennent au dépôt de cette application. Ce module standardise la déclaration, il ne la détient pas — sans lui, chaque bucket de chaque app deviendrait une PR sur tools.

Usage

Dans l'iac/ de l'app :

# Le provisionneur MinIO : des droits d'administration MINIMAUX (créer un
# bucket, un compte de service, une politique), jamais le root — qui, lui, ne
# sort pas du pipeline `minio`.
data "vault_kv_secret_v2" "minio_provisioner" {
  mount = "kvv2"
  name  = "minio/provisioner"
}

provider "minio" {
  minio_server   = "s3.arcodange.fr"
  minio_user     = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_ACCESS_KEY"]
  minio_password = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_SECRET_KEY"]
  minio_ssl      = true
}

module "stockage" {
  source    = "git::ssh://[email protected]:2222/arcodange-org/tools.git//minio/iac/modules/minio_app?depth=1&ref=main"
  app       = "mon-app"          # = le nom de son rôle Vault
  buckets   = ["mon-app-fichiers"]
  providers = { minio = minio }
}

Puis, côté chart : une VaultStaticSecret sur kvv2/minio/<app> et l'injection des variables dans le Deployment.

Ce que le module garantit

  • les buckets sont privés — l'accès passe par des URL présignées ;
  • les téléversements abandonnés sont ramassés au bout d'un jour (voir plus bas : c'est de l'hygiène de protocole, pas un choix de l'app) ;
  • le compte de service ne peut rien toucher d'autre que ces buckets-là ;
  • le compte de service peut refermer et abandonner un téléversement en partsListMultipartUploadParts et AbortMultipartUpload, les deux actions que PutObject ne couvre pas (sans elles, l'assemblage rend 403 et aucun objet de plus d'une part n'arrive jamais — mesuré le 2026-09-07) ;
  • ses clés vont dans kvv2/minio/<app>, que le module Vault central autorise déjà l'app à lire (règle inconditionnelle : le chemin porte le nom de l'app, donc il ne peut exposer que ses propres clés).

Plusieurs buckets

C'est le cas courant : deux contenus aux cycles de vie différents méritent deux buckets. Il suffit de les lister — le compte de service existant gagne l'accès, sans nouvelle clé.

Ce que le module ne fait PAS

Il ne pose ni quota, ni expiration de contenu, ni versioning : ces choix appartiennent à l'app et varient d'un bucket à l'autre. « Ces vidéos se purgent à 90 jours » est une décision de produit, elle se prend dans le dépôt du produit.

⚠ L'exception, et la ligne qu'elle trace

Ce module pose une seule règle de cycle de vie : AbortIncompleteMultipartUpload à 1 jour, sur chaque bucket qu'il crée.

Elle a l'air de contredire le paragraphe ci-dessus. Elle ne le contredit pas — elle en précise la frontière, et c'est la question « à QUOI cette connaissance appartient-elle ? » qui tranche :

  • une expiration de contenu porte sur des objets que l'app a voulus, qu'elle montre, et dont elle seule sait combien de temps ils valent. Elle varie d'une app à l'autre : elle est chez l'app ;
  • un téléversement en plusieurs parts jamais refermé n'est le contenu de personne. Ce sont des morceaux qu'aucune API ne montre — ni mc ls, ni la console — laissés par un navigateur qui a fermé l'onglet. Aucune app ne veut les garder, et aucune ne peut les voir depuis son propre code. C'est un déchet de PROTOCOLE, produit par le mécanisme même du bucket : il est chez celui qui crée les buckets.

Le test pratique : si la réponse à « combien de temps ? » demande de connaître le produit, c'est chez l'app. Ici, la réponse ne demande que de connaître S3 — passé l'expiration des URL signées, un téléversement en cours ne peut plus rien recevoir, il occupe seulement.

⚠ Le délai n'est pas paramétrable, et c'est voulu (YAGNI) : un seul cas existe. Le jour où une app signe des parts pour plus de 24 h, ce sera le déclencheur pour en faire une variable — pas avant.

Plancher de version

⚠ Ce module exige aminueza/minio >= 3.10.0 : abort_incomplete_multipart_upload y est apparu (mesuré en interrogeant le schéma du provider version par version — 3.9.0 ne l'a pas). Un appelant resté plus bas se verra dire, dès tofu init :

no available releases match the given constraints 3.3.0, >= 3.10.0

… ce qui NOMME la version à atteindre, au lieu d'un « unsupported block type » au plan, qui ne l'aurait pas dite.