`RESOURCE` 角色是 Oracle 內建的開發者角色,但其權限內容在版本間有變化,且授予使用者時會「隱含」附贈 `UNLIMITED TABLESPACE` 系統權限,而授予角色時則不會。本文實測 10g 環境下 `RESOURCE` 角色包含的 8 項系統權限,驗證 `UNLIMITED TABLESPACE` 異常傳遞行為,並揭示角色嵌套時的權限遺失陷阱。
SQL> SELECT privilege FROM role_sys_privs WHERE role = 'RESOURCE';
PRIVILEGE
----------------------------------------
CREATE CLUSTER
CREATE SEQUENCE
CREATE TRIGGER
CREATE TABLE
CREATE PROCEDURE
CREATE TYPE
CREATE OPERATOR
CREATE INDEXTYPE
注意: 不含 `CREATE SESSION`、`CREATE VIEW`、`CREATE SYNONYM` 等權限 (10g R2 起從 `CONNECT` 移除)。
-- 1. 建立測試使用者 desk (無任何權限)
CREATE USER desk IDENTIFIED BY desk;
-- desk 此時查詢 user_sys_privs → no rows selected
-- 2. 授予 RESOURCE 給 desk
GRANT RESOURCE TO desk;
-- 3. desk 再次查詢
SQL> SELECT privilege FROM user_sys_privs;
PRIVILEGE
----------------------------------------
UNLIMITED TABLESPACE -- ← 憑空出現!未在 RESOURCE 定義中
結論: Oracle 內部邏輯在 `GRANT RESOURCE TO user` 時,會額外執行 `GRANT UNLIMITED TABLESPACE TO user`。這是歷史相容性設計,但違反最小權限原則。
-- 1. 建立中繼角色 testrole
CREATE ROLE testrole IDENTIFIED BY testrole;
-- 2. 撤銷 desk 的 RESOURCE,改授予 testrole
REVOKE RESOURCE FROM desk;
GRANT RESOURCE TO testrole;
GRANT testrole TO desk;
-- 3. desk 查詢權限
SQL> SELECT privilege FROM user_sys_privs;
-- no rows selected ← UNLIMITED TABLESPACE 消失!
機制: `UNLIMITED TABLESPACE` 只在「直接授予使用者」時觸發,不遞歸傳遞給角色嵌套鏈路。
| 場景 | 實際權限 | 風險/建議 |
|---|---|---|
| GRANT RESOURCE TO app_user | RESOURCE 8 項 + UNLIMITED TABLESPACE | 使用者可在任何表空間無限擴展,建議改用 QUOTA 限制 |
| GRANT RESOURCE TO mid_role; GRANT mid_role TO app_user | 僅 RESOURCE 8 項 | 避免隱含權限,但需額外授予 CREATE SESSION 等 |
| 12c+ PDB 環境 | RESOURCE 仍含 UNLIMITED TABLESPACE 行為 | 同樣需注意,PDB 級表空間配額管理 |
-- 建立自訂開發者角色
CREATE ROLE app_developer;
-- 明確授予所需系統權限 (不含 UNLIMITED TABLESPACE)
GRANT CREATE SESSION,
CREATE TABLE,
CREATE VIEW,
CREATE SEQUENCE,
CREATE PROCEDURE,
CREATE TRIGGER,
CREATE TYPE,
CREATE SYNONYM,
CREATE DATABASE LINK
TO app_developer;
-- 表空間配額顯式控制
ALTER USER app_user QUOTA 100M ON users;
ALTER USER app_user QUOTA 500M ON data_ts;
-- 授予角色
GRANT app_developer TO app_user;
-- 角色系統權限
SELECT privilege FROM role_sys_privs WHERE role = UPPER('&role_name');
-- 角色物件權限
SELECT owner, table_name, privilege FROM role_tab_privs WHERE role = UPPER('&role_name');
-- 使用者生效系統權限 (含角色間接)
SELECT privilege FROM user_sys_privs;
理解 `RESOURCE` 角色的真實權限內容與隱含行為,能避免「以為授予開發權限,實則開放無限表空間」的安全隱患。建議自訂角色替代內建角色,實現精準權限控制。