Поделиться через


Безопасность на уровне строк в Azure Cosmos DB для PostgreSQL

Область применения: Azure Cosmos DB для PostgreSQL (на базе расширения базы данных Citus до PostgreSQL)

В соответствии с принципами Политик безопасности на уровне строк PostgreSQL ограничивается круг пользователей, которые могут изменять или получать доступ к строкам таблицы. Безопасность на уровне строк особенно полезна в мультитенантном кластере. Это позволяет отдельным клиентам иметь полный доступ к базе данных SQL, скрывая сведения каждого клиента от других клиентов.

Реализация для мультитенантных приложений

Мы можем реализовать разделение данных клиента с помощью соглашения об именовании ролей базы данных, связанном с политиками безопасности на уровне строк таблицы. Мы назначим каждому клиенту роль базы данных в нумерованной последовательности: tenant1, tenant2и т. д. Клиенты будут подключаться к Azure Cosmos DB для PostgreSQL с помощью этих отдельных ролей. Политики безопасности на уровне строк могут сравнить имя роли со значениями в столбце распространения tenant_id, чтобы принять решение, следует ли разрешать доступ.

Далее представлено применение подхода к упрощенной таблице событий, распределенной по tenant_id. Сначала создайте роли tenant1 и tenant2. Затем выполните следующие команды SQL от имени администратора 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;

На данном этапе любой пользователь, имеющий разрешения на выбор для этой таблицы может видеть обе строки. Пользователи из любого клиента могут просматривать и обновлять строку другого клиента. Мы можем устранить утечку данных с помощью политик безопасности таблиц на уровне строк.

Каждая политика состоит из двух предложений: USING (Использование) и WITH CHECK (С проверкой). Когда пользователь пытается считывать или записывать строки, база данных оценивает каждую строку по этим предложениям. PostgreSQL проверяет существующие строки таблицы на соответствие выражению, указанному в предложении USING, и строки, которые будут созданы с помощью инструкции INSERT (Вставка) или UPDATE (Обновление) в предложении 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;

Теперь роли tenant1 и tenant2 получают различные результаты для своих запросов:

Подключено как tenant1:

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

Подключено как 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"
*/

Следующие шаги