diff --git a/hashicorp-vault/iac/factory_auth.tf b/hashicorp-vault/iac/factory_auth.tf index d9a1fc0..ba87ce1 100644 --- a/hashicorp-vault/iac/factory_auth.tf +++ b/hashicorp-vault/iac/factory_auth.tf @@ -1,5 +1,5 @@ locals { - factory_crowdsec_conf_sa_name = "factory-ansible-tool-crowdsec-traefik-plugin" + factory_crowdsec_conf_sa_name = "factory-ansible-tool-crowdsec-traefik-plugin" } diff --git a/hashicorp-vault/iac/modules/app_policy/main.tf b/hashicorp-vault/iac/modules/app_policy/main.tf index 6e7a34d..f93c0fb 100644 --- a/hashicorp-vault/iac/modules/app_policy/main.tf +++ b/hashicorp-vault/iac/modules/app_policy/main.tf @@ -178,6 +178,30 @@ data "vault_policy_document" "app" { path = "postgres/creds/${local.name}*" capabilities = ["read"] } + # Identifiants de SON compte de service MinIO, provisionné par le pipeline + # `minio` (tools/minio/iac/consumers.tf) dans l'espace Vault de MinIO. + # + # INCONDITIONNEL, et c'est voulu : le chemin porte le nom de l'app, donc cette + # règle ne peut jamais exposer que ses PROPRES clés. Une app qui ne stocke rien + # lit un chemin qui n'existe pas — une règle inerte, pas un privilège. + # + # Pourquoi ici plutôt que dans `kv_read_paths` de chaque app : savoir lire ses + # propres identifiants de stockage est une propriété de la PLATEFORME, pas une + # exception par application. `kv_read_paths` est la trappe pour un secret + # appartenant à une AUTRE app (les creds GCS de Longhorn pour l'ERP) ; y ranger + # un motif standard le rendrait invisible et obligerait à le redéclarer partout. + # Conséquence pratique : déclarer un consommateur MinIO se fait à UN seul + # endroit — `var.consumers` du pipeline minio. Aucune synchronisation à tenir. + rule { + path = "kvv2/data/minio/${local.name}/*" + capabilities = ["read", "list"] + } + rule { + # Le secret est écrit à `kvv2/minio/` (sans sous-chemin) : la règle + # ci-dessus couvre les descendants, celle-ci le document lui-même. + path = "kvv2/data/minio/${local.name}" + capabilities = ["read", "list"] + } # Extra shared paths this app's prod runtime may read (e.g. backup creds). dynamic "rule" { for_each = var.kv_read_paths @@ -204,6 +228,16 @@ data "vault_policy_document" "app_non_prod" { path = "postgres/creds/${each.key}*" capabilities = ["read"] } + # Même règle qu'en prod (voir le commentaire de vault_policy_document.app) : + # chaque instance lit les identifiants MinIO portant SON nom. + rule { + path = "kvv2/data/minio/${each.key}/*" + capabilities = ["read", "list"] + } + rule { + path = "kvv2/data/minio/${each.key}" + capabilities = ["read", "list"] + } } resource "vault_policy" "app_non_prod" { for_each = toset(local.non_prod_instances) diff --git a/hashicorp-vault/iac/terraform.tfvars b/hashicorp-vault/iac/terraform.tfvars index 14cdff4..b0921e7 100644 --- a/hashicorp-vault/iac/terraform.tfvars +++ b/hashicorp-vault/iac/terraform.tfvars @@ -24,13 +24,5 @@ applications = [ service_account_namespaces = ["tools"] }, { name = "prospection" }, - { - name = "kadans" - # Le pod lit les clés de SON compte de service MinIO, écrites par le pipeline - # `minio` dans son propre espace (minio/iac/consumers.tf). Le mécanisme est - # celui qui existait déjà pour l'ERP et les creds GCS de Longhorn — aucun - # module central n'a eu à changer. Le root de MinIO, lui, ne sort jamais du - # pipeline minio : l'app ne reçoit qu'une clé bornée à son bucket. - kv_read_paths = ["kvv2/data/minio/kadans"] - }, + { name = "kadans" }, ] diff --git a/minio/README.md b/minio/README.md index 2e8276d..8e757d4 100644 --- a/minio/README.md +++ b/minio/README.md @@ -106,16 +106,22 @@ demande aucune modification des modules Vault centraux. ``` Le plan crée une politique MinIO **bornée à ce bucket**, un compte de service, et écrit ses clés dans `kvv2/minio/mon-app`. -3. **La lecture** — dans `hashicorp-vault/iac/terraform.tfvars`, l'app déclare : - ```hcl - { name = "mon-app", kv_read_paths = ["kvv2/data/minio/mon-app"] } - ``` - `kv_read_paths` **existait déjà** (l'ERP s'en sert pour les creds GCS de - Longhorn) : rien à changer dans `app_policy` ni `app_roles`. +3. **La lecture** — *rien à faire.* Le module central `app_policy` accorde à + **toute** app la lecture de `kvv2/data/minio/`. La règle est + inconditionnelle et c'est voulu : le chemin porte le nom de l'app, donc elle + ne peut jamais exposer que ses propres clés ; une app qui ne stocke rien lit + un chemin qui n'existe pas. Puis, côté app : une `VaultStaticSecret` sur `kvv2/minio/` et l'injection des variables dans le Deployment. +> **Un seul endroit déclare un consommateur** : `var.consumers`, ici. Rien à +> synchroniser dans le tfvars central, donc rien à oublier. C'est la raison pour +> laquelle la règle vit dans le module plutôt que dans `kv_read_paths` — cette +> dernière est la trappe pour lire un secret appartenant à une AUTRE app (les +> creds GCS de Longhorn pour l'ERP) ; y ranger un motif standard le rendrait +> invisible et obligerait à le redéclarer à chaque fois. + ### Pourquoi les clés vivent ICI et pas chez l'app Seul ce pipeline possède les identifiants **root** de MinIO. Si chaque app créait