oracle label security(OLS)相关主体流程整理
一个OLS简单应用场景, 下面的列子将实现这样的功能:
- 创建4个level, 级别从高到低依次为: top, high, middle, low;
- 给stu表上所有数据添加标签;
- 如果用户被赋予第一个标签, 则能查看所有带标签数据;
- 如果用户被赋予第二个标签, 则能查看对应级别及其以下的数据;
- 用户在授权范围内调整会话label, 重新查看数据;
步骤:
- 准备2个账户, quzq和us1, quzq用来创建table及赋权label, us1用来作为特权账户给数据添加label:
create user quzq identified by lala123;
grant connect, resource, dba to quzq;
create user us1 identified by lala123;
grant connect, resource, dba to us1;
- 使用quzq账户创建stu表, 并添加数据:
create table stu(s1 nvarchar2(10));
insert into stu values(1);
insert into stu values(2);
insert into stu values(3);
insert into stu values(4);
- 连接lbacsys账户创建policy及其组件(此处创建了上面所说的4个level)
exec sa_sysdba.create_policy('my_policy', 'ols_name','ALL_CONTROL'); # 创建policy, 参数详见下方ols使用的3个阶段
exec sa_components.create_level('my_policy', 100, 'low', 'low_level'); # 创建policy的level组件
exec sa_components.create_level('my_policy', 200, 'middle', 'middle_level');
exec sa_components.create_level('my_policy', 300, 'high', 'high_level');
exec sa_components.create_level('my_policy', 400, 'top', 'top_level');
- 创建label
exec sa_label_admin.create_label('my_policy',40000,'top',true);
exec sa_label_admin.create_label('my_policy',30000,'high',true);
exec sa_label_admin.create_label('my_policy',20000,'middle',true);
exec sa_label_admin.create_label('my_policy',10000,'low',true);
- 应用policy到table
exec sa_policy_admin.apply_table_policy('my_policy','quzq','stu');
此时使用quzq和us1账户分别查看stu表结果如下:
查看表结构,如下:
- 给quzq用户赋权第一个label, 再次查看数据:
exec sa_user_admin.set_user_labels('my_policy','quzq','top');
重新登录查看结果如下:
- 使用lbacsys给us1账户赋特权, 绕开OLS验证, 重新登录us1账户查看数据, 并给数据行添加label
execute sa_user_admin.set_user_privs('my_policy','us1','FULL');
- 再次使用quzq账户查看stu表:
- 使用lbacsys账户给quzq用户赋权第二个标签, 登录quzq账户再次查看stu表:
exec sa_user_admin.set_user_labels('my_policy','quzq','high');
- 用户端在权限范围内修改会话的label, 再次查看stu表:
上一步的赋权用户label中第三个参数指定了用户的最高label为high, 最低默认为low, 会话label默认也是high,
所以当前用户的权限范围可在low, middle和high中随意指定, 而不能指定成范围之外的top:
exec sa_session.set_label('my_policy','top');
- 使用当前会话进行insert操作:
OLS使用流程可拆分为3个阶段, 以下通过对这3个阶段的描述来说明OLS的使用
一.定义阶段
定义阶段包含定义policy及其组件,以及使用定义好的组件来创建label, 如下:
1.创建policy
语法: exec sa_sysdba.create_policy(policy_name, 'ols_name','');
说明: policy是使用OLS的基础, 其相当于个容器, 该容器内包含有3个组件, 分别为level, compartment和group;
参数: policy_name参数用来给policy命名, policy的名称必须是唯一的;
column_name参数用于定义将policy应用到table时, 表中生成的label列名;
default_options参数用于设定默认的策略控制选项, 如将policy应用到table时不指定控制选项, 则此默认值生效;
2.在policy中创建level
语法: exec sa_components.create_level(policy_name, level_num, short_name, long_name);
说明: level是policy中的必有组件, 其具有层级关系, level个数无明确限制, 但level_num必须唯一;
参数: policy_name参数用于指定该level属于哪个policy的组件;
level_num参数取值0-9999, 数值越大表示其层级越高, 同一个policy中level_num值唯一;
short_name参数用于给level设定简写名称, level被引用时使用该名称;
long_name参数用于给level设定全名;
3.在policy中创建compartment
语法: exec sa_components.create_compartment(policy_name, comp_num, short_name, long_name);
说明: compartment是可选组件, 没有级别或层级的区分, 个数无明确限制, 但comp_num必须唯一;
参数: policy_name参数用于指定该compartment属于哪个policy的组件;
comp_num参数取值0-9999, 数值大小只影响显示时的排序, 同一个policy中comp_num值唯一;
short_name参数用于给compartment设定简写名称, compartment被引用时使用该名称;
long_name参数用于给compartment设定全名;
4.在policy中创建group
语法: sa_components.create_group(policy_name, group_num, short_name, long_name, parent_name);
说明: group是可选组件, 有子集或父集区分, 个数无明确限制, 但group_num必须唯一;
参数: policy_name参数用于指定该group属于哪个policy的组件;
group_num参数取值0-9999, 数值大小只影响显示时的排序, 同一个policy中group_num值唯一;
short_name参数用于给group设定简写名称, group被引用时使用该名称;
long_name参数用于给group设定全名;
parent_name参数用户指定该group的父集, 该参数可选;
5.创建label
语法: exec sa_label_admin.create_label(policy_name, label_tag, label_value, data_label);
说明: label有两方面用处, 一方面用于表中数据行, 另一方面用于赋给用户; 用于控制用户能访问到的数据;
参数: policy_name参数用于指定生成哪个policy的label;
label_tag参数取值0-99999999,数值大小只影响显示时的排序,表中数据行添加label后会显示该值;
label_value参数使用policy中的level,compartment,group来生成, 如: 'level:compartment:group';
data_label参数取值为布尔型, TRUE表示该label可用于数据行;
二.应用阶段
包含: 将policy应用到table或schema上, 将label赋给用户, 将表中原有数据添加label, 如下:
1.将policy应用到table或schema(此处以应用到table来说明)
语法: exec sa_policy_admin.apply_table_policy(policy_name, schema_name, table_name, table_options,
label_function, predicate);
说明: 将policy成功应用到table上, 所有访问该table的用户都获取不到任何数据, 对表的所有想要的控制也是在
这个阶段设定的, 通过table_options的参数选项来实现,. 前3个参数是必选的.
参数: policy_name参数用于指定将被应用的policy名称;
schema_name参数用于指定用户schema;
table_name参数用于指定给哪张表添加policy;
table_options参数用于设定对表的控制项, oracle提供有10个选项, 可按需选取;
label_function参数用于设定生成label的函数;
predicate参数配合options选项为READ_CONTROL时使用;
2.将label赋给用户
将label赋给用户oracle提供有两类方法: 一类是按照组件给用户赋权, 一类是通过label string给用户赋权;
1.按照组件的赋权:
1).赋权level给用户
语法: exec sa_user_admin.set_levels(policy_name, user_name, max_level, min_level, def_level, row_level);
说明: 可单独赋权level给用户;
参数: policy_name参数用于指定生效的policy;
user_name参数用于指定赋给哪个用户;
max_level参数设置该用户能操控的最高level等级;
min_level参数设置该用户能操控的最低level等级;
def_level参数设置该用户默认的session所使用的level等级;
row_level参数设置该用户缺省insert操作时默认使用的level;
2).赋权compartment给用户:
语法: exec sa_user_admin.set_compartments(policy_name, user_name, read_comps, write_comps,def_comps, row_comps );
说明: 必须在赋权level给用户的基础上赋权compartment, 不能单独赋权compartment给用户;
参数: policy_name参数用于指定生效的policy;
user_name参数用于指定赋给哪个用户;
read_comps参数可指定多个以逗号分隔的compartment;
write_comps参数默认为null, null时以read_comps为准;
def_comps参数默认为null, null时以read_comps为准, 设定时必须是read_comps的子集;
row_comps参数默认为null, null时以def_comps为准, 设定时必须是write_comps和def_comps的子集;
3).赋权group给用户:
语法: exec sa_user_admin.set_groups(policy_name, user_name, read_groups, write_groups, def_groups,row_groups);
说明: 不能单独赋权group给用户, 必须是在赋权level的基础上才行;
参数: policy_name参数用于指定生效的policy;
user_name参数用于指定赋给哪个用户;
read_groups参数可指定多个以逗号分隔的group;
write_groups参数默认为null, null时以read_groups为准;
def_groups参数默认为null, null时以read_groups为准, 设定时必须是read_groups的子集;
row_groups参数默认null, null时以def_groups为准, 设定时必须是write_groups和def_groups的子集;
2.通过label string给用户赋权:
语法: exec sa_user_admin.set_user_labels(policy_name, user_name, max_read_label, max_write_label,min_write_label, def_label, row_label);
说明: label string赋权是结合了policy中所有组件, 以字符形式的一种赋权, 两种赋权任选其一即可.
参数: policy_name参数用于指定生效的policy;
user_name参数用于指定赋给哪个用户;
max_read_label参数用于指定最大的read权限的label, 如: 'l : c : g1, g2';
max_write_label参数默认null, null时以max_read_label为准;
min_write_label参数默认null, null时为最低level, 无compartment和group;
def_label参数取值必须是max_read_label的子集, null时以max_read_label为准;
row_label参数指定默认的行label, 必须是max_write_label和def_label的子集;
3.为表中已有数据行添加label(可选操作, 视场景选用)
table上应用policy后,有且只有数据行label和用户label能匹配上的数据才能被访问到, 默认没有label的数据行永
远无法被访问. 如对表应用policy之前,表中就存有数据的场景, 在应用policy后需要为这部分数据添加label.
1).普通用户的特权管理:
语法: exec sa_user_admin.set_user_privs(policy_name, user_name, privileges);
说明: policy应用到table后, 普通用户在不赋权label时无法无法操控数据库, 要为原有数据添加label只能使用特权来绕过OLS的认证.
参数: policy_name参数用于指定特权对哪个policy生效;
user_name参数用于指定对哪个用户授权;
privileges参数用于指定授予什么样的特权, 此参数的取值oracle提供有7个选项, 可控制不同的特权范围;
2).特权设置成功即可绕开OLS相应的验证, 以update形式给数据添加label:
update stu set OLS_CNAME=CHAR_TO_LABEL('my_policy','internal:fin,hr:west,east');
三.使用阶段
1.用户在权限范围内自定义session label
说明: 在给用户设置label时, 设定有用户默认的初始化连接数据库的label, 也设定有用户的最大和最小label.
session label的取值决定着用户所能操作的数据范围, 某些场景需要在权限范围内调高或调低session权限;
语法: exec sa_session.set_label(policy_name, label);
参数: policy_name参数用于指定policy名称;
label参数用于设定当前session使用的label, 此处取值不能超出设定的最高和最低label范围;
2.用户在权限范围内自定义row label
说明: 在给用户设置label时, 设定有用户默认的row label. row babel用于insert时不指定label值时的默认使用值,
在使用某些table_options选项来限制table时, row label的权限不能高于session label.
语法: exec sa_session.set_row_label(policy_name, label);
参数: policy_name参数用于指定policy名称;
label参数用于设定不指定label时的insert默认值, 此处取值不能超出设定的最高和最低label范围;
总结:
- 以上为使用OLS的主体流程描述, 不包含所有的OLS功能.
- OLS使用过程中比较复杂的地方在应用policy到table时的table_options选项,不同选项控制着不同的OLS行为,也会影响着各种给用户赋权label时的参数选定, 以及用户使用过程中自定义的session label和row label的取值. 去理解单独的某个功能或参数的取值没有意义, 需要结合OLS整个流程中的上下文环境去设定合适的场景.
- OLS相关视图如下:
查看创建的policy: select * from dba_sa_policies;
查看创建的level: select * from dba_sa_levels;
查看创建的compartments: select * from dba_sa_compartments;
查看创建的groups: select * from dba_sa_groups;
查看创建的labels: select * from dba_sa_labels;
查看table上的policy: select * from dba_sa_table_policies;
查看用户的label: select * from dba_sa_user_labels;
查看当前session label: select sa_session.label('MY_POLICY') from dual;
查看当前row label: select sa_session.row_label('MY_POLICY') from dual;
- policy中level, compartment, group对数据进行逻辑分类的三个维度: