MaxCompute supports row-level access control to help manage the permissions of users or roles to access specific data in MaxCompute tables. You can define matching rules between users and the data that is allowed to access in a MaxCompute table to allow specific users or roles to view only the data that they have permissions to access. This improves data security and compliance.
Background information
MaxCompute tables contain a large amount of data. In data sharing scenarios, data administrators want specific users to access only the rows that they have permissions to access. To restrict user access to specific rows, administrators must create a view or an extract, transform, and load (ETL) task to filter data for each user and transfer the data to another table before authorization.
The row-level access control feature allows administrators to authorize users to access specific table data without the need to migrate and copy data or create and maintain views.
The row-level access control feature is suitable for the following scenarios:
SQL queries
Download of table data by using Tunnel commands
Reading of table data by using an external engine, such as Spark and Flink
Engines, such as Hologres, that do not support the row-level access control feature of MaxCompute, cannot access protected data. However, you can still filter and share data by using views or transferring data to another table.
Limits
The row-level access control feature has the following limits:
Only administrators (Admin role and table owner) can configure row-level access policies.
You cannot configure row-level access policies for transactional tables, views, and materialized views. You cannot create materialized views for tables for which row-level access policies are configured or add row-level access policies to base tables of materialized views. However, you can create views based on tables for which row-level access policies are configured. The query results of views are determined by the row-level access policies that are configured for the base tables and the view rules defined by the view owner.
You cannot perform the schema evolution operation on a table for which row-level access policies are configured.
You cannot add a table for which row-level access policies are configured as a resource of a user-defined function (UDF). You cannot configure row-level access policies for a table that is added as a resource of a UDF. If you perform these operations, no immediate error is reported. However, when the related UDF is executed, an error is reported.
You cannot add masking rules to fields in a table for which row-level access policies are configured.
Row-level access control does not support partition pruning. For example, if the
ds
field is a partition field, you may need to start a full table scan to filter data even if a filter condition similar tods='20220101'
is specified in filter_expr. For more information about filter_expr, see Limits on filter_expr.
Package-based cross-project access to a table for which row-level access policies are configured has the following limits:
You can attach row-level access policies to a user who is not added to the current project. The user can be an Alibaba Cloud account or a RAM user of the current tenant.
If you use a table for which row-level access policies are configured in another project, only user policies or default policies may be met and data is filtered based on the policies.
You cannot add row-level access policies to a table that has row-level access policies in the package.
Precautions
The execution of operators or functions that are used in filter_expr may be affected by flag parameters. The system checks whether the parameter settings used during queries are consistent with the parameter settings that are configured during policy creation. If they are inconsistent, the following error message appears:
FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: java.lang.IllegalArgumentException: Row access policy flag mismatch for: xxx
Before you run a command related to row-level access control, such as CREATE, DROP, DESC, or LIST, you must configure the following Grand Unified Configuration (GUC) parameter at the session level to enable the row-level access control feature.
NoteThe row-level access control feature will be enabled at the session level by default in the future. Take note of the documentation announcements or instructions.
SET odps.sql.row.policy.enabled=true;
When you execute an SQL statement to query data in a table for which row-level access control is enabled, the amount of input data that is charged in the pay-as-you-go billing method is not reduced due to data filtering because row-level access control does not support partition pruning. A user who is attached row-level access policies may obtain filtered results even if the user specifies a full table query in an SQL expression. The amount of scanned data in the source table may be greater than the amount of data that the user estimates based on the results. You need to reduce the amount of data to be scanned to control costs.
The method of creating multiple views or tables with different user-specific filtering rules and sharing them can achieve row-level access control, allowing computations to be performed on the filtered data, making operations more convenient and intuitive. For more details, see Perform row-level access control. Compared to the method of creating shared objects for each user, row-level access control makes the query execution plans based on the original table more complex. However, it eliminates the need to create shared objects individually for each user and avoids redundant storage of shared objects. It is also more suitable for defining rules for large numbers of users, allowing you to use it flexibly according to your needs.
Syntax
You can execute the CREATE/REPLACE, DROP, DESC, and LIST statements to create (or modify), drop, or view row-level access policies.
CREATE/REPLACE
Syntax
CREATE [OR REPLACE] ROW ACCESS POLICY [IF NOT EXISTS] <policy_name> ON <table_name> TO <authorized_objects> FILTER USING <filter_expr> [AS <clause>];
Description
Creates or modifies a row-level access policy to grant permissions to the specified object (user or role).
Parameters
Parameter
Description
policy_name
The name of the row-level access policy. You can specify a custom name.
table_name
The name of the table to be accessed.
authorized_objects
The object to which permissions are granted. Valid values:
USER <user_list>
: the names of the users to which permissions are granted. Separate multiple user names with commas (,).ROLE <role_list>
: the names of the roles to which permissions are granted. Separate multiple role names with commas (,).DEFAULT
: the default policy when a user policy or role policy is not met.
filter_expr
The filter expression. For more information, see Limits on filter_expr.
clause
The attributes of the row-level access policy. Valid values:
PERMISSIVE
andRESTRICTIVE
. For more information, see Specify the PERMISSIVE or RESTRICTIVE attribute.Limits on filter_expr
filter_expr has the following limits in this version:
The value of filter_expr must be a scalar expression and of the BOOLEAN data type.
filter_expr cannot contain subqueries or statements such as SELECT, CREATE, and UPDATE.
filter_expr can reference only constants or fields in the authorized table. filter_expr cannot reference fields in other tables.
filter_expr can contain built-in operators of MaxCompute, including relational operators, arithmetic operators, bitwise operators, and logical operators. For more information, see Operators.
filter_expr can contain only specific built-in scalar functions. This parameter cannot call UDFs, aggregate functions, or window functions. filter_expr supports the following functions:
String functions: CONCAT, CONCAT_WS, GET_JSON_OBJECT, INSTR, LENGTH, LENGTHB, REGEXP_EXTRACT, REGEXP_REPLACE, REVERSE, SUBSTR, TOLOWER, TOUPPER, TRIM, LTRIM, RTRIM, and REPLACE.
Mathematical functions: ABS and ROUND.
Time functions: DATEADD, TO_DATE, and TO_CHAR.
Other functions: SIZE, FIELD, COALESCE, IF, and SPLIT.
Description of the PERMISSIVE and RESTRICTIVE attributes
Multiple policies may take effect on a specific user. The system combines multiple policies to determine whether the user can access a row of data. When you create a row-level access policy, you can use
AS {PERMISSIVE | RESTRICTIVE}
to specify the PERMISSIVE or RESTRICTIVE attribute for the policy. If you do not specify the attribute, the default value is PERMISSIVE. Example:Multiple policies take effect on a user.
If the attributes of the policies are PERMISSIVE, the relationship between the policies is OR. In this case, the user can access a row of data if the value of filter_expr in one of the policies is true.
If the attributes of the policies are RESTRICTIVE, the relationship between the policies is AND. In this case, the user can access a row of data only if all policies are met.
If the attributes of specific policies are PERMISSIVE and the attributes of other policies are RESTRICTIVE, the user can access a row of data only if the following two conditions are met:
At least one of the policies whose attributes are PERMISSIVE is met.
All policies whose attributes are RESTRICTIVE are met.
NoteEach time you add a row-level access policy to a table, you must evaluate the overall effect of the combination of all row-level access policies on the table. For example, if a RESTRICTIVE policy and a PERMISSIVE policy are configured for a user at the same time, the PERMISSIVE policy must also be met.
Scenarios
Grant permissions to the specified user.
In this example, a table named table01 contains a field whose data type is STRING and whose column name is
region
. Configure a row-level access policy for specific users to allow the users to access only the records in which the value in theregion
field ischina
. Sample statement:CREATE ROW ACCESS POLICY policy01 ON table01 TO USER (aliyun$odps_test01@aliyun.com,aliyun$odps_test02@aliyun.com) FILTER USING (region = "china");
Grant permissions to the specified role.
In this example, two roles named
role1
androle2
exist in the system. Grant permissions to the two roles so that they can access only records whose value in theregion
field ischina
. Sample statement:CREATE ROW ACCESS POLICY policy02 ON table01 TO ROLE (role1, role2) FILTER USING (region = "china");
Grant permissions to the default user.
For example, approximately 100 potential users may access a specific table. The administrator separately grants permissions to one of the users by using the authorization command. Access control is also required for other users. If you grant permissions to a specific user or role on the table, row-level access control is enabled for the table. Other users cannot access data in the table because they do not have access permissions on the table. In this case, the administrator can execute the following statement to modify the access permissions of the default user.
By default, other users are not allowed to access the table. This is the same as the effect of specifying that the default user does not have access permissions.
CREATE ROW ACCESS POLICY policy03 ON table01 TO DEFAULT FILTER USING (false);
If you want to restrict the default user to access only the records in which the value of the
region
field isother
, execute the following statement:CREATE ROW ACCESS POLICY policy04 ON table01 TO default FILTER USING (region = "other");
ImportantWhen you add a row-level access policy to a table for a specific user, you must consider the access behavior of other users. If the table has been accessed by other users, you must also configure a policy to allow access from the users to avoid unexpected access prohibition errors.
Authentication logic
The following figure shows the authentication process when a user accesses a table for which row-level access policies are configured.
DROP
Drops a specific policy from a table.
DROP ROW ACCESS POLICY <policy_name> ON <table_name>;
Drops all policies from a table.
DROP ALL ROW ACCESS POLICY ON <table_name>;
DESC
Views the permission details of a policy on a table.
DESC ROW ACCESS POLICY <policy_name> ON <table_name>;
LIST
Lists all policies in a table.
LIST ROW ACCESS POLICY ON <table_name>;
Views the policies that are configured for a user in a table.
LIST ROW ACCESS POLICY ON <table_name> TO USER <user_name>;
Views the policies that are configured for a role in a table.
LIST ROW ACCESS POLICY ON <table_name> TO ROLE <role_name>;
Sample code
Create a table named policy_test and insert data into the table. Sample statements:
-- Create a table.
CREATE TABLE policy_test(a bigint, b string);
-- Insert data into the table.
INSERT overwrite TABLE policy_test VALUES(1L, "1"), (2L, "2"), (3L, "3"), (4L, "4");
-- Check the inserted data.
SELECT * FROM policy_test;
-- Returned result:
+------------+---+
| a | b |
+------------+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+------------+---+
Examples
The following examples show how to grant row-level access permissions to the default user. Before authorization, you must prepare sample data.
Example 1: Add a row-level access policy to the policy_test table to allow the default user to access data in the
a=2L
row in the table.Create the row-level access policy policy01.
CREATE row access policy policy01 ON policy_test TO default filter using (a = 2L);
View the specific permissions of policy01 in the policy_test table.
DESC row access policy policy01 on policy_test;
Returned result:
-- The following result is returned. The value of Restrictive is false, which is the default value. 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
Query data in the policy_test table to check whether the authorization takes effect.
SELECT * FROM policy_test;
Returned result:
-- The following result is returned. The policy takes effect and only specific records are returned. +------------+---+ | a | b | +------------+---+ | 2 | 2 | +------------+---+
Example 2: Add two row-level access policies whose attributes are PERMISSIVE to a table to allow the default user to access data in the
a=2L
anda=3L
rows in the policy_test table.Create the row-level access policy policy02.
CREATE row access policy policy02 ON policy_test TO default filter using (a = 3L);
List all policies in the policy_test table.
LIST row access policy ON policy_test;
Returned result:
-- The following result is returned: 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
Query data in the policy_test table to check whether the authorization takes effect.
SELECT * FROM policy_test;
Returned result:
-- Two policies policy01 and policy02 take effect at the same time. The attributes of both policies are PERMISSIVE. Therefore, two records are returned. +------------+---+ | a | b | +------------+---+ | 2 | 2 | | 3 | 3 | +------------+---+
Example 3: Add two row-level access policies whose attributes are PERMISSIVE and one row-level access policy whose attribute is RESTRICTIVE to a table to allow the default user to access data that meets the (
a=2L
||a=3L
)&&a<3L
condition in the policy_test table.Create the row-level access policy policy03 and set the attribute of the policy to RESTRICTIVE.
CREATE row access policy policy03 ON policy_test TO default filter using (a < 3L) as restrictive;
View the permissions of policy03 in the policy_test table.
DESC row access policy policy03 ON policy_test;
Returned result:
-- The following result is returned. The value of Restrictive is 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
Query data in the policy_test table to check whether the authorization takes effect.
select * from policy_test;
Returned result:
-- The following result is returned. In this example, policy01, policy02, and policy03 take effect at the same time. -- The attributes of policy01 and policy02 are PERMISSIVE. Therefore, the default user can access the table when one of the two policies is met. -- The attribute of policy03 is RESTRICTIVE. Therefore, the default user can access the table only when this policy is met. +------------+---+ | a | b | +------------+---+ | 2 | 2 | +------------+---+
Example 4: Add a row-level access policy whose attribute is PERMISSIVE and a row-level access policy whose attribute is RESTRICTIVE for a table. The default user can access data of the table only when the two policies are met.
Drop the row-level access policy policy01.
SET odps.sql.row.policy.enabled=true; DROP ROW ACCESS POLICY policy01 ON policy_test;
View the row-level access policies on the policy_test table.
SET odps.sql.row.policy.enabled=true; LIST ROW ACCESS POLICY ON policy_test;
Returned result:
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
Query data in the policy_test table to verify the authorization result.
-- Check the inserted data. SELECT * FROM policy_test;
Returned result:
-- The returned result is empty because policy02 and policy03 take effect at the same time. +------------+------------+ | a | b | +------------+------------+ +------------+------------+
Appendixes
Check of compatible behaviors
When MaxCompute performs calculations based on a filter expression, the result may be affected by flag parameters. If users define a row-level access policy under a compatible behavior and define other row-level access policies under another compatible behavior, data leaks may occur when the result does not meet expectations. Therefore, when MaxCompute performs row-level access control, it checks the compatible behavior that is performed when the row-level access policy is defined. If the compatible behaviors are inconsistent, an error is reported and the access is prohibited.
Example: This example shows the application of a policy under different compatible behaviors based on sample data.
The behavior when the second parameter of the SUBSTR function is set to 0 is affected in the Hive-compatible data type edition. For more information, see SUBSTR.
If the Hive-compatible data type edition is enabled, the result obtained when the start position of the SUBSTR function is 0 is the same as the result obtained when the start position of the SUBSTR function is 1.
SET odps.sql.hive.compatible=true; SELECT substr('abc', 0); -- If the Hive-compatible data type edition is enabled, the result obtained when the start position of the SUBSTR function is 0 is the same as the result obtained when the start position of the SUBSTR function is 1. +-----+ | _c0 | +-----+ | abc | +-----+
If the Hive-compatible data type edition is disabled, the return value is an empty string when the start position of the SUBSTR function is 0.
SET odps.sql.hive.compatible=false; SELECT substr('abc', 0); -- If the Hive-compatible data type edition is disabled, the return value is an empty string when the start position of the SUBSTR function is 0. +-----+ | _c0 | +-----+ | | +-----+
When you create a row-level access policy, the system checks the operators and functions used in filter_expr. If the behaviors of the operators and functions depend on specific flag parameters, the system records these flag parameters in
Settings
. You can execute the DESC statement to view the flag parameters.-- Drop all policies that are configured for a table. DROP ALL row access policy ON policy_test; -- Configure a policy in the Hive-compatible data type edition. The SUBSTR function is used in filter_expr. SET odps.sql.hive.compatible=true; CREATE row access policy policy04 ON policy_test TO default filter using(substr(b, 0)='1'); -- View the policy details in the policy_test table. DESC row access policy policy04 on policy_test;
The following result is returned. The value of the
odps.sql.hive.compatible
parameter is recorded in Settings.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
When the policy is applied, the system determines whether Settings of the current environment are consistent with Settings configured when the policy is created. If they are inconsistent, an error is reported.
In the Hive-compatible data type edition, the policy is applied.
SET odps.sql.hive.compatible=true; SELECT * FROM policy_test;
Returned result:
+------------+---+ | a | b | +------------+---+ | 1 | 1 | +------------+---+
In an edition other than the Hive-compatible data type edition, the query fails because the value of the
odps.sql.hive.compatible
parameter is different from the value that is specified when the policy is created.SET odps.sql.hive.compatible=false; SELECT * FROM policy_test;
Returned result:
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 download behavior
For tables for which row-level access policies are configured, you must comply with the row-level access policies when you use Tunnel commands to download table data. However, MaxCompute Tunnel does not have the computing capabilities to execute the row-level access control filtering logic. The system starts an SQL task to filter data based on the rules and then downloads the computing results of the task.
Therefore, when you use Tunnel commands or Tunnel SDK to download data from a MaxCompute table for which row-level access policies are configured, a period of time is required to wait for the running of the SQL task.
Prohibition of the creation of row-level access policies
If a project administrator wants to prohibit the creation of new row-level access policies in a project, the project administrator can run the following command to modify the project properties:
Only the administrator can change the value of the odps.sql.create.row.policy.disable parameter at the project level by using the setproject
command. Users cannot change the value of this parameter at the session level.
setproject odps.sql.create.row.policy.disable=true;
Valid values:
false: You are allowed to create row-level access policies. This is the default value.
true: You are not allowed to create row-level access policies. You are allowed to modify or drop existing policies.