45 lines
3.2 KiB
SQL
45 lines
3.2 KiB
SQL
|
|
-- =============================================================================
|
|||
|
|
-- 03_service_bypass_policies.sql — разрешающие RLS-политики для служебных ролей
|
|||
|
|
-- =============================================================================
|
|||
|
|
-- Назначение (Путь А, Yandex Managed PG): заменяет атрибут BYPASSRLS, которого в
|
|||
|
|
-- управляемой базе НЕТ, на разрешающие политики. Три служебные роли (crm_admin_user,
|
|||
|
|
-- crm_migrator, crm_supplier_worker) получают cross-tenant доступ через политику
|
|||
|
|
-- srv_bypass; обычная роль crm_app_user её НЕ получает → остаётся изолированной по
|
|||
|
|
-- app.current_tenant_id. crm_audit_writer тоже НЕ получает (append-only, без bypass).
|
|||
|
|
--
|
|||
|
|
-- ЗАПУСК: на управляемом кластере ПОСЛЕ 00_create_roles.sql и накатки схемы,
|
|||
|
|
-- под ролью-владельцем (mdb_superuser-эквивалент), напр.:
|
|||
|
|
-- psql "host=<FQDN> port=6432 sslmode=verify-full ..." -U <owner> -d liderra \
|
|||
|
|
-- -f db/03_service_bypass_policies.sql
|
|||
|
|
--
|
|||
|
|
-- ИДЕМПОТЕНТНО (DROP POLICY IF EXISTS перед CREATE). Покрывает все таблицы с RLS,
|
|||
|
|
-- включая будущие. На самоуправляемой/dev базе, где ролей crm_* нет, — безопасный no-op.
|
|||
|
|
--
|
|||
|
|
-- ПРОВЕРЕНО на полигоне 26.06.2026 (44 политики; изоляция crm_app_user держится,
|
|||
|
|
-- crm_supplier_worker видит cross-tenant без ошибки):
|
|||
|
|
-- docs/superpowers/findings/2026-06-26-db-migration/etap1-sandbox-results.md (шов B).
|
|||
|
|
-- NB: часть политик tenant_isolation зовёт current_setting('app.current_tenant_id')
|
|||
|
|
-- без флага «,true»; srv_bypass (USING true) перекрывает это для служебных ролей —
|
|||
|
|
-- ошибки «нераспознанный параметр» нет (проверено). Желательный future-fix —
|
|||
|
|
-- привести все политики к current_setting(..., true).
|
|||
|
|
-- =============================================================================
|
|||
|
|
DO $$
|
|||
|
|
DECLARE t record;
|
|||
|
|
BEGIN
|
|||
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'crm_supplier_worker') THEN
|
|||
|
|
RAISE NOTICE 'Роли crm_* отсутствуют — srv_bypass пропущен (это dev/self-managed; запускать на управляемом кластере после 00_create_roles.sql).';
|
|||
|
|
RETURN;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
FOR t IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND rowsecurity LOOP
|
|||
|
|
EXECUTE format('DROP POLICY IF EXISTS srv_bypass ON public.%I;', t.tablename);
|
|||
|
|
EXECUTE format(
|
|||
|
|
'CREATE POLICY srv_bypass ON public.%I AS PERMISSIVE FOR ALL
|
|||
|
|
TO crm_admin_user, crm_migrator, crm_supplier_worker
|
|||
|
|
USING (true) WITH CHECK (true);', t.tablename);
|
|||
|
|
END LOOP;
|
|||
|
|
END $$;
|
|||
|
|
|
|||
|
|
-- Контроль: число созданных srv_bypass-политик (ожидается == числу RLS-таблиц, ~44).
|
|||
|
|
SELECT count(*) AS srv_bypass_policies FROM pg_policies WHERE policyname = 'srv_bypass';
|