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
This commit is contained in:
2026-07-26 09:26:05 +02:00
co-authored by Claude Opus 5
parent 4ca4a05370
commit 91a0f09b49
4 changed files with 48 additions and 16 deletions
@@ -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/<app>` (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)