feat(minio) — un compte de service par app consommatrice, borné à son bucket #21
@@ -1,5 +1,5 @@
|
|||||||
locals {
|
locals {
|
||||||
factory_crowdsec_conf_sa_name = "factory-ansible-tool-crowdsec-traefik-plugin"
|
factory_crowdsec_conf_sa_name = "factory-ansible-tool-crowdsec-traefik-plugin"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,30 @@ data "vault_policy_document" "app" {
|
|||||||
path = "postgres/creds/${local.name}*"
|
path = "postgres/creds/${local.name}*"
|
||||||
capabilities = ["read"]
|
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).
|
# Extra shared paths this app's prod runtime may read (e.g. backup creds).
|
||||||
dynamic "rule" {
|
dynamic "rule" {
|
||||||
for_each = var.kv_read_paths
|
for_each = var.kv_read_paths
|
||||||
@@ -204,6 +228,16 @@ data "vault_policy_document" "app_non_prod" {
|
|||||||
path = "postgres/creds/${each.key}*"
|
path = "postgres/creds/${each.key}*"
|
||||||
capabilities = ["read"]
|
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" {
|
resource "vault_policy" "app_non_prod" {
|
||||||
for_each = toset(local.non_prod_instances)
|
for_each = toset(local.non_prod_instances)
|
||||||
|
|||||||
@@ -24,13 +24,5 @@ applications = [
|
|||||||
service_account_namespaces = ["tools"]
|
service_account_namespaces = ["tools"]
|
||||||
},
|
},
|
||||||
{ name = "prospection" },
|
{ name = "prospection" },
|
||||||
{
|
{ name = "kadans" },
|
||||||
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"]
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|||||||
+12
-6
@@ -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,
|
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`.
|
et écrit ses clés dans `kvv2/minio/mon-app`.
|
||||||
3. **La lecture** — dans `hashicorp-vault/iac/terraform.tfvars`, l'app déclare :
|
3. **La lecture** — *rien à faire.* Le module central `app_policy` accorde à
|
||||||
```hcl
|
**toute** app la lecture de `kvv2/data/minio/<son nom>`. La règle est
|
||||||
{ name = "mon-app", kv_read_paths = ["kvv2/data/minio/mon-app"] }
|
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
|
||||||
`kv_read_paths` **existait déjà** (l'ERP s'en sert pour les creds GCS de
|
un chemin qui n'existe pas.
|
||||||
Longhorn) : rien à changer dans `app_policy` ni `app_roles`.
|
|
||||||
|
|
||||||
Puis, côté app : une `VaultStaticSecret` sur `kvv2/minio/<app>` et l'injection
|
Puis, côté app : une `VaultStaticSecret` sur `kvv2/minio/<app>` et l'injection
|
||||||
des variables dans le Deployment.
|
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
|
### 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
|
Seul ce pipeline possède les identifiants **root** de MinIO. Si chaque app créait
|
||||||
|
|||||||
Reference in New Issue
Block a user