#强制访问控制
YashanDB支持基于标签的访问控制,可以实现行级的强访问控制,根据用户的标签以及数据的标签来控制数据访问,精准控制用户对表中各行数据的读写权限,保证读写数据的安全。
# 基本原理
LBAC是强访问控制的一种方式,通过向表应用标签策略自动在目标表中新增一列记录每行数据的标签(Label),以行为颗粒度对数据进行分级和分类,再为用户分配不同的标签限制其对数据的访问权限。策略与表的应用(关联)关系允许多对多,策略应用后立即生效。
标签策略(Label Policy):用于定义标签的格式与验证规则,通过应用策略将标签与表、用户建立关联关系。
标签:由等级(Level)和范围(Compartment)组成,通常表示为
等级1,等级2…:范围1,范围2…。等级:用于定义受保护数据的敏感度等级,数值越大表示敏感度越高,例如使用10表示“公共”、20表示“机密”。
范围:用于对受保护数据进行分类,例如使用1表示“员工信息”、2表示“客户信息”。
当用户尝试访问受保护数据时,该用户的安全标签将与受保护数据的标签进行比较:
对于读访问(SELECT):用户只允许查询被LBAC授权可读的行,须同时满足以下要求:
用户的最大读标签中的等级值(DBA_SA_USER_LABELS视图中的MAX_READ_LABEL所对应的等级值) ≥ 目标数据行标签中的等级值
用户标签中的范围集包含目标数据标签中的所有范围
对于写访问(INSERT、UPDATE、DELETE):用户只允许修改、删除或插入被LBAC授权可写的行,须同时满足以下要求:
用户的最小写标签中的等级值(DBA_SA_USER_LABELS视图中的MIN_WRITE_LABEL所对应的等级值) ≥ 目标数据行标签中的等级值
用户标签中的范围集包含目标数据标签中的所有可写范围
# 配置行访问控制
行访问控制仅适用于HEAP表。
所有LBAC相关的配置操作均由具备LBAC_DBA角色的用户来执行。
配置行访问控制后,可以通过以下视图可获取LBAC标签策略相关信息:
DBA_SA_POLICIES:查看当前数据库中的所有LBAC标签策略
DBA_SA_LEVELS:查看LBAC标签策略中的等级
DBA_SA_COMPARTMENTS:查看LBAC标签策略中的范围
DBA_SA_LABELS:查看LBAC标签策略中的标签
DBA_SA_TABLE_POLICIES:查看所有已配置行访问控制的表及其对应的策略信息
DBA_SA_USER_LABELS:查看所有访问受控的用户及其对应的策略、标签信息
# 准备测试用户与数据表
以DBA用户连接并登录数据库。
$ yasql sales/********@192.168.1.2:1688 YashanDB SQL Enterprise Edition Release {version_number} x86_64 Connected to: YashanDB Server Enterprise Edition Release {version_number} x86_64 - Linux SQL>准备LBAC_DBA角色的用户和2个业务用户。
CREATE USER LBACDBA IDENTIFIED BY Yr_pswd0; GRANT LBAC_DBA,DBA TO LBACDBA; CREATE USER sales1 IDENTIFIED BY Yr_pswd1; GRANT CONNECT,CREATE ANY TABLE,SELECT ANY TABLE,INSERT ANY TABLE TO sales1; CREATE USER sales2 IDENTIFIED BY Yr_pswd2; GRANT CONNECT,CREATE ANY TABLE,SELECT ANY TABLE,INSERT ANY TABLE,UPDATE ANY TABLE TO sales2;切换登录测试用户sales1,并准备数据表。
conn sales1/******** DROP TABLE IF EXISTS product_lbac; CREATE TABLE product_lbac (product_no CHAR(5) PRIMARY KEY, product_name VARCHAR2(30), cost NUMBER, price NUMBER ); INSERT INTO product_lbac VALUES ('10001','product001',8,10); SELECT product_no,product_name,cost,price FROM product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE ---------- --------------------------------- ----------- ----------- 11001 product001 8 10
# 开启行访问控制功能
切换登录LBAC_DBA角色的用户。
conn LBACDBA/********查询DBA_YLS_STATUS视图获取行访问控制功能的状态。
SELECT name,status FROM DBA_YLS_STATUS; NAME STATUS ---------------------------------------------------------------- --------- YLS_ENABLE_STATUS FALSE若暂未开启行访问控制功能,需调用YLS_ENFORCEMENT.ENABLE_YLS开启该功能。
CALL YLS_ENFORCEMENT.ENABLE_YLS; SELECT name,status FROM DBA_YLS_STATUS; NAME STATUS ---------------------------------------------------------------- --------- YLS_ENABLE_STATUS TRUE
# 为数据配置标签策略
调用SA_SYSDBA.CREATE_POLICY创建LBAC标签策略。
CALL SA_SYSDBA.CREATE_POLICY ('product_lbac', 'policy_col', 'READ_CONTROL,WRITE_CONTROL'); SELECT policy_name,column_name,status,policy_options FROM DBA_SA_POLICIES WHERE POLICY_NAME = 'PRODUCT_LBAC'; POLICY_NAME COLUMN_NAME STATUS POLICY_OPTIONS -------------------- ---------------------- --------- ---------------------------------------------------------------- PRODUCT_LBAC POLICY_COL ENABLED READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL调用SA_COMPONENTS.CREATE_LEVEL为LBAC标签策略创建等级。
CALL SA_COMPONENTS.CREATE_LEVEL ('product_lbac', 100, 'low', 'low_level'); CALL SA_COMPONENTS.CREATE_LEVEL ('product_lbac', 200, 'mid', 'middle_level'); CALL SA_COMPONENTS.CREATE_LEVEL ('product_lbac', 300, 'high', 'high_level'); CALL SA_COMPONENTS.CREATE_LEVEL ('product_lbac', 500, 'top', 'top_level'); SELECT policy_name,level_num,short_name FROM DBA_SA_LEVELS WHERE POLICY_NAME = 'PRODUCT_LBAC'; POLICY_NAME LEVEL_NUM SHORT_NAME ---------------------------- --------- --------------------- RODUCT_LBAC 100 LOW PRODUCT_LBAC 200 MID PRODUCT_LBAC 300 HIGH PRODUCT_LBAC 500 TOP调用SA_COMPONENTS.CREATE_COMPARTMENT为LBAC标签策略创建范围。
CALL SA_COMPONENTS.CREATE_COMPARTMENT ('product_lbac', 100, 'MNG', 'MANAGER'); CALL SA_COMPONENTS.CREATE_COMPARTMENT ('product_lbac', 200, 'QA', 'QAT'); CALL SA_COMPONENTS.CREATE_COMPARTMENT ('product_lbac', 300, 'RD', 'RDB'); CALL SA_COMPONENTS.CREATE_COMPARTMENT ('product_lbac', 500, 'EG', 'EGA'); SELECT policy_name,comp_num,short_name FROM DBA_SA_COMPARTMENTS WHERE POLICY_NAME = 'PRODUCT_LBAC'; POLICY_NAME COMP_NUM SHORT_NAME ---------------------------- -------- --------------------- PRODUCT_LBAC 100 MNG PRODUCT_LBAC 200 QA PRODUCT_LBAC 300 RD PRODUCT_LBAC 500 EG调用SA_LABEL_ADMIN.CREATE_LABEL,为LBAC标签策略创建标签。
CALL SA_LABEL_ADMIN.CREATE_LABEL ('product_lbac', 100000, 'low'); CALL SA_LABEL_ADMIN.CREATE_LABEL ('product_lbac', 200200, 'mid:QA'); CALL SA_LABEL_ADMIN.CREATE_LABEL ('product_lbac', 300300, 'high:RD'); CALL SA_LABEL_ADMIN.CREATE_LABEL ('product_lbac', 500500, 'top:MNG,QA,RD,EG'); SELECT policy_name,label,label_tag,label_type FROM DBA_SA_LABELS WHERE POLICY_NAME = 'PRODUCT_LBAC'; POLICY_NAME LABEL LABEL_TAG LABEL_TYPE ---------------------------- --------------------- --------------------- ----------------- PRODUCT_LBAC LOW 100000 USER/DATA LABEL PRODUCT_LBAC MID:QA 200200 USER/DATA LABEL PRODUCT_LBAC HIGH:RD 300300 USER/DATA LABEL PRODUCT_LBAC TOP:MNG,QA,RD,EG 500500 USER/DATA LABEL调用SA_POLICY_ADMIN.APPLY_TABLE_POLICY将LBAC标签策略应用至目标数据表。
CALL SA_POLICY_ADMIN.APPLY_TABLE_POLICY ('product_lbac', 'sales1', 'product_lbac'); SELECT policy_name,schema_name,table_name,status,table_options FROM DBA_SA_TABLE_POLICIES WHERE POLICY_NAME = 'PRODUCT_LBAC'; POLICY_NAME SCHEMA_NAME TABLE_NAME STATUS TABLE_OPTIONS ---------------------------- -------------- -------------- --------- ---------------------------------------------------------------- PRODUCT_LBAC SALES1 PRODUCT_LBAC ENABLED READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL -- 查看目标表的结构 desc sales1.product_lbac NAME NULL? DATATYPE ------------------------------ --------- --------------------------------- PRODUCT_NO NOT NULL CHAR(5) PRODUCT_NAME VARCHAR(30) COST NUMBER PRICE NUMBER POLICY_COL BIGINT从回显信息可知,目标表中已自动增加策略列
policy_col。后续插入表数据时,可为每行数据自定义配置不同的标签值,但必须使用与关联策略中已存在的标签值。
# 为用户配置标签策略
调用SA_USER_ADMIN.SET_USER_LABELS向目标用户应用标签策略,设置目标用户的标签。
CALL SA_USER_ADMIN.SET_USER_LABELS ('product_lbac', 'sales1', 'high:RD'); CALL SA_USER_ADMIN.SET_USER_LABELS ('product_lbac', 'sales2', 'mid:QA'); SELECT user_name,policy_name,max_read_label,max_write_label,min_write_label FROM DBA_SA_USER_LABELS WHERE POLICY_NAME = 'PRODUCT_LBAC'; USER_NAME POLICY_NAME MAX_READ_LABEL MAX_WRITE_LABEL MIN_WRITE_LABEL -------------- ---------------------------- --------------------- --------------------- --------------------- SALES1 PRODUCT_LBAC HIGH:RD HIGH:RD LOW SALES2 PRODUCT_LBAC MID:QA MID:QA LOW
# 检验访问控制效果
验证用户sales1的访问控制是否生效。
)切换登录测试用户sales1。
conn sales1/********)查看测试表product_lbac的数据。
SELECT product_no,product_name,cost,price,policy_col FROM product_lbac; -- 无法再查看历史数据(11001,product001,8,10)策略应用到表时,不会为表中已存在的历史数据行指定标签值,该类数据将无法被普通用户读写(仅sys可读写)。
)插入数据至测试表product_lbac。
-- 正确示例 INSERT INTO product_lbac VALUES ('10002','product002',13,16,100000); INSERT INTO product_lbac VALUES ('10003','product003',199,200,300300); -- 错误示例:不允许指定比用户标签等级高的标签值 INSERT INTO product_lbac VALUES ('10004','product004',199,200,500500); -- 错误示例:不允许指定为不存在的标签值 INSERT INTO product_lbac VALUES ('10005','product005',1995,2200,600000); COMMIT;)再次查看测试表product_lbac的数据。
SELECT product_no,product_name,cost,price,policy_col FROM product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE POLICY_COL ---------- --------------------------------- ----------- ----------- --------------------- 10002 product002 13 16 100000 10003 product003 199 200 300300
验证用户sales2的访问控制是否生效。
)切换登录测试用户sales2。
conn sales2/********)查看测试表product_lbac的数据。
SELECT product_no,product_name,cost,price,policy_col FROM sales1.product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE POLICY_COL ---------- --------------------------------- ----------- ----------- --------------------- 10002 product002 13 16 100000sales2用户的标签为
MID:QA,只能查看等级比MID低且范围属于QA子集(空集亦为子集)的数据行。)对测试表product_lbac执行写操作。
-- 正确示例 INSERT INTO sales1.product_lbac VALUES ('10007','product007',80,120,200200); UPDATE sales1.product_lbac SET PRICE = 25 WHERE PRODUCT_NO = 10002; -- 错误示例:不允许更新不具有读写权限的现有数据行 UPDATE sales1.product_lbac SET PRICE = 269 WHERE PRODUCT_NO = 10003; COMMIT;)再次查看测试表product_lbac的数据。
SELECT product_no,product_name,cost,price,policy_col FROM sales1.product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE POLICY_COL ---------- --------------------------------- ----------- ----------- --------------------- 10002 product002 13 25 100000 10007 product007 80 120 200200)切换登录LBAC_DBA角色的用户,更新sales2的标签。
conn LBACDBA/******** CALL SA_USER_ADMIN.SET_USER_LABELS ('product_lbac', 'sales2', 'top:MNG,QA,RD,EG');)切换登录测试用户sales2,对测试表product_lbac进行读写操作。
conn sales2/******** SELECT product_no,product_name,cost,price,policy_col FROM sales1.product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE POLICY_COL ---------- --------------------------------- ----------- ----------- --------------------- 10002 product002 13 16 100000 10003 product003 199 200 300300 10007 product007 80 120 200200 UPDATE sales1.product_lbac SET PRICE = 269 WHERE PRODUCT_NO = 10003; SELECT product_no,product_name,cost,price,policy_col FROM sales1.product_lbac; PRODUCT_NO PRODUCT_NAME COST PRICE POLICY_COL ---------- --------------------------------- ----------- ----------- --------------------- 10002 product002 13 16 100000 10003 product003 199 269 300300 10007 product007 80 120 200200sales2用户的标签权限范围扩大后,可读写的数据行变多。

