MTES-MCT / metadata-postgresql

Plume : gestion des métadonnées du patrimoine PostgreSQL
https://mtes-mct.github.io/metadata-postgresql/
GNU Affero General Public License v3.0
1 stars 1 forks source link

Erreur bénigne à la restauration d'une base avec PlumePg #61

Closed alhyss closed 2 years ago

alhyss commented 2 years ago

Constaté sous PostgreSQL 14.2, comportement à confirmer avec les autres versions.

La restauration d'une base sur laquelle était installée PlumePg donne lieu à des erreurs sur la recréation des quatre politiques de sécurité niveau ligne définies sur la table z_plume.stamp_timestamp : timestamp_public_select, timestamp_owner_insert, timestamp_owner_update et timestamp_owner_delete. Elles sont en effet créées deux fois : une fois par le script de création de l'extension (commande CREATE EXTENSION plume_pg du script de restauration), puis une fois par des commandes CREATE POLICY explicites dans le script de restauration.

Exemple d'erreur :

pg_restore: création de POLICY « z_plume.stamp_timestamp timestamp_owner_update »
pg_restore: de l'entrée TOC 3456 ; 3256 296787 POLICY stamp_timestamp timestamp_owner_update postgres
pg_restore: erreur : could not execute query: ERREUR:  la politique « timestamp_owner_update » pour la table « stamp_timestamp » existe déjà
La commande était : CREATE POLICY timestamp_owner_update ON z_plume.stamp_timestamp FOR UPDATE USING (z_plume.is_relowner(relid)) WITH CHECK (z_plume.is_relowner(relid));

Ces erreurs sont sans conséquence, puisque les politiques de sécurité ont bien été créées et qu'il n'y aurait pas lieu de reproduire des modifications manuelles réalisées a posteriori. Mais il ne paraît pas normal que le script de restauration comprenne les commandes CREATE POLICY en question. Du point de vue des dépendances, elles fonctionnent comme les déclencheurs : elles ne sont pas marquées comme directement dépendantes de l'extension (au contraire du schéma, des tables, des types, etc.), mais elles ont une dépendance de type a / DEPENDENCY_AUTO vis-à-vis de leur relation, qui elle-même a une dépendance de type e / DEPENDENCY_EXTENSION vis-à-vis de l'extension. On pourrait donc s'attendre à ce que, comme les déclencheurs, pg_dump sache les identifier comme objets à ne pas recréer. En pratique et sans aucune certitude, la différence de traitement vient peut-être du fait que les politiques de sécurité ont aussi des dépendances de types n / DEPENDENCY_NORMAL sur les colonnes qui apparaissent dans les conditions de leurs clauses USING et WITH CHECK... mais ça n'est pas une bonne raison.

z_plume.stamp_timestamp n'est pas une table de configuration de l'extension, il faudrait voir si elles réagissent de la même façon.

J'ouvre une issue pour mémoire, mais je ne vois pas comment éviter ces erreurs. Comme c'est surtout le comportement de pg_dump qui me semble manquer de cohérence, je vais certainement faire un ticket d'anomalie et voir ce qui en sort.

Bien que ceci ne provoque pas d'erreur, il est également assez surprenant que le script de restauration contienne une commande ALTER TABLE z_plume.stamp_timestamp ENABLE ROW LEVEL SECURITY;, alors qu'il n'y a pas de commande ENABLE/DISABLE pour les déclencheurs et déclencheurs sur évènement, par exemple. Il n'est pas très intuitif que les déclencheurs soient recréés dans l'état défini par l'extension, comme le sont plus généralement tous les objets créés par l'extension hors contenu des tables identifiées comme tables de configuration de l'extension, tandis qu'une désactivation manuelle de la politique de sécurité serait préservée.

alhyss commented 2 years ago

En complément : avec certains objets (les déclencheurs, les fonctions, les vues matérialisées...), il existe une commande ALTER ... DEPENDS ON EXTENSION ... qui permet de rattacher explicitement l'objet à une extension afin qu'il soit automatiquement supprimé lorsqu'elle l'est. Les politiques de sécurité ne sont toutefois pas concernées.

alhyss commented 2 years ago

Après quelques fouilles...

Cette limitation est documentée (https://www.postgresql.org/docs/14/extend-extensions.html) : PostgreSQL does not currently support extension scripts issuing CREATE POLICY or SECURITY LABEL statements. These are expected to be set after the extension has been created. All RLS policies and security labels on extension objects will be included in dumps created by pg_dump.

Ticket de novembre 2021 sur le sujet : https://www.postgresql.org/message-id/CAANoKdbO=y0FT9fSzP24-kMf_A5y9xyujwJQk3=HgDynZYMAzQ@mail.gmail.com. Il explique bien le problème mais n'a jamais eu de réponse.

Une solution serait de définir un déclencheur sur z_plume.stamp_timestamp qui de provoque une erreur si le rôle qui exécute la commande n'est ni le propriétaire de stamp_timestamp ni le propriétaire de la table dont l'OID est OLD.relid / NEW.relid. Fonctionnellement, c'est équivalent, même si c'est moins propre, vraisemblablement moins performant et potentiellement moins sûr.

Je vais partir là-dessus pour le moment afin d'éviter l'erreur... et reviendrait aux politiques de sécurité le jour où PostgreSQL les prendra correctement en charge pour les extensions.

Pour mémoire :

ALTER TABLE z_plume.stamp_timestamp ENABLE ROW LEVEL SECURITY ;

-- Policy: timestamp_public_select

CREATE POLICY timestamp_public_select ON z_plume.stamp_timestamp
    FOR SELECT USING (True) ;

-- Policy: timestamp_owner_insert

CREATE POLICY timestamp_owner_insert ON z_plume.stamp_timestamp
    FOR INSERT WITH CHECK (z_plume.is_relowner(relid)) ;

-- Policy: timestamp_owner_update

CREATE POLICY timestamp_owner_update ON z_plume.stamp_timestamp
    FOR UPDATE USING (z_plume.is_relowner(relid))
    WITH CHECK (z_plume.is_relowner(relid)) ;

-- Policy: timestamp_owner_delete

CREATE POLICY timestamp_owner_delete ON z_plume.stamp_timestamp
    FOR DELETE USING (z_plume.is_relowner(relid)) ;
alhyss commented 2 years ago

C'est fait. public reçoit initialement SELECT, INSERT, UPDATE et DELETE sur stamp_timestamp. Le déclencheur stamp_timestamp_access_control veille à ce que seul le propriétaire de stamp_timestamp ou le propriétaire de la table concernée par un enregistrement puisse agir sur celui-ci.