CodeGym /Cours /SQL SELF /Contrôle d'accès au niveau des lignes : Row-Level Securit...

Contrôle d'accès au niveau des lignes : Row-Level Security (RLS)

SQL SELF
Niveau 47 , Leçon 3
Disponible

Si les droits au niveau des rôles et des tables, c'est "le vigile à la porte d'entrée", alors Row-Level Security, c'est le vigile perso qui vérifie si chaque utilisateur peut entrer dans chaque pièce du bâtiment.

RLS permet de faire en sorte qu'un utilisateur ne bosse que sur les lignes de la table auxquelles il a droit. Par exemple :

  • Dans une boutique en ligne, le manager doit voir uniquement ses propres commandes.
  • Dans une plateforme CRM, un employé ne voit que les clients de son équipe.
  • Dans un système bancaire, le client doit avoir accès uniquement à ses propres comptes.

Comment marche RLS

Le principe de RLS repose sur la notion de politiques d'accès. Les politiques définissent quelles lignes d'une table sont visibles pour un rôle ou un utilisateur, et lesquelles peuvent être modifiées (INSERT, UPDATE, DELETE).

Par défaut, RLS est désactivé pour toutes les tables, et tu dois l'activer manuellement.

Activer RLS pour une table

Créons une table orders où on stocke les commandes de la boutique en ligne :

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    product_name TEXT NOT NULL,
    price NUMERIC NOT NULL
);

Ajoutons quelques données de test :

INSERT INTO orders (user_id, product_name, price)
VALUES
    (1, 'Smartphone', 500),
    (2, 'Ordinateur portable', 1000),
    (1, 'Écouteurs', 100),
    (3, 'Clavier', 50);

Maintenant, on active RLS pour cette table :

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

Qu'est-ce qu'on vient de faire ? On a activé le mécanisme RLS, mais aucune politique n'est encore définie. Tant que tu n'as pas créé de politiques, RLS n'a en fait aucun effet sur l'accès à la table.

Créer une politique d'accès

Pour ajouter des règles de gestion d'accès, on utilise la commande :

CREATE POLICY nom_politique
ON table
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO rôle
USING (condition_acces)
WITH CHECK (condition_verification);
  • FOR : définit pour quelles opérations la politique s'applique (SELECT, INSERT, UPDATE, DELETE). Si tu ne mets rien, la politique s'applique à toutes les opérations.
  • TO : indique pour quels rôles la politique est active. Si tu ne précises pas, ça s'applique à tous les rôles.
  • USING : définit la condition pour que les lignes soient visibles par l'utilisateur.
  • WITH CHECK : définit la condition de vérification pour les opérations INSERT et UPDATE.

Exemple : accès uniquement à ses propres commandes

Créons une politique qui permet aux utilisateurs de voir uniquement leurs propres commandes. Imaginons que l'identifiant de l'utilisateur courant correspond à user_id dans la table :

CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);

Qu'est-ce qui se passe ici ?

  • La politique s'appelle user_can_view_own_orders.
  • Elle s'applique à l'opération SELECT.
  • Seules les lignes où user_id correspond à l'identifiant de l'utilisateur courant (current_user) sont visibles.

Donc, si tu es connecté en tant qu'utilisateur avec user_id = 1, tu ne verras que tes propres commandes.

Vérifier le fonctionnement de RLS

Créons deux utilisateurs : user1 et user2.

CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';

On donne aux rôles l'accès à la table :

GRANT SELECT ON orders TO user1, user2;

Maintenant, on se connecte en tant que user1 et on tente une requête :

SELECT * FROM orders;

Résultat : tu ne verras que les lignes où user_id = 1.

Politiques pour INSERT

Disons qu'on veut autoriser les utilisateurs à ajouter uniquement leurs propres commandes (c'est-à-dire que la ligne avec user_id doit correspondre à l'identifiant de l'utilisateur courant).

On crée une politique sur INSERT :

CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);

Maintenant, si user1 essaie d'ajouter une commande où user_id n'est pas égal à 1, la requête échouera avec une erreur.

Politiques pour UPDATE et DELETE

De la même façon, tu peux créer des politiques pour modifier et supprimer des données. Par exemple :

Pour mettre à jour ses propres données :

CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);

Pour supprimer ses propres données :

CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);

Utiliser plusieurs politiques

Tu peux créer plusieurs politiques pour une même table. Elles seront toutes appliquées en même temps. Par exemple, si plusieurs règles s'appliquent à un rôle, PostgreSQL les vérifie toutes (logique ET).

Vérification et debug de RLS

Pour vérifier quelles politiques sont définies pour une table, utilise la commande :

\di+ nom_table

Si tu veux désactiver temporairement RLS (par exemple pour un admin), fais :

ALTER TABLE orders DISABLE ROW LEVEL SECURITY;

Le rôle admin SUPERUSER n'est pas limité par RLS par défaut, donc il peut voir toutes les données.

Erreurs fréquentes lors de la config de RLS

Des erreurs peuvent arriver si tu oublies de :

  • Activer RLS avec la commande ALTER TABLE ... ENABLE ROW LEVEL SECURITY.
  • Définir les politiques nécessaires pour toutes les opérations (SELECT, INSERT, UPDATE, DELETE).
  • Bien préciser la condition dans USING et WITH CHECK. Par exemple, si tu ne vérifies pas user_id, tu risques d'ouvrir l'accès à toutes les lignes par erreur.

Row-Level Security, c'est un des outils de sécurité les plus puissants dans PostgreSQL. Ça te permet de gérer l'accès au niveau de la ligne et d'automatiser la gestion des droits, ce qui est super important pour les applis complexes avec de grosses exigences de protection des données.

2
Mission
SQL SELF, niveau 47, leçon 3
Bloqué
Politiques complexes : accès en lecture et en modification
Politiques complexes : accès en lecture et en modification
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION