全部產品
Search
文件中心

PolarDB:DBMS_RLS

更新時間:Jul 06, 2024

DBMS_RLS包可以使虛擬私人資料庫VPD(Virtual Private Database)執行於特定的PolarDB資料庫物件上。

表 1. DBMS RLS 函數/預存程序
函數/預存程序類型傳回型別說明
ADD POLICY(object schema, object name, policy name, function schema, policy function [, statement types [, update check [, enable [, static policy [, policy type [, long predicate [, sec relevant cols [, sec relevant cols opt ]]]]]]]])預存程序N/A向資料庫物件添加安全性原則。
DROP_POLICY(object_schema, object_name, policy_name)預存程序N/A從資料庫物件中刪除安全性原則。
ENABLE_POLICY(object_schema, object_name, policy_name, enable)預存程序N/A啟用或禁用安全性原則。

與Oracle版本的DBMS_RLS包執行相比,PolarDB的DBMS_RLS包執行是一個部分執行。PolarDB僅支援上述表中列出的函數和預存程序。

虛擬私人資料庫是一種使用安全政策的細粒度存取控制。虛擬私人資料庫中的細粒度存取控制意味著對於資料的訪問可以控制到具體的行資訊。

在policy function中定義了編碼安全政策的規則。這個規則是一個SPL函數,有特定的輸入參數和傳回值。security policy是命名的政策函數聯合到特定的資料庫物件,尤其是表。

說明
  • PolarDB中,可以用任何PolarDB所支援的語言來編寫政策函數。例如,除了與Oracle相容的SPL語言外,您還可以使用SQL和PL/pgSQL語言。
  • 目前PolarDB虛擬私人資料庫所支援的資料庫物件為表。政策不適用於視圖或同義字。
使用虛擬私人資料庫的優勢有以下幾點:
  • 虛擬私人資料庫可以提供細粒度層級的安全訪問。GRANT命令授予的資料庫物件層級的許可權能夠決定存取權限是否能訪問資料庫物件中的整個執行個體。虛擬私人資料庫則為資料庫物件執行個體的個人記錄提供了存取控制。
  • 根據SQL命令(INSERT、UPDATE、DELETE或SELECT)的類型,您可以應用不同的安全政策。
  • 由於每個可應用的SQL命令影響的資料庫物件取決於一些因素(例如申請訪問資料庫物件的會話使用者),因此安全政策會動態變化。
  • 安全政策的調用對所有資料庫物件的訪問申請都是透明的。因此,您不用為了應用安全政策去修改個人申請。
  • 一旦啟用了安全政策,那麼任何申請(包括新申請)都無法繞過安全政策。除下列說明中列出的系統許可權以外。
  • 除下列說明中列出的系統許可權以外,即使是超級使用者也不能繞過安全政策。
說明 唯一可以繞過安全政策的方法就是授權給使用者EXEMPT ACCESS POLICY系統許可權。但EXEMPT ACCESS POLICY系統許可權的授予必須格外小心,因為有此許可權的使用者可以繞過資料庫中所有的安全政策。

DBMS_RLS包提供的預存程序可用於建立、刪除、啟用及禁用安全政策。

執行虛擬私人資料庫的相關操作如下:
  • 首先要建立一個政策函數。這個函數必須有兩個類型為VARCHAR2的輸入參數。第一個輸入參數提供給包含資料庫物件(安全政策要應用於這個資料庫物件上)的模式。第二個輸入參數則提供給資料庫物件的名稱。所建立的這個政策函數還必須有一個VARCHAR2傳回型別,且返回的必須是一個WHERE謂語子句形式的字串。謂語將以AND條件動態附於對資料庫物件起作用的SQL命令之上。因此,不滿足政策函數謂語的記錄將從SQL命令的結果集中過濾掉。
  • 使用ADD_POLICY預存程序來定義一個新政策,這是政策函數與資料庫物件的聯合。通過使用ADD_POLICY預存程序,您可以指定SQL命令(例如:INSERT、 UPDATE、 DELETE或SELECT,且政策要應用於這些SQL命令之上)的類型,也可以決定是否在建立政策的同時對它進行啟用,或決定政策函數是否可以應用於新插入的記錄上或更新記錄修改後的映像上。
  • 使用ENABLE_POLICY預存程序來禁用或啟用現有的安全政策。
  • 使用DROP_POLICY預存程序來刪除已有的政策。但DROP_POLICY預存程序不能刪除政策函數或聯合資料庫物件。

