Le filet de propriété ne rattrape que les TABLES — l'angle mort est déjà occupé (citext, pgcrypto) #27

Open
opened 2026-07-28 22:52:41 +02:00 by arcodange · 0 comments
Owner

Le constat

Deux mécanismes prétendent rendre au rôle stable ce qu'un rôle éphémère a créé. Aucun ne fonctionne complètement.

1. Le REASSIGN de Vault ne tourne pas dans la bonne base

hashicorp-vault/iac/modules/app_roles/main.tf :

revocation_statements = [
  "REASSIGN OWNED BY \"{{name}}\" TO ${local.owner_role};",  # reassign must be executed in the
                                                             # database where the reassigned
                                                             # objects are - TODO
]

Le rôle Vault est lié à db_name = "postgres" : une seule connexion, vers la base postgres. Or REASSIGN OWNED BY n'agit que dans la base courante. Les objets de kadans, crowdsec, plausible… ne sont jamais réattribués. Le TODO l'avoue ; il est toujours là.

2. Le CronJob pg-fix-table-ownership ne regarde que pg_tables

(kube-system, 03:00 — source : dépôt factory, ansible/arcodange/factory/playbooks/setup/postgres.yml)

FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'
LOOP EXECUTE format('ALTER TABLE public.%I OWNER TO %I', r.tablename, '$role');

Vues, vues matérialisées, séquences autonomes, types, fonctions, schémas et extensions lui échappent.

L'angle mort n'est pas théorique — il est déjà occupé

Recensement de toutes les bases le 2026-07-28 (pg_class + pg_proc + pg_type + pg_namespace + pg_extension) :

crowdsec            : RIEN
dance-lessons-coach : RIEN
erp                 : RIEN
erp-sandbox         : RIEN
gitea               : RIEN
kadans              : extension=2 (v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219)
plausible           : RIEN
webapp              : RIEN
citext   | v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219
pgcrypto | v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219
plpgsql  | postgres

Deux extensions de la base kadans appartiennent à un rôle éphémère que le CronJob ne verra jamais. Conséquence limitée aujourd'hui (le propriétaire d'une extension ne compte que pour ALTER/DROP EXTENSION) — mais c'est la démonstration que le filet a des trous, et une future migration créant une vue ou une séquence tomberait dedans avec des conséquences, elles, immédiates.

Ce rôle fait par ailleurs partie des 997 qui ne sont jamais DROPés (issue #26) : personne ne le supprimera, donc personne ne butera sur l'erreur qui révélerait le problème.

Le filet complet

REASSIGN OWNED BY <éphémère> TO <app>_role exécuté dans la base de l'application — une seule instruction qui couvre tout ce que le ALTER TABLE en boucle rate.

Deux voies, non exclusives :

  1. Vault : une vault_database_secret_backend_connection par base applicative, pour que la révocation puisse jouer le REASSIGN au bon endroit. C'est la voie propre (au moment du bail, pas 24 h après) mais elle touche le module partagé par les cinq apps.
  2. Le CronJob : remplacer la boucle pg_tables par un REASSIGN OWNED BY sur chaque rôle v-kubernet-% encore existant, dans chaque base. Plus simple, mais reste un rattrapage a posteriori.

Cadeau du PR #25 : ALTER ROLE "{{name}}" SET ROLE <app>_role fait naître les nouveaux objets directement chez le rôle stable. Une fois les baux renouvelés, le CronJob et le REASSIGN deviennent des filets pour l'existant, plus des béquilles pour le quotidien. Cette issue reste ouverte pour l'existant et pour les clients qui n'obtiennent pas leurs identifiants de Vault.

Le CronJob vit dans le dépôt factory (playbook Ansible), pas ici : sa correction se déploie par un run Ansible, d'où l'issue plutôt qu'un commit.

## Le constat Deux mécanismes prétendent rendre au rôle stable ce qu'un rôle éphémère a créé. **Aucun ne fonctionne complètement.** ### 1. Le `REASSIGN` de Vault ne tourne pas dans la bonne base `hashicorp-vault/iac/modules/app_roles/main.tf` : ```hcl revocation_statements = [ "REASSIGN OWNED BY \"{{name}}\" TO ${local.owner_role};", # reassign must be executed in the # database where the reassigned # objects are - TODO ] ``` Le rôle Vault est lié à `db_name = "postgres"` : une seule connexion, vers la base `postgres`. Or `REASSIGN OWNED BY` n'agit **que dans la base courante**. Les objets de `kadans`, `crowdsec`, `plausible`… ne sont jamais réattribués. Le `TODO` l'avoue ; il est toujours là. ### 2. Le CronJob `pg-fix-table-ownership` ne regarde que `pg_tables` (`kube-system`, 03:00 — source : dépôt `factory`, `ansible/arcodange/factory/playbooks/setup/postgres.yml`) ```sql FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP EXECUTE format('ALTER TABLE public.%I OWNER TO %I', r.tablename, '$role'); ``` Vues, vues matérialisées, séquences autonomes, types, fonctions, schémas et **extensions** lui échappent. ## L'angle mort n'est pas théorique — il est déjà occupé Recensement de toutes les bases le 2026-07-28 (pg_class + pg_proc + pg_type + pg_namespace + pg_extension) : ``` crowdsec : RIEN dance-lessons-coach : RIEN erp : RIEN erp-sandbox : RIEN gitea : RIEN kadans : extension=2 (v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219) plausible : RIEN webapp : RIEN ``` ``` citext | v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219 pgcrypto | v-kubernet-kadans-4t59i0edKizfogcwiaXn-1784895219 plpgsql | postgres ``` Deux extensions de la base `kadans` appartiennent à un rôle éphémère que le CronJob ne verra jamais. Conséquence limitée aujourd'hui (le propriétaire d'une extension ne compte que pour `ALTER`/`DROP EXTENSION`) — mais c'est la démonstration que le filet a des trous, et une future migration créant une **vue** ou une **séquence** tomberait dedans avec des conséquences, elles, immédiates. Ce rôle fait par ailleurs partie des 997 qui ne sont jamais `DROP`és (issue #26) : personne ne le supprimera, donc personne ne butera sur l'erreur qui révélerait le problème. ## Le filet complet `REASSIGN OWNED BY <éphémère> TO <app>_role` exécuté **dans la base de l'application** — une seule instruction qui couvre tout ce que le `ALTER TABLE` en boucle rate. Deux voies, non exclusives : 1. **Vault** : une `vault_database_secret_backend_connection` par base applicative, pour que la révocation puisse jouer le `REASSIGN` au bon endroit. C'est la voie propre (au moment du bail, pas 24 h après) mais elle touche le module partagé par les cinq apps. 2. **Le CronJob** : remplacer la boucle `pg_tables` par un `REASSIGN OWNED BY` sur chaque rôle `v-kubernet-%` encore existant, dans chaque base. Plus simple, mais reste un rattrapage a posteriori. ⚠ **Cadeau du PR #25** : `ALTER ROLE "{{name}}" SET ROLE <app>_role` fait naître les nouveaux objets **directement** chez le rôle stable. Une fois les baux renouvelés, le CronJob et le `REASSIGN` deviennent des filets pour l'existant, plus des béquilles pour le quotidien. Cette issue reste ouverte pour l'existant et pour les clients qui n'obtiennent pas leurs identifiants de Vault. Le CronJob vit dans le dépôt `factory` (playbook Ansible), pas ici : sa correction se déploie par un run Ansible, d'où l'issue plutôt qu'un commit.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/tools#27