Функция политики VPD - PullRequest
       2

Функция политики VPD

0 голосов
/ 17 декабря 2018

Я новичок в безопасности оракула, и у меня есть вопрос о виртуальной частной базе данных. Предположим, у меня есть следующая таблица, которая называется "Расчет заработной платы", созданная пользователем с именем "PCM"

EMP_ID               DEPT                      TOTAL      TAXES
-------------------- -------------------- ---------- ----------
E1                   accounting                 2400        100 
E2                   sales                      2500         75 
E3                   research                   3000        110 
E4                   operations                 4200        120 
E5                   sales                      4800        130 
E6                   sales                      2500         75 
E7                   accounting                 5200        140 
E8                   accounting                 2700        105

Теперь я хочу добиться следующего: любой, у кого есть dept = accounting", может выбрать все остальные строки с помощью dept != accounting, но любой, у кого есть dept != accounting, может только просматривать свою запись.Моя проблема заключается в том, что, поскольку мы не можем применить оператор выбора к таблице, мы ограничиваем доступ внутри функции политики (которая является платежной ведомостью), и поскольку применение функции политики к таблице (заработной платы) будет применяться к любому основанному представлениюна это какая логика решить эту проблему ??что такое решение, я написал следующее «Я подключен как другой пользователь, не являющийся владельцем таблицы заработной платы, поэтому я подключен как пользователь с именем ANNE»:

CREATE OR REPLACE CONTEXT payroll_ctx USING payroll_ctx_pkg;
CREATE OR REPLACE PACKAGE payroll_ctx_pkg IS 
  PROCEDURE set_dept;
 END;
/
CREATE OR REPLACE PACKAGE BODY payroll_ctx_pkg IS
  PROCEDURE set_dept
  AS
    v_dept varchar2(400);
  BEGIN
     SELECT dept INTO v_dept FROM PCM.PAYROLL
        WHERE EMP_ID = SYS_CONTEXT('USERENV', 'SESSION_USER');
     DBMS_SESSION.SET_CONTEXT('payroll_ctx', 'dept', v_dept);
  EXCEPTION
   WHEN NO_DATA_FOUND THEN
   DBMS_SESSION.SET_CONTEXT('payroll_ctx', 'dept', 'E0');
  END set_dept;
END;
/

Учитывая, чтопользователи, которые будут пытаться получить доступ к таблице, теперь имеют имена столбца emp_id:

CREATE TRIGGER set_dept_trig AFTER LOGON ON DATABASE
 BEGIN
  ANNE.payroll_ctx_pkg.set_dept;
 END;
/

Теперь проблема (я знаю, что это неправильно), но не может найти решение:

create or replace function sec_fun (p_schema varchar2, p_obj varchar2)
return varchar2
as
    vv_dept varchar2(400);
    payroll_pred varchar2(400);
begin
    payroll_pred := '1=2';
    vv_dept := SYS_CONTEXT('payroll_ctx', 'dept');
    if (vv_dept != 'accounting') then
        payroll_pred := 'DEPT =''' || vv_dept ||'''';
    else
        payroll_pred:='DEPT !=''' || vv_dept ||'''';
    end if;
   return payroll_pred;
end;
/

А потом:

BEGIN
 DBMS_RLS.ADD_POLICY (
  object_schema    => 'PCM', 
  object_name      => 'PAYROLL', 
  policy_name      => 'payroll_policy', 
  function_schema  => 'ANNE',
  policy_function  => 'sec_fun',
  statement_types  => 'select');
END;
/

и сообщение об ошибке, которое я получаю, когда пользователь E1 пытается выбрать из расчета:

no rows selected

что я делаю неправильно ??Я отредактировал вопрос и результат, основываясь на ответах ниже.

1 Ответ

0 голосов
/ 17 декабря 2018

Я собираюсь сделать некоторые предположения, но если ни один из них не решит вашу проблему, вам нужно будет найти диагностическую информацию, которую предоставляет база данных.ORA-28112 создаст файл трассировки в каталоге user_dump_dest на сервере базы данных.Это должно дать вам всю информацию, необходимую для диагностики и исправления любых ошибок в коде вашей политики.Если у вас нет доступа к этому каталогу, вам нужно будет попросить помочь вашу дружную команду администраторов баз данных / системного администратора.

Итак, предположения.

Вы устанавливаете vv_dept встрока 'dept = SYS_CONTEXT(''payroll_ctx'', ''dept'')'.В блоке IF вы объединяете это с фильтром предложения WHERE.Итак, ваша последняя строка на самом деле:

DEPT =dept = SYS_CONTEXT('payroll_ctx', 'dept')

(Она никогда не выполнит ветвь DEPT !=, потому что вы присваиваете эту строку vv_dept, не выполняя ее, поэтому vv_dept никогда не может быть равным 'Accounting'.)

Это явно неправильно, и поэтому неудивительно, что Oracle швыряет ORA-28112.К счастью, решение в равной степени очевидно: просто приведите в порядок присваивание vv_dept:

vv_dept := SYS_CONTEXT('payroll_ctx', 'dept');

Другая вещь, на которую стоит обратить внимание, - это форматирование самой политики.Вы проверяете равенство строки, поэтому вам нужно заключить ее в кавычки, чтобы получить правильный SQL:

        payroll_pred := 'DEPT =''' || vv_dept ||'''';

И, очевидно, то же самое для другой ветви.

Еще одинвещь, чтобы рассмотреть.Если вы входите в систему как пользователь, которого нет в таблице payroll (не уверен, возможно ли это), вы выполняете это:

WHEN NO_DATA_FOUND THEN NULL;

Следовательно, у этого сеанса нет установленного контекста, что означает, что функция политики потерпит неудачу, есливпоследствии пользователь пытается запросить payroll.Лучшим подходом было бы установить контекст с нулевым значением для dept, затем в политику добавить тест для vv_dept is null, который применяет 1=2 или что-то подобное.

ORA-06502:PL / SQL: ошибка с числовым значением или значением: буфер символьной строки слишком мал

Что ж, вы наверняка получите это, если будете использовать опубликованный код sec_fun, потому что вы определили vv_dept как varchar2(20) и назначенная строка длиннее двадцати символов.Но вы говорите, что запускаете мои предложенные изменения, так что этого не может быть.Какой размер payroll.dept?

Последнее слово.

Политики VPD являются особым случаем динамического SQL, и основной принцип остается неизменным: динамический SQL сложен, потому что он превращает ошибки компиляции в ошибки времени выполнения.Точно так же основной инструмент отладки все еще записывает дескриптор выполнения, который записывает всю собранную строку в таблицу (или файл).


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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...