这很奇怪,而且不容易解释,所以请多多包涵。
Linux x86_64上的Oracle 12.2.0.1。
我们有一个名为BATCH
的用户,该用户具有最小权限。
CREATE USER batch IDENTIFIED BY batch
DEFAULT TABLESPACE users
QUOTA UNLIMITED ON users;
GRANT CREATE SESSION TO batch;
GRANT EXECUTE ON DBMS_CRYPTO TO batch;
这是一个名为ATLED
的架构中的PLSQL程序包,它是:
CREATE OR REPLACE PACKAGE ALTED.the_pkh AUTHID current_user AS
PROCEDURE crttab;
END;
/
CREATE OR REPLACE PACKAGE BODY ALTED.the_pkh AS
PROCEDURE crttab IS
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE atled.the_tab AS SELECT id, DBMS_CRYPTO.HASH(cc,2) AS cc FROM ARCHIVE.table_b';
END crttab;
END;
/
我们正在使用基于代码的访问控制(CBAC-12c功能)来限制/控制/允许其他没有牙齿的用户执行某些固定操作,因此我们创建了一个包装程序,并赋予了高度特权角色,然后将执行权限授予批处理用户:
CREATE OR REPLACE PROCEDURE ALTED.wrapper_crttab AS
PROCEDURE p1 IS
CURSOR c1 is SELECT * FROM SESSION_PRIVS;
BEGIN
FOR r1 IN c1 LOOP
DBMS_OUTPUT.PUT_LINE( r1.privilege );
END LOOP;
END;
BEGIN
p1;
ALTED.the_pkh.crttab;
END;
/
GRANT IMP_FULL_DATABASE TO ALTED;
GRANT IMP_FULL_DATABASE ALTED.wrapper_crttab;
GRANT EXECUTE ON ALTED.wrapper_crttab TO batch;
现在运行它:
CONN batch/batch
SET SERVEROUTPUT ON
EXEC ALTED.wrapper_crttab;
这会导致错误:
第1行出现错误:
ORA-00942:表或视图不存在
引用的表确实存在。
对p1
proc的调用确认存在与IMP_FULL_DATABASE捆绑在一起的所有特权,包括CREATE ANY TABLE
,DROP ANY TABLE
,EXECUTE ANY PROCEDURE
。
如果我这样做:
GRANT CREATE ANY TABLE TO batch;
GRANT SELECT ANY TABLE TO batch;
CONN batch/batch
EXEC EXECUTE IMMEDIATE 'CREATE TABLE atled.the_tab AS SELECT id, DBMS_CRYPTO.HASH(cc,2) AS cc FROM ARCHIVE.table_b;
这有效。
如果我更改CREATE TABLE
stmt以删除DBMS_CRYPTO
调用,它也将正常工作。
所调用的实际包/过程按上面的方式运行时会创建许多表,但是在任何CREATE TABLE
语句中调用DBMS_CRYPTO的情况下都会失败。
如果我直接向batch
用户授予CREATE ANY TABLE
,SELECT ANY TABLE
和EXECUTE ANY PROCEDURE
privs权限,并直接成批运行CREATE TABLE
命令,那么它也可以工作。
所以这不是(我认为)直接的ORA-942错误,而是与DBMS_CRYPTO特权链有关的东西,并且仅在程序包存储过程中执行时才发生,但是我不知道到底是什么。
更新1
如果我为DBMS_CRYPTO.HASH创建包装,如下所示:
CREATE OR REPLACE FUNCTION batch.crypto_hash ( pcc IN CLOB ) RETURN VARCHAR2 IS
BEGIN
RETURN DBMS_CRYPTO.HASH(pcc,2);
END;
/
然后将DBMS_CRYPTO.HASH(cc,2)
stmt中的CREATE TABLE
替换为batch.crypto_hash(cc)
,就可以了!!!
因此,绝对不是引用表的授予问题,而是DBMS_CRYPTO工作方式的内部问题。也许它在某处读取查询表。在此之前,我也尝试过GRANT EXECUTE ON UTL_I18N to batch
,但这没用。
所以我有一个解决方法,但是woudl仍然想知道为什么会这样。
答案 0 :(得分:0)
您正在这样做:
... FROM ARCHIVE.table_b
应该从该表中选择的用户必须具有SELECT
特权。可以授予
如果您通过角色授予了特权,则可以使用-但不适用于命名的PL / SQL过程。它可以在匿名PL / SQL中工作,但不能在过程,函数,程序包中工作,因此-请检查并可能将SELECT
上的table_b
授予该用户。