
本文通过一个简单的例子对Oracle Label Security的功能作初步的探讨,本文使用的环境是Oracle Database 11g Enterprise Edition Release 11.2.0.3 for linux 32 bit。
首先我们了解一下实现Oracle Label Security的大体流程。 通过Oracle提供的一系列存储过程,先创建一个policy,然后在policy中创建level,compartment,group,之后通过这些定义好的level,compartment,group再定义label,然后将policy绑定到某张表或者某个schema,最后再给相应的用户设置label。
其中牵涉到几个名词,解释一下:
Policy:就是安全策略,一个安全策略是level,compartment,group,label的集合。
Level:等级,这是最基础的安全控制等级,必须设置。Compartment:分隔,提供第二级的安全控制,是可选的。
Group:组,提供第三级的安全控制,是可选的。
Label:标签,最终体现到每一行上的安全标签,必须设置。只有用户被赋予的标签和此行上的标签相同或者等级更高的时候,该行才能够被用户存取。
1 安装
Oracle Label Security仅适用于企业版的许可选项。在安装数据库软件的时候必须保证选择了Oracle Label Security组件,否则所有功能都无法使用。如果当时没有选择,可以重新运行Universal Installer进行安装。在11.2.0的企业版中Oracle Label Security组件已经自动被安装了。通过chopt命令来启动或者关闭Oracle Label Security组件。
开启OLS:

关闭OLS:

