Skip to main content
Crée une politique de ligne, c’est-à-dire un filtre servant à déterminer quelles lignes un utilisateur peut lire dans une table.
Les politiques de ligne n’ont de sens que pour les utilisateurs disposant d’un accès readonly. Si un utilisateur peut modifier une table ou copier des partitions d’une table à une autre, cela contourne les restrictions des politiques de ligne.
Syntaxe :
ParserRowPolicyNames accepte trois formes de regroupement (et non un produit cartésien complet) :
  1. Plusieurs noms, une cible — pol1, pol2 ON table1 crée chaque nom indiqué sur cette seule table (ou db.*).
  2. Un nom, plusieurs cibles — pol1 ON table1, table2 crée le même nom court sur chacune des cibles indiquées.
  3. Paires mixtes — p1 ON t1, p2 ON t2 crée chaque nom uniquement sur la cible qui lui est associée.
Une liste de plusieurs noms ne peut pas être combinée à une liste ON de plusieurs tables dans un même groupe : p1, p2 ON t1, t2 est rejetée. Après un groupe comportant plusieurs noms, vous ne pouvez pas non plus ajouter, dans la même instruction, un autre groupe name ON target séparé par des virgules. La clause facultative ON CLUSTER s’applique à l’ensemble de l’instruction (un seul nom de cluster). ClickHouse n’accepte pas de clause ON CLUSTER différente pour chaque nom de politique regroupé dans une seule création — exécutez des instructions CREATE ROW POLICY distinctes lorsque des politiques doivent être créées sur différents clusters. CREATE ROW POLICY requiert le privilège CREATE ROW POLICY sur la table sur laquelle la politique est créée. OR REPLACE supprime une politique existante portant le même nom, y compris les rôles auxquels elle s’applique ; il requiert donc en plus le privilège DROP ROW POLICY sur cette table. Le privilège DROP ROW POLICY est requis que la politique existe déjà ou non, de sorte que l’instruction ne peut pas servir à découvrir quelles politiques existent.

Plusieurs noms et tables

Valide :
Non valide :

Clause USING

Définit une condition de filtrage pour une table. Un utilisateur ne peut voir que les lignes pour lesquelles la condition est vraie (c’est-à-dire qu’elle renvoie une valeur non nulle). Cela revient à ajouter une condition WHERE supplémentaire à chaque requête que l’utilisateur exécute sur la table. Par exemple, la politique suivante restreint analyst_role aux lignes provenant de l’UE :
Avec cette politique, SELECT * FROM db.orders renvoie les mêmes lignes que le ferait SELECT * FROM db.orders WHERE region = 'EU'.

Clause TO

Dans la section TO, vous pouvez indiquer une liste d’utilisateurs et de rôles auxquels cette politique doit s’appliquer. Par exemple, CREATE ROW POLICY ... TO accountant, john@localhost. Le mot-clé ALL désigne tous les utilisateurs ClickHouse, y compris l’utilisateur courant. Le mot-clé ALL EXCEPT permet d’exclure certains utilisateurs de la liste de tous les utilisateurs, par exemple, CREATE ROW POLICY ... TO ALL EXCEPT accountant, john@localhost Les rôles indiqués dans la section TO, y compris ceux après ALL EXCEPT, sont comparés aux rôles activés de l’utilisateur courant (system.enabled_roles), et non à tous les rôles accordés à l’utilisateur. Par conséquent, SET ROLE peut modifier les politiques qui s’appliquent.

Clause AS

Il est possible d’avoir plusieurs politiques activées sur la même table pour un même utilisateur en même temps. Il faut donc un moyen de combiner les conditions de plusieurs politiques. Par défaut, les politiques sont combinées à l’aide de l’opérateur booléen OR. Par exemple, les politiques suivantes :
permettre à l’utilisateur peter de voir les lignes où b=1 ou c=2. La clause AS indique comment les politiques doivent être combinées avec d’autres politiques. Les politiques peuvent être permissives ou restrictives. Par défaut, les politiques sont permissives, ce qui signifie qu’elles sont combinées à l’aide de l’opérateur booléen OR. Une politique peut aussi être définie comme restrictive. Les politiques restrictives sont combinées à l’aide de l’opérateur booléen AND. Voici la formule générale :
Si aucune condition permissive ne s’applique, la première condition n’a aucun effet et seules les politiques restrictives décident, car access_control_improvements.users_without_row_policies_can_read_rows est activé par défaut. Un utilisateur auquel aucune condition ne s’applique voit donc toutes les lignes, et access_control_improvements.throw_on_unmatched_row_policies, désactivé par défaut, lève à la place une exception lorsque la table comporte des conditions et qu’aucune d’entre elles ne s’applique. Par exemple, les politiques suivantes :
permet à l’utilisateur peter de voir des lignes uniquement si b=1 AND c=2. Les politiques au niveau de la base de données sont combinées avec celles de la table. Par exemple, les politiques suivantes :
permettre à l’utilisateur peter de voir les lignes de table1 uniquement si b=1 AND c=2, bien que pour toute autre table de mydb, seule la politique b=1 s’appliquerait à l’utilisateur.

