首页 文章

通过定义角色权限在PL / SQL过程中执行动态DDL

提问于
浏览
4

我想在管理员用户拥有的过程中执行一些动态DDL . 我想与具有定义权限的技术操作用户执行此过程(操作用户没有create table角色) .

问题是通过使用角色授予管理员用户“创建表”权限,这不允许我执行DDL,因为似乎角色不计入命名的pl / sql块 .

create or replace
PROCEDURE test_permissions AUTHID DEFINER AS
  v_query_string VARCHAR2(400 CHAR) := 'CREATE TABLE TEST(abcd VARCHAR2(200 CHAR))';
BEGIN

  EXECUTE IMMEDIATE v_query_string;

END;

我尝试了什么:

  • 在proc上使用AUTHID CURRENT_USER从函数集运行过程到AUTHID DEFINER(希望函数以某种方式级联定义器)

  • 在函数内部放置一个匿名块来执行DDL(因为角色似乎在匿名块中计算)

如果我将AUTHID设置为CURRENT_USER,我可以使用admin用户正确执行该过程 .

有没有办法解决这个问题而不直接向管理员用户授予CREATE TABLE?

1 回答

  • 2

    如果它具有Invoker的权限( AUTHID CURRENT_USER(see doc),则只能在PL / SQL存储过程/函数中设置角色 . 这意味着您可以't use ops_user to call admin_user'的过程然后访问admin_user的角色 . 如果您的DBA坚持使用角色来控制 CREATE TABLE 权限,请在此处查看's the approach I':

    create or replace package admin_user.role_test authid current_user is
        procedure test_permissions;
    end role_test;
    /
    create or replace package body admin_user.role_test is
        procedure test_permissions is
            v_query_string VARCHAR2(400 CHAR) := 'begin 
    dbms_output.put_line(''after'');
    for r in (select role from session_roles) loop 
        dbms_output.put_line(r.role); 
    end loop;
    end;';
        begin
            dbms_output.put_line('before');
            for r in (select role from session_roles) loop
                dbms_output.put_line(r.role);
            end loop;
            DBMS_SESSION.SET_ROLE('CREATE_TABLE_ROLE IDENTIFIED BY "SECRET_PASSWORD"');
            execute immediate v_query_string;
            DBMS_SESSION.SET_ROLE('ALL EXCEPT CREATE_TABLE_ROLE'); -- restore defaults
        end;
    end role_test;
    /
    grant execute on admin_user.role_test to ops_user;
    

    这将临时授予ops_user角色以执行您的代码 . 默认情况下,ops_user应该无法查看admin_user的包体源 . 您可以包装包体以进一步保护密码 . 但是除了密码安全之外,我最关心的是这种方法是Oracle没有提供一种很好的方法来禁用单个角色,所以如果ops_user有其他受密码保护的角色,这个代码在尝试恢复时可能会引发ORA-01979他们 .

    所以,有一个答案,但我仍然建议做其他评论者建议的内容,并向管理员用户授予CREATE TABLE .

相关问题