Sécurité au niveau des lignes dans Azure Cosmos DB for PostgreSQL

S’APPLIQUE À : Azure Cosmos DB for PostgreSQL (avec l’extension de base de données Citus pour PostgreSQL)

Les stratégies de sécurité au niveau des lignes PostgreSQL limitent les utilisateurs qui peuvent modifier ou accéder aux lignes de table. La sécurité au niveau des lignes peut être particulièrement utile dans un cluster multilocataire. Il permet aux locataires individuels d’avoir un accès SQL complet à la base de données tout en masquant les informations de chaque locataire à partir d’autres locataires.

Implémentation pour les applications multilocataires

Nous pouvons implémenter la séparation des données de locataire à l’aide d’une convention d’affectation de noms pour les rôles de base de données qui sont liés aux stratégies de sécurité au niveau des lignes de la table. Nous allons attribuer à chaque locataire un rôle de base de données dans une séquence numérotée : tenant1, tenant2, etc. Les locataires se connectent à Azure Cosmos DB for PostgreSQL à l’aide de ces rôles distincts. Les stratégies de sécurité au niveau des lignes peuvent comparer le nom du rôle aux valeurs de la colonne de distribution tenant_id pour décider s’il faut autoriser l’accès.

Voici comment appliquer l’approche sur une table d’événements simplifiée distribuée par tenant_id. Créez tout d’abord les rôlestenant1 et tenant2. Exécutez ensuite les commandes SQL suivantes en tant qu’utilisateur administrateur citus :

CREATE TABLE events(
  tenant_id int,
  id int,
  type text
);

SELECT create_distributed_table('events','tenant_id');

INSERT INTO events VALUES (1,1,'foo'), (2,2,'bar');

-- assumes that roles tenant1 and tenant2 exist
GRANT select, update, insert, delete
  ON events TO tenant1, tenant2;

En l’état, toute personne disposant d’autorisations de sélection pour cette table peut voir les deux lignes. Les utilisateurs de chaque locataire peuvent voir et mettre à jour la ligne de l’autre locataire. Nous pouvons résoudre la fuite de données avec des stratégies de sécurité de table au niveau des lignes.

Chaque stratégie se compose de deux clauses : USING et WITH CHECK. Lorsqu’un utilisateur tente de lire ou d’écrire des lignes, la base de données évalue chaque ligne par rapport à ces clauses. PostgreSQL vérifie les lignes de table existantes par rapport à l’expression spécifiée dans la clause USING et les lignes qui seraient créées via INSERT ou UPDATE par rapport à la clause WITH CHECK.

-- first a policy for the system admin "citus" user
CREATE POLICY admin_all ON events
  TO citus           -- apply to this role
  USING (true)       -- read any existing row
  WITH CHECK (true); -- insert or update any row

-- next a policy which allows role "tenant<n>" to
-- access rows where tenant_id = <n>
CREATE POLICY user_mod ON events
  USING (current_user = 'tenant' || tenant_id::text);
  -- lack of CHECK means same condition as USING

-- enforce the policies
ALTER TABLE events ENABLE ROW LEVEL SECURITY;

À présent, les rôles tenant1 et tenant2 obtiennent des résultats différents pour leurs requêtes :

Connecté en tant que locataire1 :

SELECT * FROM events;
┌───────────┬────┬──────┐
│ tenant_id │ id │ type │
├───────────┼────┼──────┤
│         1 │  1 │ foo  │
└───────────┴────┴──────┘

Connecté en tant que locataire2 :

SELECT * FROM events;
┌───────────┬────┬──────┐
│ tenant_id │ id │ type │
├───────────┼────┼──────┤
│         2 │  2 │ bar  │
└───────────┴────┴──────┘
INSERT INTO events VALUES (3,3,'surprise');
/*
ERROR:  new row violates row-level security policy for table "events_102055"
*/

Étapes suivantes