4.1 如何创建策略
4.1.1 策略的组成
策略是一组预定义的标记组件,包括等级、范围和组这三种组件,三种组件分别从不同的维度对数据进行了描述。一个策略最多只能包含这三种组件,其中必须包含等级,范围和组可以缺省。
■ 等级(Level)
等级是线性有序的名称序列,用 L=(l1,l2,…,lp)表示。其中 li(1≤i≤p)表示第 i 个名称,任意两个名称 li、lj 之间,若 i≤j,则 li≤lj,于是有 l1≤l2≤…≤lp,其中 l1,l2,…,lp 称为等级分类(以下简称等级)。
在 DM 中,一个策略最大可定义 10000 个等级。用户在定义策略中的等级时,需要为其指定编号,其编号在 0-9999 之间(编号小的意味着级别较低)。
■ 范围(Compartment)
范围是集合类型,设集合 C={c1,c2,…,cm}中每一元素都是一名称,c1,c2,…,cm 间彼此独立,无序,则集合 C 及其任意子集称为非等级类别集合,其中 c1,c2,…,cm 称为非等级类别(以下简称为范围)。
在 DM 中,最大可定义 10000 个范围,需要用户设置编号,且编号在一个策略里面须是唯一的,编号之间没有级别高低之分。
■ 组(Group)
组为树形结构,有父子之分,可以用来描述组织结构。
设树 G={g1,g2,…,gm},其中每一元素都是一名称,g1,g2,…,gm 间有父子之分,则 g1,g2,…,gm 称为组。
在 DM 中,最多能定义 10000 个组,也就是说组织结构的层次最多为 10000。组中只能有一个根组,除根组外,每个组有且仅有一个父组。
4.1.2 创建、修改与删除策略
4.1.2.1 创建策略
使用如下系统过程创建一个策略。
VOID
MAC_CREATE_POLICY(
POLICY_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 新创建的策略名称
使用说明:
只有具有 LABEL_DATABASE 数据库权限的用户才能执行此操作。
例如,创建策略 P_01
MAC_CREATE_POLICY('P_01');
4.1.2.2 修改策略
可以使用下面的系统过程修改一个策略的策略名。
VOID
MAC_ALTER_POLICY(
POLICY_NAME VARCHAR(128),
NEW_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 待修改的策略名称
NEW_NAME 将修改成的策略名称
使用说明:
只有具有 LABEL_DATABASE 数据库权限的用户才能执行此操作。
例如,将策略 P_01 改名为 P_02。
MAC_ALTER_POLICY('P_01', 'P_02');
4.1.2.3 删除策略
可以使用下面的系统过程删除一个已存在的策略。
VOID
MAC_DROP_POLICY(
POLICY_NAME VARCHAR(128),
DROP_COLUMN INT
);
参数说明:
POLICY_NAME 待删除的策略名称
DROP_COLUMN 对应用此策略的表的标记列的处理方式,取值为 0 或 1
0:不删除应用此策略的所有表对应的标记列
1:删除应用此策略的所有表对应的标记列
若 DROP_COLUMN 为 NULL,则按默认为 0 进行处理
使用说明:
- 只有具有 LABEL_DATABASE 数据库权限的用户才能执行此操作;
- 指定待删除策略必须存在。
例如,删除策略 P_02。
MAC_DROP_POLICY('P_02');
4.1.3 为策略添加组件
创建一个策略后,需要对策略添加组件,这样策略才可以被应用到表和用户上。
4.1.3.1 为策略添加等级
使用下面的系统过程为指定的策略添加等级。
VOID
MAC_CREATE_LEVEL(
POLICY_NAME VARCHAR(128),
LEVEL_NUM INT,
LEVEL_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要添加等级的策略名
LEVEL_NUM 创建的等级编号,在 0-9999 之间的整数
LEVEL_NAME 创建的等级名称
使用说明:
- LEVEL_NAME 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 同一个策略中,等级 ID 和等级名称唯一;
- 一个策略最多可以定义 10000 个等级;
- 每个等级都要有一个等级 ID,ID 越小表示安全等级越低。
例如,创建策略 P_03,并给策略 P_03 添加等级 L_01,等级编号为 10。
MAC_CREATE_POLICY('P_03');
MAC_CREATE_LEVEL('P_03', 10, 'L_01');
在为策略添加等级后,还可以通过系统过程修改等级名称和删除等级。
■ 修改等级
修改等级名称的系统过程如下:
VOID
MAC_ALTER_LEVEL(
POLICY_NAME VARCHAR(128),
LEVEL_NAME VARCHAR(128),
NEW_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要修改等级名的策略名
LEVEL_NAME 待修改的等级名称
NEW_NAME 要修改成的等级名称
使用说明:
- NEW_LEVEL 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 待修改等级名必须存在。
例如,将策略 P_03 中的等级 L_01,更名为 L_02。
MAC_ALTER_LEVEL('P_03', 'L_01', 'L_02');
■ 删除等级
删除等级的系统过程如下:
VOID
MAC_DROP_LEVEL(
POLICY_NAME VARCHAR(128),
LEVEL_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 待删除等级所在策略名
LEVEL_NAME 待删除的等级名称
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定等级必须存在;
- 如果待删除等级被某个标记使用,则拒绝删除。
例如,删除策略 P_03 中的等级 L_02。
MAC_DROP_LEVEL('P_03', 'L_02');
4.1.3.2 为策略添加范围
使用下面的系统过程为指定的策略添加范围。
VOID
MAC_CREATE_COMPARTMENT(
POLICY_NAME VARCHAR(128),
COMPART_NUM INT,
COMPART_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要添加范围的策略名
COMPART_NUM 创建的范围编号,在 0-9999 之间的整数
COMPART_NAME 创建的范围名称
使用说明:
- COMPART_NAME 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 同一个策略中,范围 ID 和范围名称唯一;
- 一个策略中最多可以定义 10000 个范围;
- 范围独立无序,范围之间是平等关系,没有等级高低之分,范围之间的比较运算采用集合间的包含关系。
例如,给策略 P_03 添加范围 C_01。
MAC_CREATE_COMPARTMENT('P_03',10, 'C_01');
在为策略添加范围后,还可以通过系统过程修改范围名称和删除范围。
■ 修改范围
修改范围名称的系统过程如下:
VOID
MAC_ALTER_COMPARTMENT(
POLICY_NAME VARCHAR(128),
COMPART_NAME VARCHAR(128),
NEW_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要修改范围名的策略名
COMPART_NAME 待修改的范围名称
NEW_NAME 要修改成的范围名称
使用说明:
- NEW_NAME 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 待修改范围名必须存在。
例如,将策略 P_03 中的范围 C_01,更名为 C_02。
MAC_ALTER_COMPARTMENT('P_03', 'C_01', 'C_02');
■ 删除范围
删除范围的系统过程如下:
VOID
MAC_DROP_COMPARTMENT(
POLICY_NAME VARCHAR(128),
COMPART_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 待删除范围所在策略名
COMPART_NAME 待删除的范围名称
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定范围必须存在;
- 如果待删除范围被某个标记使用,则拒绝删除。
例如,删除策略 P_03 中的范围 C_02。
MAC_DROP_COMPARTMENT('P_03', 'C_02');
4.1.3.3 为策略添加组
使用下面的系统过程为指定的策略添加组。
VOID
MAC_CREATE_GROUP(
POLICY_NAME VARCHAR(128),
GROUP_NUM INT,
GROUP_NAME VARCHAR(128),
PARENT_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要添加组的策略名
GROUP_NUM 创建的组编号,在 0-9999 之间的整数
GROUP_NAME 创建的组名称
PARENT_NAME 新创建组的父组的名称
使用说明:
- GROUP_NAME 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 同一个策略中,组 ID 和组名称唯一;
- 一个策略最多可以定义 10000 个组;
- 同一个策略中,只能有一个根组,如果 PARENT_NAME 为 NULL,则创建根组;
- 组之间的比较运算采用树形结构间的从属关系。
例如,给策略 P_03 创建根组 G_01;再以 G_01 为父组,创建组 G_02;以 G_02 为父组,创建组 G_03。
MAC_CREATE_GROUP ('P_03',10, 'G_01',NULL);
MAC_CREATE_GROUP ('P_03',20, 'G_02', 'G_01');
MAC_CREATE_GROUP ('P_03',30, 'G_03', 'G_02');
在为策略添加组后,还可以通过系统过程修改组名称、更新父组和删除组。
■ 修改组
修改组名称的系统过程如下:
VOID
MAC_ALTER_GROUP(
POLICY_NAME VARCHAR(128),
GROUP_NAME VARCHAR(128),
NEW_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要修改组名的策略名
GROUP_NAME 待修改的组名称
NEW_NAME 要修改成的组名称
使用说明:
- NEW_NAME 不能包含“:”和“,”;
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 待修改组名必须存在。
例如,将策略 P_03 中的组 G_03,更名为 G_04。
MAC_ALTER_GROUP('P_03', 'G_03', 'G_04');
■ 更新父组
更新父组的系统过程如下:
VOID
MAC_ALTER_GROUP_PARENT(
POLICY_NAME VARCHAR(128),
GROUP_NAME VARCHAR(128),
PARENT_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要更新父组的组所在的策略名
GROUP_NAME 待更新父组的组名称
PARENT_NAME 待修改成的父组名称
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 待修改组和待修改成的父组必须存在;
- 父组不能是自身,同时不能是自己的子节点。
例如,将策略 P_03 中的组 G_04,更换父组为 G_01。
MAC_ALTER_GROUP_PARENT ('P_03', 'G_04', 'G_01');
■ 删除组
删除组的系统过程如下:
VOID
MAC_DROP_GROUP (
POLICY_NAME VARCHAR(128),
GROUP_NAME VARCHAR(128),
);
参数说明:
POLICY_NAME 待删除组所在策略名
GROUP_NAME 待删除的组名称
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定组必须存在;
- 待删除的组不能有子节点存在,否则删除失败。
例如,删除策略 P_03 中的组 G_04。
MAC_DROP_GROUP('P_03', 'G_04');
4.2 如何创建标记
当把策略应用于用户或表时,那么该用户或表就获得了一个安全标记。一个安全标记由多个组件组成,其组件包括等级、范围和组。每个标记必须包含一个等级,范围和组则是可选的。
在 DM 中,标记用字符串表示,其最大长度为 4000。格式如下:
<等级>:[<范围>{,<范围>}]:[<组>{,<组>}];
假定系统中存在策略 P1,其包含等级 L1,L2,L3,范围 C1,C2,C3,C4,组 G1,G2,G3。则下列标记为合法标记:
L1::
L1:C1:
L1:C1,C2:
L1::G1
L1:C1:G1,G2
而下列标记为不合法标记:
:
:C1,C2
C1,C2
:C1:G1
::G1,G2
G1,G2
标记以二进制位的形式存储于数据库中。当一个策略被应用到表上时,需要指定标记的存储列名,此列的类型为 INT,此时表上每条元组的标记均存在于该列中。
在应用策略时,还可设置标记列是否被隐藏。当标记列被隐藏时,若用户在插入数据时不指定列清单,则在值列表中可以不设置该列的值,另外,在查询时也不显示该列数据。
标记列上可以建索引,设置列约束、改列名等,但不能修改列类型、设置缺省值等。标记列不能被用户显式删除,除非在表上取消该策略。
4.2.1 创建标记
可使用下面的系统过程创建一个标记。
VOID
MAC_CREATE_LABEL(
POLICY_NAME VARCHAR(128),
LABEL_TAG INT,
LABEL_VALUE VARCHAR(4000)
);
参数说明:
POLICY_NAME 要创建的标记所在的策略名
LABEL_TAG 标记值,有效范围为 0~999999999
LABEL_VALUE 标记串
使用说明:
-
该过程只能由具有 LABEL_DATABASE 的用户调用;
-
指定策略必须存在;
-
根据标记值和标记串,生成一个标记,若此标记已经存在,则返回错误。标记值由用户自己指定,且标记值在系统中应是唯一的,不同的策略中也不能使用相同的标记值。
例如,创建标记 L_01:C_01:G_02。
MAC_CREATE_POLICY('P_04');
MAC_CREATE_LEVEL ('P_04',100, 'L_01');
MAC_CREATE_COMPARTMENT ('P_04',100, 'C_01');
MAC_CREATE_GROUP ('P_04',100, 'G_01',NULL);
MAC_CREATE_GROUP ('P_04',200, 'G_02', 'G_01');
MAC_CREATE_LABEL('P_04',11, 'L_01:C_01:G_02');
上述例子执行后,将在 SYSMACLABELS 系统表中记录 TAG 值以及标记字符串'L1:C1:G1'的内部格式,这个格式是对字符串'L1:C1:G1'进行处理后的格式。
如果要查看系统中某个标记对应的具体的值,例如,要查看刚刚创建的 ID 为 11 的标记的具体值,可以使用如下系统函数:
SF_MAC_LABEL_TO_CHAR(11);
此系统函数的参数为标记的标记值,返回该标记对应的标记串。
4.2.2 修改标记
可根据标记的标记值或标记串对标记修改其标记串,使用如下的系统过程:
VOID
MAC_ALTER_LABEL(
POLICY_NAME VARCHAR(128),
LABEL_TAG INT,
NEW_LABEL_VALUE VARCHAR(4000)
);
VOID
MAC_ALTER_LABEL(
POLICY_NAME VARCHAR(128),
LABEL_VALUE VARCHAR(4000),
NEW_LABEL_VALUE VARCHAR(4000)
);
参数说明:
POLICY_NAME 待修改标记所在策略名
LABEL_TAG 待修改标记的标记值
LABEL_VALUE 待修改标记的标记串
NEW_LABEL_VALUE 要修改为的标记串
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 新的标记串必须是不存在的标记串,如果存在则报错;
- 修改标记的用处主要在于可以不用更新表中的标记列,而直接修改标记串,来改变原始数据的安全级别;
- 修改标记的标记串,如果新的标记串为 NULL,则保持原始值;
- 如果修改的标记同时应用在用户上,那么用户的标记合法性可能会遭到破坏。
例如,更改标记 L_01:C_01:G_02。
MAC_ALTER_LABEL('P_04',11, 'L_01:C_01:G_01,G_02');
MAC_ALTER_LABEL('P_04', 'L_01:C_01:G_01,G_02', 'L_01:C_01:');
4.2.3 删除标记
可根据标记的标记值或标记串删除标记,使用如下的系统过程:
VOID
MAC_DROP_LABEL(
POLICY_NAME VARCHAR(128),
LABEL_TAG INT
);
VOID
MAC_DROP_LABEL(
POLICY_NAME VARCHAR(128),
LABEL_VALUE VARCHAR(4000)
);
参数说明:
POLICY_NAME 待删除标记所在策略名
LABEL_TAG 待删除标记的标记值
LABEL_VALUE 待删除标记的标记串
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 待删除的标记必须是已存在的标记,否则报错;
- 标记可以进行删除,即使标记被应用在表或用户上,这样会导致表或用户的标记失效,使用时需注意。
例如,创建标记之后删除。
MAC_CREATE_LABEL('P_04',12, 'L_01::');
MAC_DROP_LABEL('P_04',12);
MAC_CREATE_LABEL('P_04',13, 'L_01::G_01');
MAC_DROP_LABEL('P_04', 'L_01::G_01');
4.2.4 隐式创建标记
可以使用下面的系统过程隐式创建标记。
VOID
SP_MAC_LABEL_FROM_CHAR(
POLICY_NAME VARCHAR(128),
LABEL_VALUE VARCHAR(4000),
TAG INT
);
参数说明:
POLICY_NAME 标记所在的策略名
LABEL_VALUE 标记串
标记值 输出参数,标记串对应的标记值
使用说明:
- 指定策略必须存在;
这个系统过程首先会去系统表 SYSMACLABELS 查找是否具有指定标记串的标记,如果存在,则返回相应的标记值,如果不存在,系统会自动创建一个对应的标记,并返回给用户相应的标记值,标记值由系统自动生成。
DM 的 INI 参数 MAC_LABEL_OPTION 用于控制 SP_MAC_LABEL_FROM_CHAR 过程的使用范围,有三种取值:
- 0:只有 SSO 可以调用
- 1:所有用户都可以调用
- 2:所有用户可以调用,但是非 SSO 用户不会主动创建新的 LABEL
例 1 隐式创建标记,标记串不存在的情况。
DECLARE
TAG INT;
BEGIN
SP_MAC_LABEL_FROM_CHAR ('P_04', 'L_01::G_02', TAG);
PRINT TAG ;
END;
/
由于之前系统中没有指定标记串的标记,此时会为这个标记串创建一个标记,返回系统自动生成的 TAG 值。
例 2 隐式创建标记,标记值已存在的情况。
MAC_CREATE_LABEL('P_04',21, 'L_01:C_01:G_02');
DECLARE
TAG INT;
BEGIN
SP_MAC_LABEL_FROM_CHAR ('P_04', 'L_01:C_01:G_02', TAG);
PRINT TAG ;
END;
/
由于先创建了标记串为 L_01:C_01:G_02 的标记,指定标记值为 21,因此后面的 SP_MAC_LABEL_FROM_CHAR 过程调用不会创建新的标记,直接返回标记值 21。
4.3 如何对表应用策略
4.3.1 对表应用策略
将策略应用在一个表上时,就使该表处于一定的等级、范围和组内。一个表上可以应用多个策略,但一个策略对表只能应用一次。
对表应用策略时,会在表上新建一个标记列,用于记录标记,新建的标记列名必须和表中已有列名不同,同时还可以指定初始的标记值,以及是否将标记列设置为隐藏列。
使用下述系统过程对表应用策略:
VOID
MAC_APPLY_TABLE_POLICY(
POLICY_NAME VARCHAR(128),
SCHEMANAME VARCHAR(128),
TABLENAME VARCHAR(128),
COLNAME VARCHAR(128),
LABELVALUE VARCHAR(4000),
OPTION INT
);
参数说明:
POLICY_NAME 应用于指定表的策略名
SCHEMANAME 表所属模式名称
TABLENAME 策略所应用的表名称
COLNAME 用于记录标记的列名称
LABELVALUE 用于说明被应用了策略的表中,已有元组的等级、范围和组
OPTION 1 代表隐藏标记列,0 代表不隐藏标记列,缺省为 0
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- 策略不能应用在系统表、临时表、HUGE 表、水平分区表、物化视图、含有聚集主键的表、含有位图连接索引的表、含有位图索引的表上;
例如,将策略 P_04 应用于 PRODUCTION 模式中 PRODUCT 表,指定标记列为 LABEL_COL,不隐藏标记列。
MAC_APPLY_TABLE_POLICY ('P_04', 'PRODUCTION', 'PRODUCT', 'LABEL_COL', 'L_01::',0);
过程中的 OPTION 参数用来指定该标记列是否隐藏。若对表应用策略时指定新增的这一列隐藏,那么对表进行 INSERT 数据时,如果未指定标记列的列名,就不能对这一列插入数据,如果对其插入数据,则会出错;如果指明具体的列来插入数据,这一列是允许插入数据的。当执行 SELECT * 来查询该表数据时,标记列被隐藏不予显示;但也允许通过指明列名来查询该列。若对表应用策略时指定新增的这一列为 0,那么该列就可以被视为一个普通列。
当一个新的策略被应用于表上时,过程的 LABELVALUE 参数用于初始化表中已有的数据关于该策略的标记。当某个策略已被应用于表时,则其已有的等级、范围和组均不能被删除,除非从所有的用户和表上取消对该策略的应用。
4.3.2 取消表策略
使用下述系统过程取消表上的指定策略:
VOID
MAC_REMOVE_TABLE_POLICY(
POLICY_NAME VARCHAR(128),
SCHEMANAME VARCHAR(128),
TABLENAME VARCHAR(128),
DROP_COLUMN INT
);
参数说明:
POLICY_NAME 表上待取消应用的策略
SCHEMANAME 表所属模式名称
TABLENAME 表名称
DROP_COLUMN 1 代表删除标记列,0 代表不删除标记列,缺省为 0
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
例如,取消应用在 PRODUCTION 模式中 PRODUCT 表上的策略,删除标记列。
MAC_REMOVE_TABLE_POLICY ('P_04', 'PRODUCTION', 'PRODUCT' ,1);
4.4 如何对用户应用策略
用户的标记来源于策略。对用户应用一个策略,要指定一个最高等级、最低等级、默认等级和行等级,其中默认等级介于最高等级和最低等级之间,最高等级限制了用户最高的读写权限,最低等级限制了用户的写权限,默认等级表示用户登录时会话标记的等级,行等级表示插入一行数据的标记使用的等级;指定范围和组,对范围需要指定读的范围、写的范围、默认范围和行级范围,其中写范围必须是读范围的子集,默认范围是读范围的子集,行级范围是写范围和默认范围的交集的子集。组的规则与范围相同。用户标记属性如下表所示:
组成 | 备注 |
---|---|
max_level | 最大读写级别 |
min_level | 最小写级别 |
def_level | 默认级别,登录时级别 |
row_level | 列级别,用于默认插入 |
categories | 包含的范围,可设置属性 |
groups | 包含的组,可设置属性 |
4.4.1 设置用户等级
对用户应用策略,应先设置用户的等级,使用如下系统过程:
VOID
MAC_USER_SET_LEVELS(
POLICY_NAME VARCHAR(128),
USER_NAME VARCHAR(128),
MAX_LEVEL VARCHAR(128),
MIN_LEVEL VARCHAR(128),
DEF_LEVEL VARCHAR(128),
ROW_LEVEL VARCHAR(128)
);
参数说明:
POLICY_NAME 应用于用户的策略名称
USER_NAME 策略所应用的用户名称
MAX_LEVEL 应用于用户的最大等级
MIN_LEVEL 应用于用户的最小等级
DEF_LEVEL 应用于用户的默认等级
ROW_LEVEL 应用于用户的行等级
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在;
- MAX_LEVEL 不能为空;
- MIN_LEVEL 不指定时,设置为策略的最小级别;
- DEF_LEVEL 不指定时,设置为 MAX_LEVEL;
- ROW_LEVEL 不指定时,设置为 DEF_LEVEL;
- 合法的 LEVEL 规则如下:
MAX_LEVEL >= MIN_LEVEL
MAX_LEVEL >= DEF_LEVEL >= MIN_LEVEL
DEF_LEVEL >= ROW_LEVEL >= MIN_LEVEL
例如,设置 BOOKSHOP_USER 用户的等级。等级 L_01,L_02,L_03,L_04 已存在,且等级级别相等,或依次增加。
MAC_USER_SET_LEVELS('P_04', 'BOOKSHOP_USER', 'L_04', 'L_01', 'L_03', 'L_02');
4.4.2 设置用户范围
对用户设置了等级后,可以对用户设置相应的范围和组。
使用下面的系统过程为用户设置范围:
VOID
MAC_USER_SET_COMPARTMENTS(
POLICY_NAME VARCHAR(128),
USER_NAME VARCHAR(128),
READ_COMP VARCHAR(128),
WRITE_COMP VARCHAR(128),
DEF_COMP VARCHAR(128),
ROW_COMP VARCHAR(128)
);
参数说明:
POLICY_NAME 应用于用户的策略名称
USER_NAME 策略所应用的用户名称
READ_COMP 应用于用户的可读范围
WRITE_COMP 应用于用户的可写范围
DEF_COMP 应用于用户的默认范围
ROW_COMP 应用于用户的行范围
使用说明:
-
该过程只能由具有 LABEL_DATABASE 的用户调用;
-
用户范围具有 READ、WRITE、DEFAULT 和 ROW 四个属性,说明如下:
- READ:用户的可读范围,READ 不能为空;
- WRITE:用户的可写范围,进行 UPDATE,DELETE 时需要使用,进行判断权限。WRITE 属于 READ,为空时使用 READ;
- DEFAULT:会话默认使用的范围。DEFAULT 属于 READ,为空时使用 READ;
- ROW:插入时不指定标记时使用。ROW 属于 DEFAULT 和 WRITE 的交集,为空时使用 DEFAULT 和 WRITE 的交集。
例如,假设范围 C_01,C_02,C_03 已存在,设置 BOOKSHOP_USER 用户的范围。
MAC_USER_SET_COMPARTMENTS('P_04','BOOKSHOP_USER','C_01,C_02,C_03','C_01,C_02','C_01,C_03','C_01');
4.4.3 设置用户组
使用下面的系统过程为用户设置组:
VOID
MAC_USER_SET_GROUPS (
POLICY_NAME VARCHAR(128),
USER_NAME VARCHAR(128),
READ_GROUP VARCHAR(128),
WRITE_GROUP VARCHAR(128),
DEF_GROUP VARCHAR(128),
ROW_GROUP VARCHAR(128)
);
参数说明:
POLICY_NAME 应用于用户的策略名称
USER_NAME 策略所应用的用户名称
READ_GROUP 应用于用户的可读组
WRITE_GROUP 应用于用户的可写组
DEF_GROUP 应用于用户的默认组
ROW_GROUP 应用于用户的行组
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 用户的组具有 READ、WRITE、DEFAULT 和 ROW 四个属性,说明如下:
- READ:用户的可读组;
- DEFAULT:会话默认使用的组;
- WRITE:进行 UPDATE,DELETE 时需要使用,进行判断权限;
- ROW:插入时不指定标记时使用;
- 合法的用户组规则如下:
- WRITE 属于 READ
- DEFAULT 属于 READ
- ROW 属于 DEFAULT 和 WRITE 的交集
例如,假设组 G_01,G_02,G_03 已存在,设置 BOOKSHOP_USER 用户的组。
MAC_USER_SET_GROUPS ('P_04', 'BOOKSHOP_USER', 'G_01,G_02,G_03', 'G_02,G_03', 'G_01,G_03', 'G_03');
4.4.4 清除用户策略
使用下面的系统过程清除应用于某用户的指定策略。
VOID
MAC_USER_REMOVE_POLICY(
POLICY_NAME VARCHAR(128),
USER_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要清除的策略名
USER_NAME 用户名
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在。
例如,清除用户 BOOKSHOP_USER 的策略 P_04。
MAC_USER_REMOVE_POLICY ('P_04', 'BOOKSHOP_USER');
4.5 如何对会话应用策略
为了方便用户在执行时进行 MAC 权限的设置,系统提供了针对会话的标记设置,这些设置会挂载在会话上,一旦会话结束,这些信息就完全被抛弃,而不会影响系统表。
用户可以设置自身当前会话的默认标记,但其必须在合法的范围内,等级必须在用户的 MIN_LEVEL 和 MAX_LEVEL 之间,范围必须是用户 READ_COMP 的子集,组必须是用户 READ_GROUP 的子集。用户还可以设置会话的行级标记,同样必须在合法的范围内。
4.5.1 设置会话默认标记
使用如下的系统过程设置会话的默认标记:
VOID
MAC_SET_SESSION_LABEL(
POLICY_NAME VARCHAR(128),
LABELVALUE VARCHAR(4000)
);
参数说明:
POLICY_NAME 策略名
LABELVALUE 为会话设置的默认标记
使用说明:
- 设置的等级必须在用户的 MIN_LEVEL 和 MAX_LEVEL 之间,范围必须是用户 READ_COMP 的子集,组必须是用户 READ_GROUP 的子集;
- 由于行标记的范围来源于会话标记,故重置会话标记后,需对行标记进行调整。
例如,接 4.4.1、4.4.2、4.4.3 节的例子,BOOKSHOP_USER 用户设置会话默认标记。
MAC_SET_SESSION_LABEL('P_04', 'L_03:C_01,C_02:G_01,G_03');
4.5.2 设置会话行标记
使用如下的系统过程设置会话的行标记:
VOID
MAC_SET_SESSION_ROW_LABEL(
POLICY_NAME VARCHAR(128),
LABELVALUE VARCHAR(4000)
);
参数说明:
POLICY_NAME 策略名
LABELVALUE 为会话设置的行标记
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 设置的行标记必须是合法值。
例如,设置当前会话行标记。
MAC_SET_SESSION_ROW_LABEL('P_04', 'L_01:C_02:G_01');
4.5.3 清除会话标记
POLICY_NAME 要保存的会话标记所在的策略名
例如,将当前会话上策略 P_04 的标记刷入相应的数据字典。
使用如下的系统过程清除会话上对应某策略的标记:
VOID
MAC_RESTORE_DEFAULT_LABELS(
POLICY_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 指定策略名
使用说明:
清除当前会话对应指定策略的所有的标记,仅用户的标记可用。
例如,清除当前会话对应策略 P_04 的所有标记。
MAC_RESTORE_DEFAULT_LABELS('P_04');
4.5.4 保存会话标记
会话上的标记只在会话生存期间存在,并没有保存到数据库的数据字典中,一旦会话结束,会话标记就被丢弃。DM 提供以下的系统过程允许用户将会话上指定策略刷入相应的数据字典,这时,用户标记会被会话标记覆盖,会话标记与用户标记一致。
VOID
MAC_SAVE_DEFAULT_LABELS (
POLICY_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 要保存的会话标记所在的策略名
例如,将当前会话上策略 P_04 的标记刷入相应的数据字典。
使用如下的系统过程清除会话上对应某策略的标记:
MAC_SAVE_DEFAULT_LABELS('P_04');
4.6 读写控制规则
DM 支持同时使用自主访问控制与强制访问控制策略。自主访问控制策略优先于强制访问控制策略。为了能访问一条元组,用户不仅首先要满足自主访问控制条件,还必须满足强制访问控制的条件。
用户访问表时,必须保证应用于表上的所有策略均适用于该用户,否则访问被拒绝。若表上未应用任何策略,则用户只需满足自主访问控制条件即可。
4.6.1 读访问规则
强制访问控制的读访问规则为:
- 用户的等级必须大于等于数据的等级;
- 用户的标记必须包含至少一个数据的组(或者是其某一个的父亲组);
- 用户的标记必须包含数据的所有的范围。
如果用户满足以上三个规则,即可以对数据进行读取。比较的先后顺序是等级,组,范围。DM 中实现读访问规则的流程如图 4.1 所示。
4.6.2 写访问规则
强制访问控制的写访问规则为:
- 数据标记的等级必须大于等于用户标记的最小等级,小于或等于用户的会话标记的等级;
- 用户的标记必须包含至少一个数据的组(或者是其某一个的父亲组)的写权限;
- 用户的标记必须包含数据的所有的范围上的写权限。
如果用户满足以上三个规则,即可以对数据进行写操作。比较的先后顺序是等级,组,范围。DM 中实现写访问规则的流程如图 4.2 所示。
4.6.3 特权
在给用户应用策略时,可以同时授予策略特权。策略特权分为访问特权和行标记特权。
访问特权分为两种:
- READ:读数据时不受策略影响,但写数据访问控制仍然受到强制访问控制
- FULL:可以读写任何数据,不受策略影响。
一旦一个行的标记设定后,就需要行标记特权才能 UPDATE 其标记列。行标记特权有如下三种:
- WRITE UP:用户可以利用该特权提升一个行的等级,同时不改变范围和组。这个等级可以提高到用户的最高等级,而该行的原始等级可能比用户的最低等级还低
- WRITE DOWN:用户可以利用该特权降低一个行的等级,同时不改变范围和组。这个等级可以降低到用户的最低等级,而该行的原始等级可能比用户的最低等级还低
- WRITE ACROSS:用户可以利用该特权修改一个行的范围和组,同时不改变等级。新的范围和组只要满足在策略中是合理的就可以了,不必限于用户拥有访问权的范围和组
使用下面的系统过程为用户设置特权:
VOID
MAC_USER_SET_USER_PRIVS(
POLICY_NAME VARCHAR(128),
USER_NAME VARCHAR(128),
PRIVS VARCHAR(128)
);
参数说明:
POLICY_NAME 特权对应的策略名
USER_NAME 为其设置特权的用户名
PRIVS 特权类型
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- PRIVS 取值可以是 READ、FULL、WRITEUP、WRITEDOWN、WRITEACCROSS 中的一种或几种的组合。
例如,设置 BOOKSHOP_USER 用户的特权。
MAC_USER_SET_USER_PRIVS('P1', 'BOOKSHOP_USER', 'READ,WRITEUP');
4.7 扩展客体标记
除了行标记,DM 的扩展客体标记支持对数据库除约束和目录外的所有的客体进行标记,如模式、表、索引等对象。一旦一个对象被应用了扩展客体标记,则用户只有在支配相应标记的情况下,才能访问客体。
创建的新对象不会含有默认的标记,需要安全员进行手工设置。
4.7.1 对客体应用标记
使用下面的系统过程可以对客体应用标记:
VOID
MAC_APPLY_OBJ_POLICY(
POLICY_NAME VARCHAR(128),
OBJ_TYPE VARCHAR(128),
SCH_NAME VARCHAR(128),
OBJ_NAME VARCHAR(128),
COL_NAME VARCHAR(128),
LABEL VARCHAR(4000)
);
参数说明:
POLICY_NAME 策略名称
OBJ_TYPE 客体对象类型,必须是下面几个选项之一: “SCHEMA”、“TABLE”、“VIEW”、“INDEX”、“PROCEDURE”、“FUNCTION”、“PACKAGE”、“SEQUENCE”、“TRIGGER”、“COLUMN”、“SYNONYM”、“DOMAIN”、“CONTEXT INDEX”、“CONTEXT”
SCH_NAME 客体所在的模式名,为 NULL 时代表对库级的对象应用策略,如公用同义词
OBJ_NAME 应用标记的客体名称,如果对模式应用策略,则此值和 SCH_NAME 值一致
COL_NAME 应用标记的列名,只有在 OBJ_TYPE='COLUMN'时,此列才有效
LABEL 应用的标记值
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在。
例如,对模式 PRODUCTION 应用策略 P1 的标记(L1:C1:G1)。
MAC_APPLY_OBJ_POLICY('P1', 'SCHEMA', 'PRODUCTION', 'PRODUCTION', NULL'L1:C1:G1');
4.7.2 修改客体标记
使用下面的系统过程修改客体的标记:
VOID
MAC_ALTER_OBJ_POLICY(
POLICY_NAME VARCHAR(128),
OBJ_TYPE VARCHAR(128),
SCH_NAME VARCHAR(128),
OBJ_NAME VARCHAR(128),
COL_NAME VARCHAR(128),
LABEL VARCHAR(4000)
);
参数说明:
POLICY_NAME 策略名称
OBJ_TYPE 客体对象类型,必须是下面几个选项之一, “SCHEMA”、“TABLE”、“VIEW”、“INDEX”、“PROCEDURE”、“FUNCTION”、“PACKAGE”、“SEQUENCE”、“TRIGGER”、“COLUMN”、“SYNONYM”、“DOMAIN”、“CONTEXT INDEX”、“CONTEXT”
SCH_NAME 客体所在的模式名,为 NULL 时代表对库级的对象应用策略,如公用同义词
OBJ_NAME 修改标记的客体名称,如果对模式应用策略,则此值和 SCH_NAME 值一致
COL_NAME 修改标记的列名,只有在 OBJ_TYPE='COLUMN'时,此列才有效
LABEL 修改的标记值
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在。
例如,将模式 PRODUCTION 的标记修改为策略 P1 的标记(L1:C1,C2:G1)。
MAC_ALTER_OBJ_POLICY ('P1', 'SCHEMA', 'PRODUCTION', 'PRODUCTION', NULL, 'L1:C1,C2:G1');
4.7.3 删除客体标记
使用下面的系统过程删除指定客体上对应指定策略的标记:
VOID
MAC_DROP_OBJ_POLICY(
POLICY_NAME VARCHAR(128),
OBJ_TYPE VARCHAR(128),
SCH_NAME VARCHAR(128),
OBJ_NAME VARCHAR(128),
COL_NAME VARCHAR(128)
);
参数说明:
POLICY_NAME 策略名称
OBJ_TYPE 客体对象类型,必须是下面几个选项之一, “SCHEMA”、“TABLE”、“VIEW”、“INDEX”、“PROCEDURE”、“FUNCTION”、“PACKAGE”、“SEQUENCE”、“TRIGGER”、“COLUMN”、“SYNONYM”、“DOMAIN”、“CONTEXT INDEX”、“CONTEXT”
SCH_NAME 客体所在的模式名,为 NULL 时代表对库级的对象应用策略,如公用同义词
OBJ_NAME 删除标记的客体名称,如果对模式应用策略,则此值和 SCH_NAME 值一致
COL_NAME 删除标记的列名,只有在 OBJ_TYPE='COLUMN'时,此列才有效
使用说明:
- 该过程只能由具有 LABEL_DATABASE 的用户调用;
- 指定策略必须存在。
例如,删除模式 PRODUCTION 与策略 P1 相关的标记。
MAC_DROP_OBJ_POLICY('P1', 'SCHEMA', 'PRODUCTION', 'PRODUCTION',NULL);
4.8 一个强制访问控制的例子
下面给出一个强制访问控制的例子,综合运用了本章介绍的一些主要概念和方法。强制访问控制在真实应用中的使用会复杂得多,需要安全管理员事先进行全面的策略设计。
- SYSSSO 登录,创建一个策略 P_TEST
//SYSSSO/SYSSSO,创建策略
MAC_CREATE_POLICY('P_TEST');
MAC_CREATE_LEVEL('P_TEST', 11, 'L_01');
MAC_CREATE_LEVEL('P_TEST', 12, 'L_02');
MAC_CREATE_LEVEL('P_TEST', 13, 'L_03');
MAC_CREATE_LEVEL('P_TEST', 14, 'L_04');
MAC_CREATE_COMPARTMENT('P_TEST',11, 'C_01');
MAC_CREATE_COMPARTMENT('P_TEST',12, 'C_02');
MAC_CREATE_COMPARTMENT('P_TEST',13, 'C_03');
MAC_CREATE_COMPARTMENT('P_TEST',14, 'C_04');
MAC_CREATE_GROUP ('P_TEST',11, 'G_01',NULL);
MAC_CREATE_GROUP ('P_TEST',12, 'G_02','G_01');
MAC_CREATE_GROUP ('P_TEST',13, 'G_03','G_02');
- SYSDBA 登录,创建一个用户 USER_TEST,并授予其 RESOURCE 角色
//SYSDBA/SYSDBA,创建用户USER_TEST,并授予其RESOURCE角色
CREATE USER USER_TEST IDENTIFIED BY TEST12345;
GRANT RESOURCE TO USER_TEST;
- USER_TEST 登录,创建一个表 TEST,插入两行数据,并查询,此时由于没有对表应用策略,表中没有标记列
// USER_TEST/TEST12345,创建表TEST,插入数据
CREATE TABLE TEST(C1 INT, C2 INT);
INSERT INTO TEST VALUES(1,1);
INSERT INTO TEST VALUES(2,2);
COMMIT;
SELECT * FROM TEST;
行号 C1 C2
---------- ----------- -----------
1 1 1
2 2 2
- SYSSSO 登录,为用户 USER_TEST 和表 USER_TEST.TEST 应用策略
//SYSSSO/SYSSSO,为用户USER_TEST应用策略,为表USER_TEST.TEST应用策略
MAC_USER_SET_LEVELS('P_TEST', 'USER_TEST', 'L_04', 'L_01', 'L_03', 'L_02');
MAC_USER_SET_COMPARTMENTS('P_TEST', 'USER_TEST', 'C_01,C_02,C_03', 'C_01,C_02', 'C_01,C_03', 'C_01');
MAC_USER_SET_GROUPS ('P_TEST', 'USER_TEST', 'G_01,G_02,G_03', 'G_02,G_03', 'G_01,G_03', 'G_03');
MAC_APPLY_TABLE_POLICY ('P_TEST', 'USER_TEST', 'TEST', 'LABEL_COL', 'L_01::',0);
- USER_TEST 登录,此时查询表 TEST,可看到表中已有行的 LABEL_COL 值为应用表策略时指定的值
//USER_TEST/TEST12345
SELECT * FROM TEST;
行号 C1 C2 LABEL_COL
---------- ----------- ----------- -----------
1 1 1 11
2 2 2 11
- USER_TEST 继续操作,向表 TEST 插入一行新的记录,可以看到这行记录的标记为 USER_TEST 的行标记
INSERT INTO TEST(C1,C2) VALUES(3,3);
COMMIT;
SELECT * FROM TEST;
行号 C1 C2 LABEL_COL
---------- ----------- ----------- -----------
1 1 1 11
2 2 2 11
3 3 3 21
SELECT SF_MAC_LABEL_TO_CHAR(21);
行号 SF_MAC_LABEL_TO_CHAR(21)
---------- ------------------------
1 L_02:C_01:G_03
- USER_TEST 继续操作,设置会话默认标记和会话行标记,再向表 TEST 中插入一行数据,可看到这一行的标记为会话的行标记
MAC_SET_SESSION_LABEL('P_TEST', 'L_03:C_01,C_02:G_01,G_03');
MAC_SET_SESSION_ROW_LABEL('P_TEST', 'L_01:C_01:G_03');
INSERT INTO TEST(C1, C2) VALUES(4,4);
COMMIT;
SELECT * FROM TEST;
行号 C1 C2 LABEL_COL
---------- ----------- ----------- -----------
1 1 1 11
2 2 2 11
3 3 3 21
4 4 4 24
SELECT SF_MAC_LABEL_TO_CHAR(24);
行号 SF_MAC_LABEL_TO_CHAR(24)
---------- ------------------------
1 L_01:C_01:G_03
- SYSDBA 登录,查询表 USER_TEST.TEST,由于此时 SYSDBA 没有被应用策略 P_TEST,因此一行数据也不能访问
// SYSDBA/SYSDBA
SELECT * FROM USER_TEST.TEST;
未选定行
- SYSSSO 登录,为 SYSDBA 应用策略,设置 SYSDBA 的标记
//SYSSSO/SYSSSO,为SYSDBA应用策略
MAC_USER_SET_LEVELS('P_TEST', 'SYSDBA', 'L_01', 'L_01', 'L_01', 'L_01');
MAC_USER_SET_COMPARTMENTS('P_TEST', 'SYSDBA', 'C_01,C_02,C_03', 'C_01,C_02', 'C_01,C_03', 'C_01');
MAC_USER_SET_GROUPS ('P_TEST', 'SYSDBA', 'G_01,G_02,G_03', 'G_02,G_03', 'G_01,G_03', 'G_03');
- SYSDBA 登录,再次查询表 USER_TEST.TEST,根据读访问规则,可以查询到三条记录
// SYSDBA/SYSDBA
SELECT * FROM USER_TEST.TEST;
行号 C1 C2 LABEL_COL
---------- ----------- ----------- -----------
1 1 1 11
2 2 2 11
3 4 4 24
- SYSSSO 登录,为 SYSDBA 设置 READ 特权
// SYSSSO/SYSSSO,为SYSDBA设置特权
MAC_USER_SET_USER_PRIVS('P_TEST', 'SYSDBA', 'READ');
- SYSDBA 登录,再次查询表 USER_TEST.TEST,由于拥有 READ 特权,可以查询到全部记录
// SYSDBA/SYSDBA
SELECT * FROM USER_TEST.TEST;
行号 C1 C2 LABEL_COL
---------- ----------- ----------- -----------
1 1 1 11
2 2 2 11
3 3 3 21
4 4 4 24
4.9 相关数据字典表
DM 中与强制访问控制相关的数据字典表有以下这些,这些字典表属于模式“SYSSSO”,只有具有 SSO 类型的用户才能查询。
- SYSMACPLYS
记录策略定义。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | ID | INTEGER | 策略 ID |
2 | NAME | VARCHAR(128) | 策略名 |
- SYSMACLVLS
记录策略的等级。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | PID | INTEGER | 策略 ID |
2 | ID | SMALLINT | 等级 ID |
3 | NAME | VARCHAR(128) | 等级名 |
- SYSMACCOMPS
记录策略的范围。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | PID | INTEGER | 策略 ID |
2 | ID | SMALLINT | 范围 ID |
3 | NAME | VARCHAR(128) | 范围名 |
- SYSMACGRPS
记录策略所在组的信息。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | PID | INTEGER | 策略 ID |
2 | ID | SMALLINT | 组 ID |
3 | PARENTID | SMALLINT | 父节点 ID |
4 | NAME | VARCHAR(128) | 组名 |
- SYSMACLABELS
记录策略的标记信息。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | PID | INTEGER | 策略 ID |
2 | ID | INTEGER | 标记 ID |
3 | LABEL | VARCHAR(4000) | 标记信息 |
- SYSMACTABPLY
记录表策略信息。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | TID | INTEGER | 表 ID |
2 | PID | INTEGER | 策略 ID |
3 | COLID | SMALLINT | 列 ID |
4 | OPTIONS | BYTE | 可见性 |
- SYSMACUSRPLY
记录用户的策略信息。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | UID | INTEGER | 用户 ID |
2 | PID | INTEGER | 策略 ID |
3 | MAXREAD | INTEGER | 最大读标记 ID |
4 | MINWRITE | INTEGER | 最小写标记 ID |
5 | DEFTAG | INTEGER | 默认标记 ID |
6 | ROWTAG | INTEGER | 行级标记 ID |
7 | PRIVS | BYTE | 特权 |
- SYSMACOBJ
记录扩展客体标记信息。
序号 | 列 | 数据类型 | 说明 |
---|---|---|---|
1 | OBJID | INTEGER | 对象 ID |
2 | COLID | SMALLINT | 列 ID |
3 | PID | INTEGER | 策略 ID |
4 | TAG | INTEGER | 标记 ID |