Tables qui lisent les données d’autres tables

Une politique de ligne filtre les lignes au point où les données sont effectivement lues. Une table Alias renvoie les lignes de sa table cible comme si elles lui appartenaient. Les politiques de ligne de la table cible s’appliquent donc aussi aux lectures effectuées via l’alias, conjointement avec celles de l’alias lui-même, selon un AND logique. Une table Merge applique les politiques des tables qu’elle lit. Il existe toutefois une exception : lorsqu’une table correspondante lit des données à distance, comme une table Distributed, le serveur distant traite la requête avant que la politique ne soit appliquée, car celle-ci intervient au-dessus de l’opération de lecture de la table, et non au point où les données sont lues. Une telle requête peut échouer si elle agrège les données sans sélectionner les colonnes utilisées par la politique. Elle peut aussi renvoyer moins de lignes que la politique ne l’autorise si le serveur distant applique un ORDER BY ... LIMIT à des lignes que la politique aurait masquées. Définissez plutôt la politique sur les tables locales sous-jacentes de chaque serveur distant. Ce comportement ne s’applique pas à toutes les tables qui lisent les données d’une autre table. Une table Buffer et une vue matérialisée qui lisent les données par l’intermédiaire de leur table de destination ou de leur table cible n’héritent pas des politiques de ligne de cette table : la politique est définie à partir du schéma de la table cible et, dans le cas d’une vue avec SQL SECURITY DEFINER, elle est évaluée pour un autre utilisateur que celui qui effectue la lecture. Dans ces cas, définissez la politique sur la table que les utilisateurs interrogent réellement.

Tables Distributed et tables s’appuyant sur des serveurs distants

Une politique de ligne filtre les lignes là où les données de la table sont effectivement lues. Une table qui délègue la lecture à des serveurs distants, telle qu’une table Distributed ou un wrapper qui s’appuie sur une telle table (par exemple, une vue matérialisée avec une cible Distributed), ne transmet que le texte de la requête aux serveurs distants et ne peut pas appliquer le filtre de la politique à la lecture distante. Pour éviter que le filtre soit ignoré silencieusement, les requêtes vers une telle table effectuées par les utilisateurs auxquels la politique s’applique sont rejetées avec une erreur ILLEGAL_PREWHERE. Définissez plutôt la politique sur les tables locales sous-jacentes de chaque serveur distant ; elle y est appliquée lorsque la requête transmise les lit :
Cela fonctionne tant que la requête est transmise sous forme de texte, ce qui est le comportement par défaut. Avec serialize_query_plan = 1, l’initiateur transmet à la place un plan de lecture déjà construit. Un serveur distant qui exécute un tel plan n’applique pas ses propres politiques de ligne : la lecture d’une table Distributed via local_table renvoie donc des lignes non filtrées. Conservez serialize_query_plan = 0 pour les utilisateurs dont les politiques de ligne doivent être appliquées. Consultez l’issue n° 112891.

Tables Join

Une table Join est une table de hachage préconstruite qu’un JOIN ou un joinGet lit telle quelle ; ses lignes ne peuvent donc pas y être filtrées. Une politique définie sur une telle table, y compris une politique ON db.* portant sur l’ensemble de la base de données, filtre un simple SELECT sur la table, mais tant qu’elle s’applique, les requêtes JOIN et joinGet sur cette table échouent avec l’erreur ACCESS_DENIED.

Clause ON CLUSTER

Permet de créer des politiques sur un cluster, voir DDL distribué. C’est également une méthode pratique pour créer la politique sur les tables locales de chaque serveur du cluster.

Exemples

CREATE ROW POLICY filter1 ON mydb.mytable USING a<1000 TO accountant, john@localhost CREATE ROW POLICY filter2 ON mydb.mytable USING a<1000 AND b=5 TO ALL EXCEPT mira CREATE ROW POLICY filter3 ON mydb.mytable USING 1 TO admin CREATE ROW POLICY filter4 ON mydb.* USING 1 TO admin