Files
tools/minio/iac/modules/minio_app/README.md
T
arcodange 249ff00d3a
Helm Charts / Detect changed charts (push) Successful in 1m2s
Helm Charts / Library charts tool (push) Skipped
Helm Charts / Application charts chart (push) Skipped
Helm Charts / Application charts crowdsec (push) Skipped
Helm Charts / Application charts grafana (push) Skipped
Helm Charts / Application charts hashicorp-vault (push) Skipped
Helm Charts / Application charts pgbouncer (push) Skipped
Helm Charts / Application charts pgcat (push) Skipped
Helm Charts / Application charts prometheus (push) Skipped
Helm Charts / Application charts redis (push) Skipped
Helm Charts / Application charts minio (push) Successful in 11s
minio_app : le compte de service peut refermer et abandonner un téléversement en parts (kadans#1033) (#35)
2026-09-07 09:07:28 +02:00

105 lines
4.5 KiB
Markdown

# `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 :
```hcl
# 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
parts** — `ListMultipartUploadParts` 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.