Compartilhar via


Segurança no nível de linha no Azure Cosmos DB for PostgreSQL

APLICA-SE AO: Azure Cosmos DB for PostgreSQL (da plataforma da extensão de dados Citus para PostgreSQL)

As políticas de segurança no nível de linha do PostgreSQL restringem quais usuários podem modificar ou acessar quais linhas da tabela. A segurança no nível de linha pode ser especialmente útil em um cluster multilocatário. Ela permite que locatários individuais tenham acesso SQL completo ao banco de dados e, ao mesmo tempo, ocultam as informações de cada locatário para outros locatários.

Implementação para aplicativos multilocatários

Podemos implementar a separação de dados de locatário, usando uma convenção de nomenclatura para funções do banco de dados vinculadas às políticas de segurança no nível de linha da tabela. Atribuiremos a cada locatário uma função do banco de dados em uma sequência numerada: tenant1, tenant2 etc. Os locatários serão conectados ao Azure Cosmos DB for PostgreSQL usando essas funções separadas. As políticas de segurança no nível de linha podem comparar o nome da função com os valores tenant_id na coluna de distribuição, para decidir se permitem o acesso.

Veja como aplicar a abordagem em uma tabela de eventos simplificada distribuída por tenant_id. Primeiro, crie as funçõestenant1 e tenant2. Em seguida, execute os seguintes comandos SQL como o usuário administrador 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;

Tal como está, qualquer pessoa com as permissões selecionadas para essa tabela pode ver ambas as linhas. Usuários de qualquer um dos locatários podem ver e atualizar a linha do outro locatário. Podemos resolver o vazamento de dados com políticas de segurança de tabela no nível de linha.

Cada política consiste em duas cláusulas: USING e WITH CHECK. Quando um usuário tenta ler ou gravar linhas, o banco de dados avalia cada linha em relação a essas cláusulas. O PostgreSQL verifica as linhas existentes da tabela em relação à expressão especificada na cláusula USING e as linhas que seriam criadas com o INSERT ou UPDATE na cláusula 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;

Agora, as funções tenant1 e tenant2 recebem resultados diferentes para as consultas:

Conectado como tenant1:

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

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

Próximas etapas