DBAtlas · Atlas d'exploitation des bases de données

Mettre en place l'isolation des tenants avec la row-level security

PostgreSQLSécurité

Commande

ALTER TABLE app.orders ENABLE ROW LEVEL SECURITY;
-- Make the table owner subject to the policy too
ALTER TABLE app.orders FORCE ROW LEVEL SECURITY;

CREATE POLICY orders_tenant_isolation ON app.orders
  FOR ALL
  TO app_readwrite
  USING (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::int)
  WITH CHECK (tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::int);

-- The application sets the tenant at the start of every transaction (pooler-friendly)
BEGIN;
SET LOCAL app.tenant_id = '42';
SELECT * FROM app.orders;
COMMIT;

-- Configured policies
SELECT schemaname, tablename, policyname, roles, cmd, qual, with_check
FROM pg_policies
WHERE tablename = 'orders';

Ce que fait la commande

Active RLS sur la table et définit une politique qui filtre les lignes selon l'identifiant de tenant d'une variable de session (USING) et bloque les écritures pour un autre tenant (WITH CHECK).

Quand l'utiliser

Pour imposer l'isolation des données dans la base pour les applications multi-tenant au lieu de s'en remettre au code applicatif.

Attention

Les superutilisateurs et les rôles dotés de l'attribut BYPASSRLS contournent toujours les politiques ; le propriétaire de la table n'y est soumis qu'avec FORCE ROW LEVEL SECURITY. Avec RLS activé et aucune politique correspondante, le résultat est vide (sans erreur). current_setting(..., true) renvoie NULL lorsque la variable n'est pas définie ; NULLIF empêche la chaîne vide laissée après RESET d'échouer en ''::int. Les utilisateurs peuvent modifier app.tenant_id avec SET ; seule une couche applicative de confiance doit le définir et les utilisateurs finaux ne doivent pas avoir d'accès SQL. Avec un pooler en mode transaction, utilisez SET LOCAL au lieu de SET. Indexez la colonne tenant_id utilisée dans la politique. pg_dump échoue s'il est exécuté par un utilisateur soumis à RLS ; faites les sauvegardes avec un rôle BYPASSRLS.

Ouvrir dans DBAtlas →

Voir aussi