【问题标题】:Execute dynamic DDL in PL/SQL procedure through definer role permissions通过定义者角色权限在 PL/SQL 过程中执行动态 DDL
【发布时间】:2018-01-06 18:58:08
【问题描述】:

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

问题是“创建表”权限是通过使用角色授予管理员用户的,这不允许我执行 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,我可以使用管理员用户正确执行该过程。

有没有什么办法可以在不直接将 CREATE TABLE 授予管理员用户的情况下解决这个问题?

【问题讨论】:

  • 您不能只创建一个在管理员架构中执行此操作的过程/函数,并将对该过程/函数的执行权限授予您心目中的用户。这样,您可以实现隔离+限制注入,如果您打算让查询保持打开状态,只需对通过的任何内容使用 execute immediate。
  • 确实这是我打算做的,但管理员没有直接授权来创建表,只能通过角色。这似乎使得无法使用定义者权限执行该过程,即使它是由管理员用户自己执行的。
  • 为什么不想将 CREATE TABLE 授予管理员用户?
  • 如果 CREATE TABLE 不被公司政策允许,那么它也应该被角色禁止。请您的 DBA 将此权限授予您的用户。
  • 是的,CREATE TABLE 授予架构对象的 ALTER 和 DROP 权限。

标签: oracle stored-procedures plsql grant database-permissions


【解决方案1】:

如果 PL/SQL 存储过程/函数具有调用者权限,则只能在角色中设置角色 (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 授予您的管理员用户。

【讨论】:

  • 感谢您的选择。正如您所建议的那样,我将首先尝试为我的管理员用户获得直接的 CREATE TABLE 授权。
猜你喜欢
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多