Oracle Label Security相关的用户可以利用$ORACLE_HOME/rdbms/admin/catols.sql创建。
SYS@PROD1>@?/rdbms/admin/catols.sql
在这个脚本的最后会自动关闭数据库,所以请不要在生产库上直接测试。
再次打开数据库,就可以使用LBACSYS用户登录了,默认密码就是lbacsys,如果投放在生产环境中,请立刻修改默认密码。
2 创建测试用户并赋予相关权限
SYS@PROD1>CREATE USER ols_test IDENTIFIED BY ols_test DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
User created.
SYS@PROD1>GRANT CONNECT, RESOURCE, SELECT_CATALOG_ROLE TO ols_test;
Grant succeeded.
SYS@PROD1>ALTER USER lbacsys IDENTIFIED BY lbacsys ACCOUNT UNLOCK;
User altered.
SYS@PROD1>CONN lbacsys/lbacsys
Connected.
LBACSYS@PROD1>GRANT EXECUTE ON sa_components TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_user_admin TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_user_admin TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_label_admin TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_policy_admin TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_audit_admin TO ols_test WITH GRANT OPTION;
Grant succeeded.
LBACSYS@PROD1>GRANT LBAC_DBA TO ols_test;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON sa_sysdba TO ols_test;
Grant succeeded.
LBACSYS@PROD1>GRANT EXECUTE ON to_lbac_data_label TO ols_test;
Grant succeeded.
3 创建Policy
SYS@PROD1>conn ols_test/ols_test
Connected.
OLS_TEST@PROD1>begin
2 SA_SYSDBA.CREATE_POLICY(
3 policy_name => 'region_policy',
4 column_name => 'region_label');
5 END;
6 /
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>GRANT region_policy_DBA TO ols_test;
Grant succeeded.
4 定义Labels的内容
(1)定义Levels
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',20,'L1','Level 1');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',40,'L2','Level 2');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_LEVEL('region_policy',60,'L3','Level 3');
PL/SQL procedure successfully completed.
第一个参数是上一步创建的安全策略的名字。第二个参数是Level的等级,数字越大表示权限越高,比如此处具有L3等级的就可以同时查看有L2和L1等级的数据。第三个参数是Level的短名,随便定义。第四个参数是Level的长名,只是起到一个说明的作用,随便定义。
可以从DBA_SA_LEVELS视图中查询安全等级的情况。
(2)定义Compartments
本步操作是可选项,仅仅使用上一步中的Level就已经可以控制数据的行级安全性了,但是如果要实现更加复杂的控制,就可能需要定义Compartment和下一步的Group。
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_COMPARTMENT('region_policy',100,'M','MANAGEMENT');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_COMPARTMENT('region_policy',120,'E','EMPLOYEE');
PL/SQL procedure successfully completed.
参数依次是安全策略名,Compartment数字,短名,长名,此处的Compartment数字不涉及到权限的高低,仅仅是一个标识符而已。
可以从DBA_SA_COMPARTMENTS视图中查询安全间隔的情况。
(3)定义Groups
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',20,'R20','REGION NORTH');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',40,'R40','REGION SOUTH');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',60,'R60','REGION EAST');
PL/SQL procedure successfully completed.
OLS_TEST@PROD1>EXECUTE SA_COMPONENTS.CREATE_GROUP('region_policy',80,'R80','REGION WEST');
PL/SQL procedure successfully completed.
参数依次是安全策略名,Group数字,短名,长名,此处的Group数字不涉及到权限的高低,仅仅是一个标识符而已。
可以从DBA_SA_GROUPS视图中查询安全组的情况。
注意,create_group存储过程有第5个参数,是parent_name,通过这个参数可以实现几乎无限制的多层权限控制,这里就不再深入了。
(4)设置用户权限
OLS_TEST@PROD1>EXECUTE SA_USER_ADMIN.SET_USER_PRIVS('region_policy','ols_test','FULL,PROFILE_ACCESS');
PL/SQL procedure successfully completed.
5 创建测试的schema
OLS_TEST@PROD1>CREATE TABLE customers (
2 id NUMBER(10) NOT NULL,
3 cust_type VARCHAR2(10),
4 first_name VARCHAR2(30),
5 last_name VARCHAR2(30),
6 region VARCHAR2(5),
7 credit NUMBER(10,2),
8 CONSTRAINT customer_pk PRIMARYKEY (id));
Table created.
OLS_TEST@PROD1>GRANT SELECT, INSERT, UPDATE, DELETE ON customers TO PUBLIC;
Grant succeeded.
编辑插入脚本并插入
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 1, 'SILVER', 'Harry', 'Hill', 'NORTH', 11000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 2, 'SILVER', 'Vic', 'Reeves', 'NORTH', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 3, 'SILVER', 'Bob', 'Mortimer', 'WEST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 4, 'SILVER', 'Paul', 'Whitehouse', 'SOUTH', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 5, 'SILVER', 'Harry', 'Enfield', 'EAST', 20000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 6, 'GOLD', 'Jenifer', 'Lopez', 'WEST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 7, 'GOLD', 'Kylie', 'Minogue', 'NORTH', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 8, 'GOLD', 'Maria', 'Carey', 'WEST', 1000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES ( 9, 'GOLD', 'Dani', 'Minogue', 'SOUTH', 20000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (10, 'GOLD', 'Whitney', 'Houston', 'EAST', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (11, 'PLATINUM', 'Robbie', 'Williams', 'SOUTH', 500.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (12, 'PLATINUM', 'Thom', 'Yorke', 'NORTH', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (13, 'PLATINUM', 'Gareth', 'Gates', 'WEST', 10000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (14, 'PLATINUM', 'Darius', 'Dinesh', 'EAST', 2000.00);
INSERT INTO customers (id, cust_type, first_name, last_name, region, credit)
VALUES (15, 'PLATINUM', 'Will', 'Young', 'EAST', 100.00);
COMMIT;
6 创建labels
这里是手工编辑的一个函数来创建labels
OLS_TEST@PROD1>CREATE OR REPLACE FUNCTION get_customer_label (
2 p_cust_type IN VARCHAR2,
3 p_region IN VARCHAR2,
4 p_credit IN NUMBER)
5 RETURN LBACSYS.LBAC_LABEL AS
6 v_label VARCHAR2(80);
7 BEGIN
8 IF p_credit > 2000 THEN
9 v_label := 'L3:';
10 ELSIF p_credit > 500 THEN
11 v_label := 'L2:';
12 ELSE
13 v_label := 'L1:';
14 END IF;
15
16 IF p_cust_type = 'PLATINUM' THEN
17 v_label := v_label || 'M:';
18 ELSE
19 v_label := v_label || 'E:';
20 END IF;
21
22 IF p_region = 'NORTH' THEN
23 v_label := v_label || 'R20';
24 ELSIF p_region = 'SOUTH' THEN
25 v_label := v_label || 'R40';
26 ELSIF p_region = 'EAST' THEN
27 v_label := v_label || 'R60';
28 ELSIF p_region = 'WEST' THEN
29 v_label := v_label || 'R80';
30 END IF;
31
32 RETURN TO_LBAC_DATA_LABEL('region_policy',v_label);
33 END get_customer_label;
34 /
Function created.
OLS_TEST@PROD1>show errors
No errors.
7 将策略赋予表
OLS_TEST@PROD1>BEGIN
2 SA_POLICY_ADMIN.APPLY_TABLE_POLICY(
3 policy_name => 'REGION_POLICY',
4 schema_name => 'OLS_TEST',
5 table_name => 'CUSTOMERS',
6 table_options => 'NO_CONTROL');
7 END;
8 /
PL/SQL procedure successfully completed.
8 初始化标签
接下来,我们初始化现有数据的标签列。 没有这个权限将不允许访问。
OLS_TEST@PROD1>UPDATE customers
2 SET region_label = CHAR_TO_LABEL('REGION_POLICY','L1');
15 rows updated.
OLS_TEST@PROD1>commit;
Commit complete.
9 重新应用策略
接下来,我们将策略重新应用到表并链接到刚才创建的label function。
OLS_TEST@PROD1>BEGIN
2 SA_POLICY_ADMIN.REMOVE_TABLE_POLICY('REGION_POLICY','OLS_TEST','CUSTOMERS');
3 SA_POLICY_ADMIN.APPLY_TABLE_POLICY (
4 policy_name => 'REGION_POLICY',
5 schema_name => 'OLS_TEST',
6 table_name => 'CUSTOMERS',
7 table_options => 'READ_CONTROL,WRITE_CONTROL,CHECK_CONTROL',
8 label_function =>'ols_test.get_customer_label(:new.cust_type,:new.region,:new.credit)',
9 predicate => NULL);
10 END;
11 /
PL/SQL procedure successfully completed.
10 重新标记行
接下来,我们使用label function重新标记行。
OLS_TEST@PROD1>UPDATE customers set first_name = first_name;
15 rows updated.
OLS_TEST@PROD1>commit;
Commit complete.
11 创建用户来测试安全设置
OLS_TEST@PROD1>conn as sysdba
Connected.
SYS@PROD1>CREATE USER sales_manager IDENTIFIED BY sales_manager;
User created.
SYS@PROD1>CREATE USER sales_north IDENTIFIED BY sales_north;
User created.
SYS@PROD1>CREATE USER sales_south IDENTIFIED BY sales_south;
User created.
SYS@PROD1>CREATE USER sales_east IDENTIFIED BY sales_east;
User created.
SYS@PROD1>CREATE USER sales_west IDENTIFIED BY sales_west;
User created.
SYS@PROD1>GRANT CONNECT TO sales_manager, sales_north, sales_south, sales_east, sales_west;
Grant succeeded.
SYS@PROD1>conn ols_test/ols_test
Connected.
OLS_TEST@PROD1>BEGIN
2 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_manager','L3:M,E:R20,R40,R60,R80');
3 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_north','L3:E:R20,R40');
4 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_south','L3:E:R20,R40,R60,R80');
5 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_east','L3:E:R60');
6 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_west','L3:E:R80');
7 END;
8 /
PL/SQL procedure successfully completed.
12 测试Label Security Policy
OLS_TEST@PROD1>conn as sysdba
Connected.
SYS@PROD1>CREATE USER sales_manager IDENTIFIED BY sales_manager;
User created.
SYS@PROD1>CREATE USER sales_north IDENTIFIED BY sales_north;
User created.
SYS@PROD1>CREATE USER sales_south IDENTIFIED BY sales_south;
User created.
SYS@PROD1>CREATE USER sales_east IDENTIFIED BY sales_east;
User created.
SYS@PROD1>CREATE USER sales_west IDENTIFIED BY sales_west;
User created.
SYS@PROD1>GRANT CONNECT TO sales_manager, sales_north, sales_south, sales_east, sales_west;
Grant succeeded.
SYS@PROD1>conn ols_test/ols_test
Connected.
OLS_TEST@PROD1>BEGIN
2 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_manager','L3:M,E:R20,R40,R60,R80');
3 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_north','L3:E:R20,R40');
4 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_south','L3:E:R20,R40,R60,R80');
5 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_east','L3:E:R60');
6 SA_USER_ADMIN.SET_USER_LABELS('region_policy','sales_west','L3:E:R80');
7 END;
8 /
PL/SQL procedure successfully completed.





近期精彩文件推荐
中国OCM之家
专注数据 共现梦想
QQ群:554334183






