Оператор рлс условия и привилегии

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Row-Level Security (RLS) — это технология безопасности на уровне строк данных, позволяющая ограничивать доступ пользователей к конкретным строкам таблиц в зависимости от контекста их сессии или роли․ В экосистеме Oracle эта технология реализуется через Virtual Private Database (VPD) и пакет DBMS_RLS․ Статья подробно рассматривает условия срабатывания политик, необходимые привилегии, архитектуру предикатов и нюансы администрирования․

Архитектура и Основные Компоненты

Механизм RLS (VPD) работает на уровне ядра базы данных, прозрачно модифицируя SQL-запросы пользователей путем добавления динамически генерируемых предикатов (условий WHERE)․

Ключевые элементы:

  • Application Context (Контекст приложения): Набор пар «имя-значение», доступных в сессии․ Используется политиками для принятия решений (например, CLIENT_IDENTIFIER, USER_ID, DEPARTMENT_ID)․
  • Policy Function (Функция политики): PL/SQL-функция, возвращающая строку-предикат (например, 'DEPT_ID = SYS_CONTEXT(''APP_CTX'', ''DEPT_ID'')')․
  • DBMS_RLS Package: Административный интерфейс для привязки политик к таблицам/представлениям․ Доступен только в Enterprise Edition․

Условия Срабатывания Политик (Policy Conditions)

Политики RLS не применяются ко всем пользователям и операциям безусловно․ Существует четкая иерархия проверок:

  1. Проверка привилегий на объект: Сначала Oracle проверяет стандартные привилегии (SELECT, INSERT, UPDATE, DELETE) на таблицу․ Если их нет — запрос завершается ошибкой до вызова RLS․
  2. Проверка владельца и BYPASSRLS: По умолчанию политики не применяются к:
    • Владельцу таблицы (схеме-владельцу объекта)․
    • Пользователям с системной привилегией EXEMPT ACCESS POLICY (ранее известной как BYPASSRLS)․
    • Пользователям с ролью DBA (если им ена EXEMPT ACCESS POLICY)․
  3. Тип операции (Statement Types): Политика может быть назначена на конкретные операции:
    • FOR SELECT
    • FOR INSERT
    • FOR UPDATE
    • FOR DELETE
    • FOR ALL (по умолчанию, если не указано иное)․
  4. Вычисление предиката: Если проверки пройдены, для каждой применимой политики вызывается функция-политика․ Возвращаемый предикат конкатенируется к исходному запросу через AND․

Пример сложного предиката

Функция политики может возвращать выражения произвольной сложности, включая подзапросы:

AND (
 512 IN (SELECT id_user FROM v_admin_users WHERE id_department = 255)
 OR
 512 IN (SELECT id_user FROM v_bypass_rls)
)

Примечание: Предикаты должны быть детерминированными в рамках одного выполнения запроса для корректной работы кэша курсоров (если используется STATIC или CONTEXT_SENSITIVE типы политик)․

Привилегии и Роли для Администрирования RLS

Управление политиками требует высоких привилегий, разделенных на уровни ответственности․

Системные привилегии

Привилегия Описание Кому назначается
EXECUTE ON DBMS_RLS Базовая привилегия для вызова процедур добавления/удаления/включения политик (ADD_POLICY, DROP_POLICY, ENABLE_POLICY)․ Разработчикам БД, админам безопасности приложений․
EXEMPT ACCESS POLICY Полный обход всех политик VPD/RLS для всех таблиц во всех схемах․ Опасно! Только супер-администраторам (SYS, SYSTEM), утилитам экспорта/импорта (Data Pump), DBA для аварийного доступа․
ALTER ANY SECURITY POLICY Разрешает изменение политик безопасности в любой схеме․ Предназначена для Security Policy Administrator (Диспетчера политик безопасности)․ Специализированной роли безопасности (Security Officer), не DBA․

