15.11.2013

Пример реализации Virtual Private Database (VPD)

Cуть технологии в том, что к запросу данных из защищенной таблицы или представления динамически добавляется предикат. Предикат формируется в заранее определенном методе.
Создадим тестовую таблицу с данными:
create table apps.test_users_all (
       id    number not null,
       name  varchar2(255)
       )
/   
create or replace synonym apps.test_users for apps.test_users_all
/
insert into apps.test_users_all (id, name)
values (1, user)
/
insert into apps.test_users_all (id, name)
values (2, 'SCOTT')
/
insert into apps.test_users_all (id, name)
values (3, 'TIGER')
/
Обратимся за данными к синониму:
SQL> select * from test_users
  2  /
        ID NAME
        ---------- -----------
         1 APPS
         2 SCOTT
         3 TIGER
Настроим ограничение так, чтобы отображались только строки, в которых name = user. В данном случае этому ограничению соответствует одна строка с ID = 1.
Создадим пакет с функциями, реализующими предикат:
create or replace package XXTEST_VPD is
 function users_security (obj_schema varchar2, 
                          obj_name   varchar2) return varchar2; 
end XXTEST_VPD
/
create or replace package body XXTEST_VPD is
 function users_security (obj_schema varchar2, 
                          obj_name   varchar2) return varchar2
 is
 begin
   return 'name = user';
 end users_security; 
end XXTEST_VPD
/ 
Применим политику безопасности:
declare
  l_tmp number;
begin
  begin
    select 1
     into l_tmp
     from dual
     where not exists 
     (select null
            from dba_policies p
            where p.object_name = 'TEST_USERS');
  exception
    when NO_DATA_FOUND then
      dbms_rls.drop_policy(object_schema => 'APPS',
                           object_name   => 'TEST_USERS',
                           policy_name   => 'USERS_SECURITY');
  end;
  dbms_rls.add_policy(object_schema   => 'APPS',
                      object_name     => 'TEST_USERS',
                      policy_name     => 'USERS_SECURITY',
                      policy_function => 'XXTEST_VPD.USERS_SECURITY',
                      function_schema => 'APPS');
end; 
Здесь мы применяем ограничение на синоним TEST_USERS. Пробуем выполнить запрос к защищенной таблице:
SQL> select * from test_users
  2  /
        ID NAME
        ---------- ----------
         1 APPS
Мы видим, что синоним ограничен по определенному нами предикату.