Files
portal/db/03_service_bypass_policies.sql
T

45 lines
3.2 KiB
SQL
Raw Normal View History

-- =============================================================================
-- 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';