Объектные привилегии

  • Для создания политики на чужой таблице требуется SELECT на эту таблицу (для чтения метаданных) + EXECUTE ON DBMS_RLS․
  • Функция-политика выполняется с правами создателя политики (Definer’s Rights), а не вызывающего пользователя․ Поэтому создателю политики нужны права на объекты, используемые внутри функции (доступ к контекстам, таблицам справочникам и т․д․)․

Типы Политик и Производительность (Policy Types)

Выбор типа политики критически влияет на производительность, так как определяет частоту вызова функции-политики․

  • DYNAMIC (По умолчанию): Функция вызывается при каждом выполнении запроса (parse/execute)․ Максимальная гибкость, накладные расходы на CPU․
  • STATIC: Предикат вычисляется один раз при первом парсинге и кэшируется в SGA․ Подходит, если предикат зависит только от неизменяемых в рамках сессии атрибутов (например, фиксированная роль пользователя)․ Не подходит, если контекст меняется часто․
  • CONTEXT_SENSITIVE: Предикат кэшируется до изменения контекста приложения (Namespace/Attribute)․ Оптимальный баланс для большинства приложений с DBMS_SESSION․SET_CONTEXT․
  • SHARED_CONTEXT_SENSITIVE / SHARED_STATIC: Варианты для совместного использования курсоров между пользователями с одинаковым контекстом (для пулов соединений)․

Временное Отключение RLS (Runtime Control)

В некоторых сценариях (пакетная загрузка данных, отчеты администратора, отладка) требуется отключить RLS для текущей сессии без выдачи привилегии EXEMPT ACCESS POLICY․

Стандартные подходы:

  1. Пакетная переменная-флаг (Application Level): В коде приложения заводится пакет (например, PRVD_PKG) с переменной outRLS NUMBER := 0․
    -- В функции политики:
    IF PRVD_PKG․outRLS = 1 THEN
     RETURN NULL; -- Предикат не добавляется
    END IF;

    Переменная устанавливается в 1 перед критической операцией и сбрасывается в 0 в процедурах-обертках StartPrvd92 / FinishPrvd (или через DBMS_SESSION․SET_CONTEXT)․

  2. DBMS_RLS․ENABLE_POLICY / DISABLE_POLICY: Административное отключение политики для всех пользователей․ Требует привилегий EXECUTE ON DBMS_RLS․ Используется для обслуживания (maintenance windows)․
  3. ALTER SESSION SET «_vpd_policy_optimization» = FALSE: (Скрытый параметр, не рекомендуется без поддержки Oracle Support)․

Особенности в Мультитенантной Среде (CDB/PDB)

В архитектуре Multitenant (12c+):

  • Политики RLS создаются локально внутри PDB (Pluggable Database)․
  • Контексты приложений могут быть LOCAL (видимы только в текущем PDB) или GLOBAL (видимы во всем CDB, создаются в CDB$ROOT)․
  • Привилегия ALTER ANY SECURITY POLICY может быть предоставлена как локально (в PDB), так и глобально (в CDB$ROOT с CONTAINER=ALL)․
  • Дополнительное разделение политик для разных контейнеров требуется только при сложных схемах изоляции данных между PDB, а не как стандарт для каждого случая․

Типичные Ошибки и Лучшие Практики

Ошибки:

  • Использование SYSDATE / USERENV в предикате без CONTEXT_SENSITIVE: Приводит к некорректному кэшированию куроров (предкат «застывает» на момент первого парсинга)․
  • Слишком сложные предикаты: Подзапросы к большим таблицам внутри функции политики убивают производительность (Full Scan на каждый вызов)․ Решение: материализованные представления, кэширование в PGA/Package State, индексы․
  • Циклические зависимости: Функция политики запрашивает таблицу, на которой висит эта же политика (или другая, вызывающая первую)․ Приводит к ORA-04091 (mutating table) или рекурсии․
  • Игнорирование INSERT/UPDATE: Политика только на SELECT позволяет пользователю вставить/обновить строку, которую он потом не увидит (или увидит чужую)․ Всегда используйте FOR ALL или явный перечень операций․

