Oracle虚拟专用数据库(VPD):触发特权/函数生成无效的谓词

时间:2018-07-12 13:28:49

标签: oracle plsql triggers vpd

在创建虚拟专用数据库期间遇到两个问题。

  1. 运行数据库登录触发器需要哪些特权?用户需要特殊特权吗?
  2. 错误信息:该函数有问题,但该函数运行良好。

来自用户和表创建的代码:

-- as SYS:
-- in the pdb:
alter session set container = orclpdb;

create user orders identified by orders;
create user vpd_admin identified by vpd_admin;
create user hanna identified by hanna;
create user smith identified by smith;

grant create session to orders, vpd_admin, hanna, smith;
grant create table, unlimited tablespace to orders, vpd_admin;
grant execute on dbms_rls to vpd_admin;
grant create procedure to vpd_admin;

-- in SQL Developer, you can build connections now
-- service name = orclpdb

-- in ORDERS schema:
create table orderinfo2
(ordid number,
product varchar2(10),
custid number);

create table customers
(custid number,
name varchar2(10));

insert into orderinfo2 values (6001, 'coctail', 101);
insert into orderinfo2 values (6002, 'wine', 101);
insert into orderinfo2 values (6003, 'coctail', 102);

insert into customers values (101, 'hanna');
insert into customers values (102, 'smith');

grant select on customers to vpd_admin, hanna, smith;
grant select on orderinfo2 to vpd_admin, hanna, smith;


-- in SYS:
alter session set container = orclpdb;
grant create any trigger to vpd_admin;
grant administer database trigger to vpd_admin;

Package01:转换为kod变量

-- in vpd_admin schema:
create or replace package
    vpd_admin.order_sec_ident
    is procedure kod_variable;
end;
/
 
create or replace package body
    vpd_admin.order_sec_ident
    is procedure
    kod_variable
    is
        kod number;
    begin
        select custid into kod
            from orders.customers where
                trim(upper(name)) =
                sys_context('USERENV', 'SESSION_USER');
        dbms_session.set_context
            ('ORDER_NS', 'KOD_ARG', to_char(kod));
        exception
            when no_data_found then
            dbms_session.set_context
            ('ORDER_NS', 'KOD_ARG', '-1');
    end;
end order_sec_ident;
/

grant execute on order_sec_ident to public;

登录触发器:

create or replace trigger logon_trigger
   after logon
   on database
begin vpd_admin.order_sec_ident.kod_variable;
end;
/

package2:条件纳入政策

create or replace package vpd_admin.orders_cond as
    function cond
    (schema_v varchar2,
    table_v varchar2)
    return varchar2;
    pragma restrict_references (cond, wnds);
end;
/
create or replace package body vpd_admin.orders_cond as
    function cond
    (schema_v varchar2,
    table_v varchar2)
    return varchar2
is
    wherevalue varchar2(2000);
begin
    if
        trim(upper(user)) <> schema_v
        and trim(upper(user)) <> 'SYS'
        and trim(upper(user)) <>'SYSTEM' then
        wherevalue := 'trim(upper(name)) = 
            sys_context (''ORDER_NS'', ''KOD_ARG'')';
    else wherevalue := '1=1';
    end if;
    return wherevalue;
end cond;
end;
/

dbms_rls.add_policy

begin
 dbms_rls.add_policy
 ('orders',
'orderinfo2',
'ord_sec_pol2',
'vpd_admin',
'orders_cond.cond',
'SELECT');
end;
/

问题1:由于logon_trigger,用户无法登录

问题1:用户没有足够的特权来运行触发器,需要授予哪些特权?

An error was encountered performing the requested operation:

ORA-04088: error during execution of trigger 'VPD_ADMIN.LOGON_TRIGGER'
ORA-00604: error occurred at recursive SQL level 1
ORA-01031: insufficient privileges
ORA-06512: at "SYS.DBMS_SESSION", line 130
ORA-06512: at "VPD_ADMIN.ORDER_SEC_IDENT", line 12
ORA-06512: at line 1
04088. 00000 -  "error during execution of trigger '%s.%s'"
*Cause:    A runtime error occurred during execution of a trigger.
*Action:   Check the triggers which were involved in the operation.
Vendor code 4088
-- (as sys granted dba to smith so I can continue testing)

问题2-1:如何查看跟踪文件?

问题2-2:函数有什么问题?

-- in smith schema:
select * from orders.orderinfo2;

ORA-28113: policy predicate has error
28113. 00000 -  "policy predicate has error"
*Cause:    Policy function generates invalid predicate.
*Action:   Review the trace file for detailed error information.

分别运行功能脚本,它可以工作:

-- in vpd_admin:
create or replace
 function cond
    (schema_v varchar2,
    table_v varchar2)
    return varchar2
is
    wherevalue varchar2(2000);
begin
    if
        trim(upper(user)) <> schema_v
        and trim(upper(user)) <> 'SYS'
        and trim(upper(user)) <>'SYSTEM' then
        wherevalue := 'trim(upper(name)) = 
            sys_context (''ORDER_NS'', ''KOD_ARG'')';
    else wherevalue := '1=1';
    end if;
    return wherevalue;
end cond;
/

declare
    x varchar2(20) := 'aa';
    y varchar2(20) := 'bb';
begin
    dbms_output.put_line(cond(x, y));
end;
/

-- result: trim(upper(name)) = 
            sys_context ('ORDER_NS', 'KOD_ARG')

1 个答案:

答案 0 :(得分:1)

回应:

  

问题1:用户没有足够的权限来运行触发器,   需要授予什么特权?

这里的问题是触发器执行但引发异常。登录异常会停止登录,并可能对数据库产生广泛影响,这当然是不希望的。因此,登录触发器通常被创建为无异常或仔细控制任何可能的异常。

在此示例中, app.use(express.static(path.join(__dirname, '/movies-client/dist/movies-client'))); app.use('/movies', movies); app.get('/', (req, res) => { res.send('invaild endpoint'); }); app.get('*', (req, res) => { res.sendFile(path.join(__dirname + '/movies-client/dist/movies-client/index.html')); }); vpd_admin.order_sec_ident进行了一些处理,但是可以引发其他异常,并且处理程序本身可以引发异常。一些实现在数据库范围的登录触发器中使用no data found以确保没有异常。如果此处解决了触发器中的异常,则用户将能够再次登录。

您看到的priv问题可能是由于在过程中使用EXCEPTION WHEN OTHERS而引起的。确保DBMS_SESSION.SET_CONTEXT可以访问并在其auth中运行上下文设置可以解决priv问题。

针对:

  

问题2-1:如何查看跟踪文件?

警报,跟踪文件条件,位置等是可配置的。 Documentation有更多信息

针对:

  

问题2-2:函数有什么问题?

vpd_admin没有名称列。子句orderinfo2中的名称在执行时产生无效的sql。

orderinfo2上的策略必须对列'trim(upper(name)) = sys_context ('ORDER_NS', 'KOD_ARG')'ordidproduct有效(或与示例中的custid一样有效且不包含任何列) )。

将通过更改1=1条件来更正此异常,使其在类似'trim(upper(name)) = sys_context ('ORDER_NS', 'KOD_ARG')'的语句中有效