一旦政策建立之後,您就可以在與Oracle相容的目錄檢視下瀏覽所建立的政策。

SYS_CONTEXT函數通常與DBMS_RLS一起使用。文法如下:
SYS_CONTEXT(namespace, attribute)        
  • namespace 是一個VARCHAR2值。唯一接受的值是USERENV。任何其他的值返回的都將是NULL。
  • attribute是一個VARCHAR2值。屬性取值如下:
    屬性值等效值
    SESSION_USERpg_catalog.session_user
    CURRENT_USERpg_catalog.current_user
    CURRENT_SCHEMApg_catalog.current_schema
    HOSTpg_catalog.inet_host
    IP_ADDRESSpg_catalog.inet_client_addr
    SERVER_HOSTpg_catalog.inet_server_addr
說明 用於說明DBMS_RLS包的樣本是基於樣本表emp修改後的副本, 提供表emp的PolarDB及一個名為salesmgr的角色授予所有許可權給這個表。如下所示,您可以建立一個emp表的副本並命名為vpemp及名為salesmgr的角色。
CREATE TABLE public.vpemp AS SELECT empno, ename, job, sal, comm, deptno FROM emp;
ALTER TABLE vpemp ADD authid VARCHAR2(12);
UPDATE vpemp SET authid = 'researchmgr' WHERE deptno = 20;
UPDATE vpemp SET authid = 'salesmgr' WHERE deptno = 30;
SELECT * FROM vpemp;

empno | ename  |    job    |   sal   |  comm   | deptno |   authid    
-------+--------+-----------+---------+---------+--------+-------------
  7782 | CLARK  | MANAGER   | 2450.00 |         |     10 | 
  7839 | KING   | PRESIDENT | 5000.00 |         |     10 | 
  7934 | MILLER | CLERK     | 1300.00 |         |     10 | 
  7369 | SMITH  | CLERK     |  800.00 |         |     20 | researchmgr
  7566 | JONES  | MANAGER   | 2975.00 |         |     20 | researchmgr
  7788 | SCOTT  | ANALYST   | 3000.00 |         |     20 | researchmgr
  7876 | ADAMS  | CLERK     | 1100.00 |         |     20 | researchmgr
  7902 | FORD   | ANALYST   | 3000.00 |         |     20 | researchmgr
  7499 | ALLEN  | SALESMAN  | 1600.00 |  300.00 |     30 | salesmgr
  7521 | WARD   | SALESMAN  | 1250.00 |  500.00 |     30 | salesmgr
  7654 | MARTIN | SALESMAN  | 1250.00 | 1400.00 |     30 | salesmgr
  7698 | BLAKE  | MANAGER   | 2850.00 |         |     30 | salesmgr
  7844 | TURNER | SALESMAN  | 1500.00 |    0.00 |     30 | salesmgr
  7900 | JAMES  | CLERK     |  950.00 |         |     30 | salesmgr
(14 rows)

CREATE ROLE salesmgr WITH LOGIN PASSWORD 'password';
GRANT ALL ON vpemp TO salesmgr;

ADD_POLICY

ADD_POLICY預存程序通過聯合政策函數和資料庫物件來建立一個新政策。

只有超級使用者才能執行ADD_POLICY預存程序。

ADD_POLICY(object_schema VARCHAR2, object_name VARCHAR2,
  policy_name VARCHAR2, function_schema VARCHAR2,
  policy_function VARCHAR2
  [, statement_types VARCHAR2
  [, update_check BOOLEAN
  [, enable BOOLEAN
  [, static_policy BOOLEAN
  [, policy_type INTEGER
  [, long_predicate BOOLEAN
  [, sec_relevant_cols VARCHAR2
  [, sec_relevant_cols_opt INTEGER ]]]]]]]])

參數

