Condividi tramite


Sicurezza a livello di riga in Azure Cosmos DB for PostgreSQL

SI APPLICA A: Azure Cosmos DB for PostgreSQL (con tecnologia basata sull'estensione di database Citus per PostgreSQL)

I criteri di sicurezza a livello di riga di PostgreSQL limitano gli utenti che possono modificare o accedere a date righe della tabella. La sicurezza a livello di riga può essere particolarmente utile in un cluster multi-tenant. Consente ai singoli tenant di avere un accesso SQL completo al database nascondendo le informazioni di ogni tenant agli altri tenant.

Implementazione per app multi-tenant

È possibile implementare la separazione dei dati del tenant usando una convenzione di denominazione per i ruoli del database che si collega ai criteri di sicurezza a livello di riga della tabella. Si assegnerà a ogni tenant un ruolo del database in una sequenza numerata: tenant1, tenant2 e così via. I tenant si connetteranno ad Azure Cosmos DB for PostgreSQL usando questi ruoli separati. I criteri di sicurezza a livello di riga possono confrontare il nome del ruolo con i valori nella colonna di distribuzione tenant_id per decidere se consentire l'accesso.

Ecco come applicare l'approccio a una tabella eventi semplificata distribuita da tenant_id. Creare prima di tutto i ruoli tenant1 e tenant2. Quindi,eseguire i comandi SQL seguenti come utente amministratore 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;

In questo modo, chiunque disponga delle autorizzazioni di selezione per questa tabella può visualizzare entrambe le righe. Gli utenti di entrambi i tenant possono visualizzare e aggiornare la riga dell'altro tenant. È possibile risolvere la perdita di dati con i criteri di sicurezza delle tabelle a livello di riga.

Ogni criterio è costituito da due clausole: USING e WITH CHECK. Quando un utente tenta di leggere o scrivere righe, il database valuta ogni riga rispetto a queste clausole. PostgreSQL controlla le righe di tabella esistenti rispetto all'espressione specificata nella clausola USING e le righe che verrebbero create tramite INSERT o UPDATE rispetto alla clausola 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;

Adesso, i ruoli tenant1 e tenant2 ottengono risultati diversi per le query:

Connesso come tenant1:

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

Connesso come tenant2:

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"
*/

Passaggi successivi