fix(pgbouncer,vault) — ce qu'un client laisse sur une connexion, le suivant n'en hérite plus #25
Merged
arcodange
merged 2 commits from 2026-07-29 20:22:14 +02:00
arcodange/fuite-set-role into main
2
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7d13a8d764 |
doc(pgbouncer) — la version mesurée n'était pas la déployée, et DISCARD ALL a un prix
Trois corrections au raisonnement, toutes issues d'une contre-vérification qui a refait les mesures au lieu de les relire. 1. La mesure invoquait pgbouncer 1.25.2 « la version en prod ». Le pod tourne 1.23.1 (ghcr.io/icoretech/pgbouncer-docker:1.23.1-fixed, chart 2.3.1, up 133 j). Tout a été rejoué sur 1.23.1 avec la ConfigMap extraite du cluster : les conclusions tiennent, mais la preuve invoquée portait sur autre chose. 2. La portée de la fuite était laissée en suspens, donc lue au pire. Les pools sont partitionnés par (base, utilisateur) — 210 pools, aucun mélange. Le seul héritier possible du SET ROLE de kadans-api est kadans-api. Défaut d'hygiène, pas brèche inter-applications. Le dire baisse la gravité, et c'est plus utile qu'une alarme vague. 3. ⚠ Le point manquant, et c'est l'inverse de ce qu'on croyait : DISCARD ALL rend la protection de db.go STRICTEMENT PLUS FRAGILE. Aujourd'hui (DEALLOCATE ALL) elle survivrait à un passage en transaction pooling ; après, non — le SET ROLE d'AfterConnect est effacé entre deux transactions, et poserRoleProprietaire ne peut pas le voir puisqu'il relit current_role à l'ouverture. Sans danger tant que pool_mode reste `session` (le défaut, non déclaré) — mais c'est précisément le genre de trappe qui se referme des mois plus tard sur quelqu'un qui optimise. Les quatre combinaisons sont mesurées et écrites au-dessus de la ligne. La ceinture Vault couvre ce cas (un défaut de rôle survit à DISCARD ALL), mais seulement au renouvellement des baux. D'où l'avertissement explicite. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK |
||
|
|
1dd905dc5f |
fix(pgbouncer,vault) — ce qu'un client laisse sur une connexion, le suivant n'en hérite plus
Un pgbouncer partagé n'a qu'UNE barrière entre deux clients d'un même pool : le
`server_reset_query`. La nôtre ne nettoyait que les requêtes préparées. Tout le
reste de l'état de session — variables, LISTEN, tables TEMP, et le rôle
courant — traversait la déconnexion et tombait dans les mains du client suivant.
CE QUI A ÉTÉ MESURÉ, PAS SUPPOSÉ
pgbouncer 1.25.2 (la version qui tourne), monté avec NOTRE configuration :
`pool_mode = session`, `server_reset_query = DEALLOCATE ALL`,
`server_reset_query_always = 1`, `default_pool_size = 1`. Le client 1 pose son
état puis se déconnecte ; le client 2, qui n'a rien demandé, arrive.
DEALLOCATE ALL (l'existant) client 2 hérite : work_mem=17MB, 1 LISTEN,
la table TEMP du client 1, et son SET ROLE —
au point de créer des tables appartenant à un
rôle qui n'est pas le sien.
DISCARD ALL (ce commit) client 2 obtient work_mem=4MB, 0 LISTEN, pas
de table TEMP, et son PROPRE rôle.
POURQUOI `DISCARD ALL` NE PEUT RIEN CASSER
C'est le défaut de pgbouncer, et un sur-ensemble STRICT des deux valeurs qui
l'ont précédé ici : il contient `DEALLOCATE ALL` — donc le correctif crowdsec de
|