參數名稱描述
object_schema包含資料庫物件(政策將應用於這個資料庫物件上)的模式名稱。
object_name政策所要應用於的資料庫物件的名稱。也許會有1個以上的政策應用於一個指定的資料庫物件上。
policy_name分配給政策的名稱。資料庫物件(由object_schema object_name 標識)的聯結與政策名稱在資料庫中必須是唯一的。
function_schema包含政策函數的模式名稱。
說明 政策函數也許屬於一個包。在這種情況下,function_schema必須含有定義包的模式名稱。
policy_functionSPL函數的名稱,用於定義安全政策的規則。相同的函數也許會指定於多個政策中。
說明 政策函數也許屬於一個包。在這種情況下,policy_function必須也包含點符號的包名稱(也就是package_name. function_name
statement_types逗號分隔的SQL命令列表,且政策應用於SQL命令之上。有效SQL命令是INSERT、UPDATE、DELETE和SELECT。預設為INSERT,UPDATE,DELETE,SELECT
說明 PolarDB接受INDEX為語句類型,但會忽略。在PolarDB中,政策不能應用於索引操作中。
update_checkupdate_check只能應用於INSERTUPDATE的SQL命令中。
  • update_check設定為TRUE時,政策可應用於新插入的記錄及更新記錄修改後的映像上。如果根據政策函數謂語內容, 新的或修改後的記錄不是模式限定的,那麼INSERTUPDATE命令則會產生異常,並且不會插入或修改任何記錄。
  • update_check設為FALSE時,政策不可應用於新插入的記錄或更新記錄修改後的映像上。 因此,新插入的記錄也許不會出現在SQL命令序列(SQL命令是調用相同政策的命令)的結果集中。同樣的,根據UPDATE命令之前的政策,如果記錄為模式限定的,那麼記錄將不會出現在SQL命令(調用相同的政策的SQL命令)的序列集中。
enable
  • enable設定為TRUE時, 則啟用政策並將其應用到statement_types參數指定的SQL命令中。預設值為TRUE.
  • enable設定為FALSE時,則禁用了政策且政策將不能應用於任何SQL命令中。通過使用ENABLE_POLICY預存程序,可以啟用政策。
static_policy
  • 在Oracle環境下,當static_policy設定為TRUE時,政策是靜態。即在資料庫物件上的政策對每一個資料庫物件進行第一次調用時,政策函數都會被評估一次。作為結果的政策函數謂語字串會儲存在記憶體中。當資料庫伺服器執行個體運行時,這些字串可以為相同資料庫物件上的相同政策的所有調用所再次使用。
  • 在Oracle環境下,當static_policy設定為FALSE時,政策是動態。即政策函數會被重新評估,且政策函數謂語字串也會為政策的所有調用而再次產生。預設值為FALSE。
說明
  • 在Oracle 10g中介紹了policy_type參數,用於替換static_policy參數。在Oracle環境下,如果沒有將policy_type參數設為預設值NULL,則policy_type參數值將覆蓋static_policy參數值。
  • PolarDB僅執行動態政策,無需進行static_policy參數的設定。
policy_type在Oracle環境下,policy_type用於決定重新評估政策函數的時間。預設值為NULL。
說明 PolarDB僅執行動態政策,無需進行policy_type參數的設定。
longpredicate在Oracle環境下,如果將longpredicate設定為TRUE,則允許謂語達到32KB位元組。 否則,謂語就限制於4000位元組。預設值為FALSE。
說明 longpredicate參數的設定會被PolarDB忽略。一個PolarDB政策函數能返回一個對於所有實際用途不限長度的謂語。
sec_relevant_colssec_relevant_colsobject_name列的逗號分隔的列表。它可以給列出的列提供列層級的虛擬私人資料庫。如果所列出的列引用於statement_types中列出的SQL命令類型中,那麼政策將被執行。如果沒有引用這樣的列,則不會執行政策。

預設值為NULL,預設值和sec_relevant_cols 包括了所有資料庫物件的列一樣,有相同的效果。

sec_relevant_cols_opt在Oracle環境下,如果將sec_relevant_cols_opt設為DBMS_RLS.ALL_ROWS(INTEGER常量值1),那麼在sec_relevant_cols中列出的列就會返回所有記錄的NULL值。其中,記錄中應用的政策謂語為假。如果沒有把sec_relevant_cols_opt設為DBMS_RLS.ALL_ROWS,那麼結果集中將不會有這些記錄返回。,預設值為NULL。
說明 PolarDB不支援DBMS_RLS.ALL_ROWS函數。如果將sec_relevant_cols_opt設為DBMS_RLS.ALL_ROWS(INTEGER常量值1),那麼PolarDB就會產生錯誤。

樣本

CREATE OR REPLACE FUNCTION verify_session_user (
    p_schema        VARCHAR2,
    p_object        VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
    RETURN 'authid = SYS_CONTEXT(''USERENV'', ''SESSION_USER'')';
END;

此函數產生的謂語authid = SYS_CONTEXT('USERENV', 'SESSION_USER')被添加到在ADD_POLICY預存程序中指定類型的任何SQL命令的WHERE子句中。

此函數對那些列authid內容與會話使用者相同的記錄限制了SQL命令的結果。

說明 這個樣本中使用的SYS_CONTEXT函數用於返回登入使用者名稱。在Oracle環境下,SYS_CONTEXT函數用於返回一個application context的屬性。SYS_CONTEXT函數的第一個參數是一個應用內容相關的名稱。第二個參數則是應用上下文中的屬性集的名稱。USERENV是一個特殊的內建命名空間,用來描述當前會話。PolarDB除支援SYS_CONTEXT函數的特殊用法以外,不支援應用上下文。

下列匿名代碼塊調用了ADD_POLICY預存程序。從而建立名為secure_update的政策。 通過使用函數verify_session_user,可以把政策secure_update應用於表vpemp之上,即使在參考資料表vpemp時,是否給出了一個INSERT、 UPDATE或DELETE命令。

DECLARE
    v_object_schema         VARCHAR2(30) := 'public';
    v_object_name           VARCHAR2(30) := 'vpemp';
    v_policy_name           VARCHAR2(30) := 'secure_update';
    v_function_schema       VARCHAR2(30) := 'polardb';
    v_policy_function       VARCHAR2(30) := 'verify_session_user';
    v_statement_types       VARCHAR2(30) := 'INSERT,UPDATE,DELETE';
    v_update_check          BOOLEAN      := TRUE;
    v_enable                BOOLEAN      := TRUE;
BEGIN
    DBMS_RLS.ADD_POLICY(
        v_object_schema,
        v_object_name,
        v_policy_name,
        v_function_schema,
        v_policy_function,
        v_statement_types,
        v_update_check,
        v_enable
    );
END;

在成功建立政策之後,由使用者salesmgr發起了一個終結會話。下列查詢顯示了表vpemp的內容。

\c polardb salesmgr
Password for user salesmgr: 
You are now connected to database "polardb" as user "salesmgr".
SELECT * FROM vpemp;
 empno | ename  |    job    |   sal   |  comm   | deptno |   authid    
-------+--------+-----------+---------+---------+--------+-------------
  7782 | CLARK  | MANAGER   | 2450.00 |         |     10 | 
  7839 | KING   | PRESIDENT | 5000.00 |         |     10 | 
  7934 | MILLER | CLERK     | 1300.00 |         |     10 | 
  7369 | SMITH  | CLERK     |  800.00 |         |     20 | researchmgr
  7566 | JONES  | MANAGER   | 2975.00 |         |     20 | researchmgr
  7788 | SCOTT  | ANALYST   | 3000.00 |         |     20 | researchmgr
  7876 | ADAMS  | CLERK     | 1100.00 |         |     20 | researchmgr
  7902 | FORD   | ANALYST   | 3000.00 |         |     20 | researchmgr
  7499 | ALLEN  | SALESMAN  | 1600.00 |  300.00 |     30 | salesmgr
  7521 | WARD   | SALESMAN  | 1250.00 |  500.00 |     30 | salesmgr
  7654 | MARTIN | SALESMAN  | 1250.00 | 1400.00 |     30 | salesmgr
  7698 | BLAKE  | MANAGER   | 2850.00 |         |     30 | salesmgr
  7844 | TURNER | SALESMAN  | 1500.00 |    0.00 |     30 | salesmgr
  7900 | JAMES  | CLERK     |  950.00 |         |     30 | salesmgr
(14 rows)

使用者salesmgr發起了一個非模式限定的UPDATE命令(沒有WHERE子句):

UPDATE vpemp SET comm = sal * .75;
UPDATE 6

政策不會更新表中所有的記錄,而是僅對那些authid列中含有salesmgr的記錄限制更新結果。其中,salesmgr值是由政策函數謂語authid = SYS_CONTEXT('USERENV', 'SESSION_USER') 指定的。

下列查詢結果顯示了comm列僅為那些authid列中含有salesmgr的記錄而進行改變。所有其他的記錄不變 。

SELECT * FROM vpemp;
 empno | ename  |    job    |   sal   |  comm   | deptno |   authid    
-------+--------+-----------+---------+---------+--------+-------------
  7782 | CLARK  | MANAGER   | 2450.00 |         |     10 | 
  7839 | KING   | PRESIDENT | 5000.00 |         |     10 | 
  7934 | MILLER | CLERK     | 1300.00 |         |     10 | 
  7369 | SMITH  | CLERK     |  800.00 |         |     20 | researchmgr
  7566 | JONES  | MANAGER   | 2975.00 |         |     20 | researchmgr
  7788 | SCOTT  | ANALYST   | 3000.00 |         |     20 | researchmgr
  7876 | ADAMS  | CLERK     | 1100.00 |         |     20 | researchmgr
  7902 | FORD   | ANALYST   | 3000.00 |         |     20 | researchmgr
  7499 | ALLEN  | SALESMAN  | 1600.00 | 1200.00 |     30 | salesmgr
  7521 | WARD   | SALESMAN  | 1250.00 |  937.50 |     30 | salesmgr
  7654 | MARTIN | SALESMAN  | 1250.00 |  937.50 |     30 | salesmgr
  7698 | BLAKE  | MANAGER   | 2850.00 | 2137.50 |     30 | salesmgr
  7844 | TURNER | SALESMAN  | 1500.00 | 1125.00 |     30 | salesmgr
  7900 | JAMES  | CLERK     |  950.00 |  712.50 |     30 | salesmgr
(14 rows)

由於在ADD_POLICY預存程序中將update_check參數設為TRUE,所以下列INSERT命令會產生異常。 且由於給列authid的researchmgr值與會話使用者salesmgr不匹配,所以使政策失效。

INSERT INTO vpemp VALUES (9001,'SMITH','ANALYST',3200.00,NULL,20, 'researchmgr');
ERROR:  policy with check option violation
DETAIL:  Policy predicate was evaluated to FALSE with the updated values

如果您將update_check設為FALSE,上面描述的INSERT命令就會生效。

下列樣本說明了要應用於政策的sec_relevant_cols參數僅在SQL命令中引用特定列時使用。樣本中的政策函數選擇了員工薪水少於2000的記錄。

CREATE OR REPLACE FUNCTION sal_lt_2000 (
    p_schema        VARCHAR2,
    p_object        VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN
    RETURN 'sal < 2000';
END;

建立政策是為了在SELECT命令包括sal或comm列時,執行所建立的政策:

DECLARE
    v_object_schema         VARCHAR2(30) := 'public';
    v_object_name           VARCHAR2(30) := 'vpemp';
    v_policy_name           VARCHAR2(30) := 'secure_salary';
    v_function_schema       VARCHAR2(30) := 'polardb';
    v_policy_function       VARCHAR2(30) := 'sal_lt_2000';
    v_statement_types       VARCHAR2(30) := 'SELECT';
    v_sec_relevant_cols     VARCHAR2(30) := 'sal,comm';
BEGIN
    DBMS_RLS.ADD_POLICY(
        v_object_schema,
        v_object_name,
        v_policy_name,
        v_function_schema,
        v_policy_function,
        v_statement_types,
        sec_relevant_cols => v_sec_relevant_cols
    );
END;

如果一個查詢沒有引用列sal或comm,即沒有應用政策。下列查詢返回的是表vpemp的14行記錄:

SELECT empno, ename, job, deptno, authid FROM vpemp;
 empno | ename  |    job    | deptno |   authid    
-------+--------+-----------+--------+-------------
  7782 | CLARK  | MANAGER   |     10 | 
  7839 | KING   | PRESIDENT |     10 | 
  7934 | MILLER | CLERK     |     10 | 
  7369 | SMITH  | CLERK     |     20 | researchmgr
  7566 | JONES  | MANAGER   |     20 | researchmgr
  7788 | SCOTT  | ANALYST   |     20 | researchmgr
  7876 | ADAMS  | CLERK     |     20 | researchmgr
  7902 | FORD   | ANALYST   |     20 | researchmgr
  7499 | ALLEN  | SALESMAN  |     30 | salesmgr
  7521 | WARD   | SALESMAN  |     30 | salesmgr
  7654 | MARTIN | SALESMAN  |     30 | salesmgr
  7698 | BLAKE  | MANAGER   |     30 | salesmgr
  7844 | TURNER | SALESMAN  |     30 | salesmgr
  7900 | JAMES  | CLERK     |     30 | salesmgr
(14 rows)

如果查詢引用了列sal或comm,這個查詢則應用了政策。然後這個查詢刪除了任何sal大於或等於2000的記錄。如下所示:

SELECT empno, ename, job, sal, comm, deptno, authid FROM vpemp;
 empno | ename  |   job    |   sal   |  comm   | deptno |   authid    
-------+--------+----------+---------+---------+--------+-------------
  7934 | MILLER | CLERK    | 1300.00 |         |     10 | 
  7369 | SMITH  | CLERK    |  800.00 |         |     20 | researchmgr
  7876 | ADAMS  | CLERK    | 1100.00 |         |     20 | researchmgr
  7499 | ALLEN  | SALESMAN | 1600.00 | 1200.00 |     30 | salesmgr
  7521 | WARD   | SALESMAN | 1250.00 |  937.50 |     30 | salesmgr
  7654 | MARTIN | SALESMAN | 1250.00 |  937.50 |     30 | salesmgr
  7844 | TURNER | SALESMAN | 1500.00 | 1125.00 |     30 | salesmgr
  7900 | JAMES  | CLERK    |  950.00 |  712.50 |     30 | salesmgr
(8 rows)

DROP_POLICY

DROP_POLICY預存程序用於刪除已有的政策。但DROP_POLICY預存程序不能刪除與政策相關的政策函數及資料庫物件。
說明 只有超級使用者才能執行DROP_POLICY預存程序。
DROP_POLICY(object_schema VARCHAR2, object_name VARCHAR2,

  policy_name VARCHAR2)

參數

參數名稱描述
object_schema資料庫物件(政策應用於此資料庫物件之上)的模式名稱。
object_name資料庫物件(政策應用於此資料庫物件之上)的名稱。
policy_name要刪除的政策名稱。

樣本

下列樣本刪除了應用於表public. Vpemp的secure_update政策:

DECLARE
    v_object_schema         VARCHAR2(30) := 'public';
    v_object_name           VARCHAR2(30) := 'vpemp';
    v_policy_name           VARCHAR2(30) := 'secure_update';
BEGIN
    DBMS_RLS.DROP_POLICY(
        v_object_schema,
        v_object_name,
        v_policy_name
    );
END;

ENABLE_POLICY

ENABLE_POLICY預存程序用於啟用或禁用指定資料庫物件上已有的政策。
說明 只有超級使用者才能執行ENABLE_POLICY預存程序。
ENABLE_POLICY(object_schema VARCHAR2, object_name VARCHAR2,
  policy_name VARCHAR2, enable BOOLEAN)

參數

參數名稱描述
object schema資料庫物件(政策應用於此資料庫物件之上)的模式名稱。
object name資料庫物件(政策應用於此資料庫物件之上)的名稱。
policy name要啟用或禁用的政策名稱。
enable啟用或禁用政策。
  • 設定為TRUE時,啟用政策。
  • 設定為FALSE時,禁用政策。

樣本

下列樣本禁用了表public .vpemp上的secure_update政策:

DECLARE
    v_object_schema         VARCHAR2(30) := 'public';
    v_object_name           VARCHAR2(30) := 'vpemp';
    v_policy_name           VARCHAR2(30) := 'secure_update';
    v_enable                BOOLEAN := FALSE;
BEGIN
    DBMS_RLS.ENABLE_POLICY(
        v_object_schema,
        v_object_name,
        v_policy_name,
        v_enable
    );
END;