# Compte de PROVISIONNEMENT : crée buckets, politiques et comptes de service — # aucun droit sur les objets. C'est lui que lisent les rôles CI des apps, pour # qu'elles déclarent leurs buckets sans qu'on leur confie le root. # Décisions : factory/doc/adr/20260726-stockage-objet-minio.md # # Noms d'actions confirmés par le premier apply réel (kadans, 2026-07-26) : le # bloc admin passe tel quel ; côté s3 il manquait `s3:ListBucket`, que le # provider appelle AVANT de créer un bucket pour savoir s'il existe déjà. resource "minio_iam_policy" "provisioner" { name = "provisioner" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "admin:CreateUser", "admin:DeleteUser", "admin:ListUsers", "admin:GetUser", "admin:CreatePolicy", "admin:DeletePolicy", "admin:GetPolicy", "admin:ListUserPolicies", "admin:AttachUserOrGroupPolicy", ] Resource = ["arn:aws:s3:::*"] }, { # s3:GetObject / s3:PutObject volontairement ABSENTS : le provisionneur # ne LIT ni n'ÉCRIT aucun objet, c'est ce qui rend son partage entre # rôles CI acceptable. # # `s3:ListBucket` est la seule concession : MinIO le demande pour un # HeadBucket, et le provider teste l'existence du bucket avant de le # créer. Il donne la vue des CLÉS d'un bucket, jamais leur contenu. Effect = "Allow" Action = ["s3:CreateBucket", "s3:DeleteBucket", "s3:ListBucket", "s3:ListAllMyBuckets", "s3:GetBucketLocation", "s3:GetBucketPolicy", "s3:PutBucketPolicy"] Resource = ["arn:aws:s3:::*"] }, ] }) } resource "random_password" "provisioner" { length = 40 special = false } resource "minio_iam_user" "provisioner" { name = "provisioner" secret = random_password.provisioner.result force_destroy = false } resource "minio_iam_user_policy_attachment" "provisioner" { user_name = minio_iam_user.provisioner.id policy_name = minio_iam_policy.provisioner.id } resource "vault_kv_secret_v2" "provisioner" { mount = "kvv2" name = "minio/provisioner" data_json = jsonencode({ MINIO_ENDPOINT = var.minio_endpoint MINIO_ACCESS_KEY = minio_iam_user.provisioner.id MINIO_SECRET_KEY = random_password.provisioner.result }) }