Лучшие практики:

  1. Используйте Application Contexts для передачи параметров безопасности, а не параметры функции (функция политики не принимает пользовательских аргументов)․
  2. Тип политики по умолчанию, CONTEXT_SENSITIVE․
  3. Выносите логику проверки прав в отдельные представления (Views) или таблицы конфигурации, чтобы функция политики была легкой: RETURN 'SEC_ID IN (SELECT sec_id FROM user_sec_v WHERE user_id = SYS_CONTEXT(․․․))'․
  4. Аудируйте назначение EXEMPT ACCESS POLICY — это «мастер-ключ» от всех данных․
  5. Тестируйте планы выполнения запросов с включенным RLS (EXPLAIN PLAN показывает добавленные предикаты в секции PREDICATE INFORMATION)․

Пример Полного Цикла Создания Политики

-- 1․ Создание контекста
CREATE OR REPLACE CONTEXT app_security_ctx USING pkg_security_ctx;

-- 2․ Пакет установки контекста (вызывается при логине/смене роли)
CREATE OR REPLACE PACKAGE BODY pkg_security_ctx AS
 PROCEDURE set_dept(p_dept_id NUMBER) IS
 BEGIN
 DBMS_SESSION․SET_CONTEXT('app_security_ctx', 'dept_id', p_dept_id);
 END;
END;

-- 3․ Функция-политика (возвращает VARCHAR2)
CREATE OR REPLACE FUNCTION f_rls_dept_pred (
 p_schema VARCHAR2, p_object VARCHAR2
) RETURN VARCHAR2 AS
 v_pred VARCHAR2(4000);
BEGIN
 -- Если контекст не установлен (админ/тех․ юзер) ⎼ доступ закрыт или открыт по стратегии
 IF SYS_CONTEXT('app_security_ctx', 'dept_id') IS NULL THEN
 RETURN '1=0'; -- Запрет всего
 END IF;
 
 v_pred := 'department_id = ' || SYS_CONTEXT('app_security_ctx', 'dept_id');
 RETURN v_pred;
END;

-- 4․ Привязка политики (CONTEXT_SENSITIVE ⎻ кэш до смены dept_id)
BEGIN
 DBMS_RLS․ADD_POLICY(
 object_schema => 'HR',
 object_name => 'EMPLOYEES',
 policy_name => 'SEC_DEPT_POLICY',
 function_schema => 'SEC_MGR',
 policy_function => 'F_RLS_DEPT_PRED',
 statement_types => 'SELECT, INSERT, UPDATE, DELETE',
 policy_type => DBMS_RLS․CONTEXT_SENSITIVE,
 sec_relevant_cols => 'DEPARTMENT_ID', -- Опционально: только для колонок
 update_check => TRUE -- Проверка предиката при UPDATE/INSERT
 );
END;
/

Технология RLS (VPD) в Oracle предоставляет мощный, централизованный и прозрачный для приложений механизм реализации Fine-Grained Access Control (FGAC)․ Ключевыми факторами успеха являются:

  • Правильный выбор типа политики (Dynamic vs Context Sensitive) для баланса безопасности и производительности․
  • Строгое разграничение привилегий администрирования (EXECUTE ON DBMS_RLS vs ALTER ANY SECURITY POLICY vs EXEMPT ACCESS POLICY)․
  • Использование Application Context как единственного легального канала передачи контекста в предикаты․
  • Обязательное покрытие всеми типами DML-операций (FOR ALL) и включение UPDATE_CHECK => TRUE․

Грамотная реализация RLS позволяет вынести логику безопасности из кода приложений (Java, ․NET, PL/SQL API) непосредственно в ядро БД, гарантируя защиту данных даже при прямом доступе через SQL*Plus, BI-инструменты или уязвимости приложения (SQL Injection)․


Статья подготовлена на основе документации Oracle Database Security Guide, пакета DBMS_RLS и лучших практик внедрения VPD․ Дата актуализации: ․