[Factory](../../../README.md) > [Doc](../../README.md) > [Runbooks](../README.md) > [Nouvelle application web](README.md) > **3. Vault plateforme** # 3. Déclarer l'app côté Vault plateforme > **Status:** ✅ Active > **Upstream:** [1. Dépôt Gitea](01-gitea-repo.md) > **Downstream:** [5. Terraform de l'app](05-app-terraform.md), [6. Workflows CI](06-ci-workflows.md) > **Related:** [2. Base de données](02-database.md) · [4. Chart Helm](04-helm-chart.md) · [Conventions de nommage](conventions.md) --- ## Summary Avant que la CI de l'app puisse gérer ses propres secrets, Vault doit connaître l'app : il lui faut un **rôle JWT de CI** (`gitea_cicd_`) pour que la pipeline s'authentifie, une **policy CI** (`-ops`) qui l'autorise à créer ses rôles Postgres/K8s, et une **policy runtime** (``) que le pod utilisera. Tout ça est généré par un module, depuis une seule ligne ajoutée côté plateforme dans le dépôt `tools`. ## Action Ajouter une entrée pour l'app au set `applications` de [`tools/hashicorp-vault/iac/terraform.tfvars`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/hashicorp-vault/iac/terraform.tfvars) : ```hcl applications = [ { name = "webapp" }, { name = "erp" }, { name = "" }, # ← ajouter # options possibles : # { # name = "" # ops_policies = ["factory__cf_r2_arcodange_tf"] # policies ops supplémentaires (ex. token Cloudflare) # service_account_names = ["cloudflared"] # SA additionnels autorisés à prendre la policy runtime # service_account_namespaces = ["tools"] # namespaces additionnels # }, ] ``` Puis pousser : la CI [`tools/.gitea/workflows/vault.yaml`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/.gitea/workflows/vault.yaml) applique le Terraform. ## Ce que ça crée Le module [`app_policy`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/hashicorp-vault/iac/modules/app_policy/main.tf) (appelé en `for_each` depuis [`main.tf`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/hashicorp-vault/iac/main.tf)) crée, **par app** : | Ressource Vault | Nom | À quoi ça sert | |---|---|---| | `vault_jwt_auth_backend_role` | `gitea_cicd_` | **Identité de la CI** : la pipeline de l'app s'y authentifie (mount `gitea_jwt`, `user_claim=email`, `bound_audiences=[gitea_app_id]`) | | `vault_policy` (ops) | `-ops` | Droits CI : créer `postgres/roles/*`, `auth/kubernetes/role/*`, éditer `kvv2//*`, lire les secrets de bootstrap google/gitea | | `vault_identity_group` | `-ops` | Groupe Vault rattachant les comptes Gitea à la policy ops | | `vault_policy` (runtime) | `` | Droits **du pod** : lire `kvv2/data//*` et `postgres/creds/*` | Extraits clés : ```hcl resource "vault_jwt_auth_backend_role" "gitea_jwt_cicd" { backend = data.vault_auth_backend.gitea_jwt.path # "gitea_jwt" role_name = "gitea_cicd_${local.name}" token_policies = concat(["default"], var.ops_policies) bound_audiences = [var.gitea_app_id] user_claim = "email" role_type = "jwt" } resource "vault_policy" "app" { # policy runtime du pod name = local.name # = "" policy = data.vault_policy_document.app.hcl # read kvv2/data//* + postgres/creds/* } ``` ## Prérequis plateforme (déjà là) Ces fondations vivent dans [`tools/hashicorp-vault/iac/main.tf`](https://gitea.arcodange.lab/arcodange-org/tools/src/branch/main/hashicorp-vault/iac/main.tf) et n'ont **pas** à être recréées : - mounts `kvv2` (KV v2), `postgres` (moteur de bases de données), `transit` (cache VSO), auth `kubernetes` ; - la **connexion Vault→Postgres** (`vault_database_secret_backend_connection`) qui se connecte à `pgbouncer.tools:5432/postgres` avec le compte `credentials_editor` (issu de l'[étape 2](02-database.md)) ; - `var.gitea_app_id` = l'id de l'application OAuth2 Gitea, réglé une fois au setup ([`gitea_oidc_auth.yml`](https://gitea.arcodange.lab/arcodange-org/factory/src/branch/main/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/tasks/gitea_oidc_auth.yml)). ## Pourquoi cette étape vient avant la CI de l'app > [!IMPORTANT] > C'est ici que `gitea_cicd_` **naît**. Le `iac/providers.tf` de l'app ([étape 5](05-app-terraform.md)) et le step `vault-action` du workflow ([étape 6](06-ci-workflows.md)) s'authentifient avec ce rôle. S'il n'existe pas encore, la toute première exécution de la CI de l'app échoue à l'authentification Vault. **Appliquer cette étape (et l'[étape 2](02-database.md)) avant de pousser le `iac/` de l'app.** ## Notes / contraintes - Découpage des privilèges : la policy **`-ops`** (CI, large) est distincte de la policy **``** (runtime, en lecture seule sur ses propres secrets). Le pod ne peut jamais créer de rôles. - `ops_policies` permet d'octroyer à la CI des droits transverses (ex. `cms` lit un token Cloudflare R2 via `factory__cf_r2_arcodange_tf`). ## Related - [2. Base de données](02-database.md) — fournit `credentials_editor`, réutilisé par la connexion Vault→Postgres. - [5. Terraform de l'app](05-app-terraform.md) — s'authentifie avec `gitea_cicd_` et crée `creds/` + le rôle K8s ``. - [6. Workflows CI](06-ci-workflows.md) — le step `vault-action` et `tofu apply` utilisent `gitea_cicd_`. - [4. Chart Helm](04-helm-chart.md) — le pod utilise la policy runtime `` via son ServiceAccount.