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

Execute dynamic DDL in PL/SQL procedure through definer role permissions

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

问题是 '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;

我尝试了什么:

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

有什么办法可以解决这个问题而不直接将 CREATE TABLE 授予管理员用户?

您只能在 PL/SQL 存储的 procedure/function 中设置角色,前提是它具有 调用者权限 (AUTHID CURRENT_USER)(see doc).这意味着您不能使用 ops_user 调用 admin_user 的过程然后访问 admin_user 的角色。如果您的 DBA 坚持使用角色来控制 CREATE TABLE 权限,这是我以前见过的方法:

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。