為了便於控制使用者或角色對MaxCompute表中特定資料的訪問,MaxCompute提供了行級存取控制功能,通過在原表上定義使用者與資料(被允許訪問的資料)的匹配規則,控制特定使用者或角色僅可見其有許可權訪問的資料,從而提升資料安全性和合規性。
背景資訊
MaxCompute表中包含大量資料,在資料共用情境下,資料管理者通常希望特定的使用者只能訪問其被授權訪問的資料行。以前為了控制使用者對特定資料行的訪問,通常需要為每個使用者建立一張視圖來過濾資料,或者通過ETL任務過濾資料,並將其轉存到另一張表中再授權。
行級存取控制功能簡化了管理者授權使用者訪問特定表資料的操作流程,無需搬移、複製資料,或建立、維護視圖,即可實現該功能。
行級存取控制功能適用於以下情境:
SQL查詢。
通過Tunnel下載表資料。
通過外部引擎(如Spark、Flink)讀取表資料。
不支援MaxCompute行級存取控制的引擎(如Hologres),會被禁止訪問受保護的資料,但您仍然可以通過視圖或轉存表方式實現資料過濾共用。
使用限制
行級存取控制的限制如下:
僅支援管理員(Admin角色、表Owner)配置行級訪問規則(Row Access Policy)。
暫不支援對Transactional表、視圖和物化視圖等對象配置行級訪問規則;不支援在添加了行級訪問規則的表上建立物化視圖,或在物化視圖的基礎資料表上增加行級訪問規則;但您可以基於配置了行級訪問規則的表建立視圖,對視圖的查詢結果由基礎資料表上配置的行級訪問規則與視圖Owner定義的視圖規則共同決定。
不支援在配置了行級訪問規則的表上進行Schema Evolution操作。
不支援將配置了行級訪問規則的表添加為UDF的表資源,或者對已經添加為UDF的表資源再配置行級訪問規則。目前添加或設定階段不報錯,只在運行階段報錯。
不支援在配置了行級訪問規則的表上增加欄位脫敏規則。
行級存取控制當前暫不支援分區裁剪。假如
ds
是分區欄位,即使在filter_expr中指定了類似於ds='20220101'
的過濾條件,也可能需要啟動全表掃描來過濾資料。filter_expr詳情請參見filter_expr說明。
通過Package跨專案共用增加了行級許可權的表的限制如下:
支援對未加入專案的使用者(當前租戶的主帳號或RAM子帳號)配置行級許可權。
跨專案使用增加了行級許可權的表時,只有使用者或Default規則可能命中併產生過濾效果。
不允許對Package中增加了行級許可權的表再次增加行級許可權。
注意事項
filter_expr中使用的運算子或函數可能會受各種Flag參數的影響。系統會檢查Query運行時和建立policy時的參數設定是否一致,若不一致則會出現如下報錯資訊。
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.IllegalArgumentException: Row access policy flag mismatch for: xxx
執行行級存取控制相關命令(如CREATE、DROP、DESC或LIST)前,您需要在Session層級設定如下GUC參數,啟用行級存取控制功能。
說明系統後續會預設在Session層級啟用,請關注文檔公告或此處說明。
SET odps.sql.row.policy.enabled=true;
使用SQL查詢添加了行級存取控制的表時,由於行級存取控制不支援分區裁剪,所以後付費計量中的輸入資料量不會因過濾而減少;同時被設定行級訪問規則的使用者即使在SQL運算式中定義了查詢全表資料,仍然可能得到過濾後的結果,掃描源表的資料量可能會大於使用者通過結果判斷的大小,請您注意費用控制。
面向不同使用者和各自過濾規則建立多個視圖或表並進行共用的方式,可實現行級存取控制,並且可以在已過濾資料的基礎上進行計算,操作更為簡便和直觀。詳情請參見行層級許可權控制。相較於面向使用者建立共用對象的方式,行級存取控制會讓基於原表的查詢執行計畫更複雜,但是免去為每個使用者逐個建立共用對象的工作,並避免了共用對象的冗餘儲存,且更適合針對大量使用者定義規則,您可以根據需求靈活使用。
文法說明
您可以通過CREATE/REPLACE、DROP、DESC、LIST命令建立(或修改)、刪除或查看行級訪問規則。
CREATE/REPLACE
命令格式
CREATE [OR REPLACE] ROW ACCESS POLICY [IF NOT EXISTS] <policy_name> ON <table_name> TO <authorized_objects> FILTER USING <filter_expr> [AS <clause>];
命令說明
建立(或修改)行級訪問規則,為指定的對象(使用者或角色)授權。
參數說明
參數
描述
policy_name
行級存取控制許可權的名稱,可自訂。
table_name
訪問的表名稱。
authorized_objects
授權對象。取值如下:
USER <user_list>
:待授權的使用者名稱稱列表,多個使用者名稱稱之間以半形逗號分隔。ROLE <role_list>
:待授權的角色名稱列表,多個角色名稱之間以半形逗號分隔。DEFAULT
:未命中使用者規則或角色規則時的預設規則。
filter_expr
過濾條件運算式,詳情請參見filter_expr說明。
clause
行級訪問規則的屬性。取值為
PERMISSIVE
或RESTRICTIVE
,詳情請參見指定PERMISSIVE或RESTRICTIVE屬性。filter_expr說明。
目前的版本對filter_expr做了較嚴格的約束:
filter_expr必須是一個標量運算式(Scalar Expression),並且取實值型別必須為BOOLEAN類型。
不允許其中存在子查詢和SELECT、CREATE、UPDATE等語句。
filter_expr只能引用常量或者所授權表的欄位,不允許引用其他表的欄位。
支援使用MaxCompute內建的運算子,包括關係運算子、算數運算子、位元運算符和邏輯運算子。詳情請參見運算子。
關於函數:只允許使用部分內建的純量涵式(Builtin Scalar Function),不允許調用使用者自訂的UDF,也不允許調用彙總函式、視窗函數等。支援使用的函數如下:
字串函數:CONCAT、CONCAT_WS、GET_JSON_OBJECT、INSTR、LENGTH、LENGTHB、REGEXP_EXTRACT、REGEXP_REPLACE、REVERSE、SUBSTR、TOLOWER、TOUPPER、TRIM、LTRIM、RTRIM、REPLACE。
數學函數:ABS、ROUND。
時間函數:DATEADD、TO_DATE、TO_CHAR。
其他函數:SIZE、FIELD、COALESCE、IF、SPLIT。
指定PERMISSIVE或RESTRICTIVE屬性。
對某一個使用者來說,可能會有多個Policy對其生效,因此需要將多個Policy結合在一起來確定使用者最終是否可以訪問某一行資料。建立Row Access Policy時,可以通過
AS {PERMISSIVE | RESTRICTIVE}
指定Policy為PERMISSIVE或者RESTRICTIVE屬性,若不指定屬性,則預設為PERMISSIVE。樣本如下:假如有多個Policy對某個使用者生效:
若Policy屬性都為PERMISSIVE,則Policy之間是OR的關係,即對某一行資料而言,只要這些Policy中的任何一個filter_expr的取值為true,使用者就可以訪問此行資料。
若Policy屬性都為RESTRICTIVE,則Policy之間是AND的關係,即對某一行資料而言,必須滿足所有Policy,使用者才可以訪問此行資料。
若其中一部分Policy屬性為PERMISSIVE,另外一部分屬性為RESTRICTIVE,對某一行資料而言,必須同時滿足以下兩點,使用者才可以訪問此行資料。
至少滿足PERMISSIVE屬性的Policy中的其中一條。
滿足所有RESTRICTIVE屬性的Policy。
說明每次對錶增加新的行級許可權規則,都需要整體評估表上所有的行級許可權規則群組合效果。例如當使用者同時存在一條RESTRICTIVE規則和一條PERMISSIVE規則時,這條PERMISSIVE規則也必須被滿足。
使用情境
為指定的使用者(User)單獨授權。
假設表名為table01,其中存在一個資料類型為STRING,且列名為
region
的欄位,為某些使用者佈建行級訪問規則,限制其只能訪問region
欄位中值為china
的記錄。命令樣本如下:CREATE ROW ACCESS POLICY policy01 ON table01 TO USER (aliyun$odps_test01@aliyun.com,aliyun$odps_test02@aliyun.com) FILTER USING (region = "china");
為指定的角色(Role)單獨授權。
假設系統中有兩個角色,分別為
role1
和role2
,為這兩個角色授權,使其只能訪問region
欄位中取值為china
的記錄。命令樣本如下:CREATE ROW ACCESS POLICY policy02 ON table01 TO ROLE (role1, role2) FILTER USING (region = "china");
為Default使用者授權。
假設存在一張表,大約有100個潛在的使用者可能訪問該表。管理員已經針對其中的某個使用者,使用指定使用者授權命令為其單獨進行了授權。對於其餘未指定授權的使用者,也希望能夠進行許可權控制。首先,給某個表增加某個使用者或角色的存取控制,則代表這張表已經被行級存取控制策略管理,其他使用者由於沒有在允許訪問的列表中,所以都失去對錶中資料的存取權限。此時管理員可以使用如下命令修改Default使用者的訪問授權。
預設禁止其他使用者訪問的行為,等同於指定Default使用者都沒有存取權限。
CREATE ROW ACCESS POLICY policy03 ON table01 TO DEFAULT FILTER USING (false);
假如想限制Default使用者只能訪問
region
欄位中值為other
的記錄,命令樣本如下:CREATE ROW ACCESS POLICY policy04 ON table01 TO default FILTER USING (region = "other");
重要對錶增加行級規則時,需要考慮被控制的使用者之外的其他使用者的訪問行為,如果該表之前已經被其他使用者訪問,則需要為他們設定明確的規則,避免產生非預期的禁止訪問報錯。
鑒權處理邏輯
使用者訪問某一張table,假如table上配置了行級訪問規則,則鑒權處理流程如下:
DROP
刪除某張表中的某個特定Policy。
DROP ROW ACCESS POLICY <policy_name> ON <table_name>;
刪除某張表中的所有Policy。
DROP ALL ROW ACCESS POLICY ON <table_name>;
DESC
查看某張表中某個Policy的許可權詳情。
DESC ROW ACCESS POLICY <policy_name> ON <table_name>;
LIST
列出某張表中的所有Policy。
LIST ROW ACCESS POLICY ON <table_name>;
查看某張表中針對某個使用者配置的Policy。
LIST ROW ACCESS POLICY ON <table_name> TO USER <user_name>;
查看某張表中針對某個角色配置的Policy。
LIST ROW ACCESS POLICY ON <table_name> TO ROLE <role_name>;
樣本資料
建立名為policy_test的表,並插入資料。SQL命令如下:
--建立表
CREATE TABLE policy_test(a bigint, b string);
--插入資料
INSERT overwrite TABLE policy_test VALUES(1L, "1"), (2L, "2"), (3L, "3"), (4L, "4");
--檢查插入的資料
SELECT * FROM policy_test;
--返回結果:
+------------+---+
| a | b |
+------------+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+------------+---+
使用樣本
此處以Default使用者授權情境為例,為您介紹行級存取權限的使用。在此之前,您需要提前準備好樣本資料。
樣本1:對一張表增加行級許可權,允許Default使用者訪問policy_test表中
a=2L
的資料。建立行級存取權限policy01。
CREATE row access policy policy01 ON policy_test TO default filter using (a = 2L);
查看policy_test表中policy01的具體許可權。
DESC row access policy policy01 on policy_test;
返回結果:
--返回結果如下,注意Restrictive取預設值false Authorization Type: Row Access Policy Name: policy01 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a = 2L) NormalizedFilterExpr: (policy_test.a = 2L) Restrictive: false Settings: OK
查詢policy_test表資料,驗證授權操作是否生效。
SELECT * FROM policy_test;
返回結果:
--返回結果如下,注意policy生效,只返回了部分記錄 +------------+---+ | a | b | +------------+---+ | 2 | 2 | +------------+---+
樣本2:對一張表增加兩個permissive的行級許可權,允許Default使用者訪問policy_test表中
a=2L
和a=3L
的資料。建立行級存取權限policy02。
CREATE row access policy policy02 ON policy_test TO default filter using (a = 3L);
列出policy_test表中的所有policy。
LIST row access policy ON policy_test;
返回結果:
--返回結果如下: Authorization Type: Row Access Policy Name: policy01 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a = 2L) NormalizedFilterExpr: (policy_test.a = 2L) Restrictive: false Settings: Name: policy02 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a = 3L) NormalizedFilterExpr: (policy_test.a = 3L) Restrictive: false Settings: OK
查詢policy_test表資料,驗證授權操作是否生效。
SELECT * FROM policy_test;
返回結果:
--有兩個policy,policy01和policy02同時起作用,它們都是permissive的,因此返回了兩條記錄 +------------+---+ | a | b | +------------+---+ | 2 | 2 | | 3 | 3 | +------------+---+
樣本3:對一張表增加兩個permissive和一個restrictive的行級許可權,允許Default使用者訪問policy_test表中滿足(
a=2L
||a=3L
)&&a<3L
的資料。建立行級存取權限policy03,並將其屬性設定為RESTRICTIVE。
CREATE row access policy policy03 ON policy_test TO default filter using (a < 3L) as restrictive;
查看policy_test表中policy03的具體許可權。
DESC row access policy policy03 ON policy_test;
返回結果:
--返回結果如下,注意其Restrictive取值為true Authorization Type: Row Access Policy Name: policy03 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a < 3L) NormalizedFilterExpr: (policy_test.a < 3L) Restrictive: true Settings: OK
查詢policy_test表資料,驗證授權操作是否生效。
select * from policy_test;
返回結果:
--返回結果如下,這裡policy01/policy02/policy03同時起作用, --policy01和policy02是permisive的,只要其中有一個滿足就可以。 --而policy03是restrictive的,必須要滿足條件。 +------------+---+ | a | b | +------------+---+ | 2 | 2 | +------------+---+
樣本4:對一張表增加一個permissive和一個restrictive的行級許可權,Default使用者訪問表資料需要同時滿足這兩個條件。
刪除行級存取權限policy01。
SET odps.sql.row.policy.enabled=true; DROP ROW ACCESS POLICY policy01 ON policy_test;
查看policy_test表上的行級許可權。
SET odps.sql.row.policy.enabled=true; LIST ROW ACCESS POLICY ON policy_test;
返回結果:
Authorization Type: Row Access Policy Name: policy02 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a = 3L) NormalizedFilterExpr: (policy_test.a = 3L) Restrictive: false Settings: Name: policy03 Objects: acs:odps:*:projects/clone_table_2/tables/policy_test FilterExpr: (a < 3L) NormalizedFilterExpr: (policy_test.a < 3L) Restrictive: true Settings: OK
查詢policy_test表資料,驗證授權結果。
--檢查插入的資料 SELECT * FROM policy_test;
返回結果:
--返回結果為空白,因為=3和小於3同時生效。 +------------+------------+ | a | b | +------------+------------+ +------------+------------+
附錄
相容行為檢查
MaxCompute在對過濾運算式進行計算時,其行為可能會受Flag參數的影響。如果使用者在某種相容行為下定義了行級訪問規則,但在另一種相容行為下定義了其他行級訪問規則,則會由於結果不符合預期而產生資料泄露,因此執行行級存取控制時,會檢查其定義時的相容行為,如果不一致則會報錯,並禁止訪問。
樣本:此處基於樣本資料,為您展示不同相容行為下Policy的應用。
SUBSTR函數的第2個參數取值為0時的行為,受Hive相容模式的影響。詳情請參見SUBSTR。
Hive相容模式下,SUBSTR函數的起始位置為0時,與起始位置為1時的結果相同。
SET odps.sql.hive.compatible=true; SELECT substr('abc', 0); --在hive相容模式下,起始位置為0時,與起始位置為1時的結果相同。 +-----+ | _c0 | +-----+ | abc | +-----+
非Hive相容模式下,當起始位置為0時,傳回值為空白字串。
SET odps.sql.hive.compatible=false; SELECT substr('abc', 0); --在非hive相容模式下,當起始位置為0時,傳回值為空白字串 +-----+ | _c0 | +-----+ | | +-----+
在建立行級訪問規則時,系統會檢查filter_expr中使用的運算子和函數,假如它們的行為依賴於某些Flag參數,則會將這些Flag參數記錄在
Settings
中,您可以通過DESC命令查看相關Flag參數。--刪除表上配置的所有policy DROP ALL row access policy ON policy_test; --在Hive相容模式下配置policy,filter_expr中使用了SUBSTR函數 SET odps.sql.hive.compatible=true; CREATE row access policy policy04 ON policy_test TO default filter using(substr(b, 0)='1'); --查看policy_test表中配置的policy詳情 DESC row access policy policy04 on policy_test;
返回結果如下:Settings中記錄了
odps.sql.hive.compatible
參數的取值。Authorization Type: Row Access Policy Name: policy04 Objects: acs:odps:*:projects/sql_optimizer/tables/policy_test FilterExpr: substr(b, 0) = '1' NormalizedFilterExpr: ::substr(policy_test.b, 0) = '1' Restrictive: false Settings: odps.sql.hive.compatible=true
後續應用Policy時,會判斷當前環境中的Settings和建立Policy時的Settings是否一致,若不一致則會報錯。
Hive相容模式下,應用Policy。
SET odps.sql.hive.compatible=true; SELECT * FROM policy_test;
返回結果:
+------------+---+ | a | b | +------------+---+ | 1 | 1 | +------------+---+
非Hive相容模式,由於
odps.sql.hive.compatible
參數與建立Policy時的取值不一致,導致Query執行失敗。SET odps.sql.hive.compatible=false; SELECT * FROM policy_test;
返回結果:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.IllegalArgumentException: Row access policy flag mismatch for: odps.sql.hive.compatible, flag value when grant this policy is true, while at runtime is false. please set odps.sql.hive.compatible = true or contact your project manager.
Tunnel下載行為說明
對於配置了行級訪問規則的表,使用Tunnel下載表資料時也需要遵守行級存取控制的規則,但Tunnel本身沒有可以執行行級存取控制過濾邏輯的計算能力,需要啟動SQL任務按照規則進行過濾,然後再下載任務計算的結果。
因此使用Tunnel命令或Tunnel SDK下載配置了行級訪問規則的MaxCompute表資料時,會存在一段等待執行SQL任務的時間。
管理員禁止建立行級許可權
如果專案系統管理員希望禁止在該專案內建立Row Access Policy,可以通過如下命令來修改專案空間屬性。
只允許管理員通過setproject
命令在Project層級進行修改,使用者在Session層級無法修改該參數值。
setproject odps.sql.create.row.policy.disable=true;
取值範圍如下:
false(預設值):允許建立Row Access Policy。
true:不允許建立Row Access Policy,但是允許對已有的Policy進行修改和刪除。