概述
由于敏感数据一直是数据库安全中最重要的一部分, 因此对于敏感数据的适当脱敏是很有必要的。 GBase 8a 提供动态数据脱敏的新功能供不同角色使用。
- 使得开发人员或者数据库管理员能够有效控制数据库中敏感数据的暴露程度,并且在数据库层面生成数据,这大大简化了数据库应用层的安全设计和编码。
- 使得用户可以通过 sql 语法的形式,给需要进行数据脱敏的字段添加脱敏属性,通过用户权限控制,决定是否对有查询要求的用户暴露原始数据。
运行环境
本功能为 GBase 8a 子功能模块。
运行环境参考 GBase 8a 或集群各版本运行环境。
脱敏功能
动态数据脱敏并不会真正改动表中存储的实际数据,只是在查询的时候应用该特性控制查询返回的数据。
动态数据脱敏是否启用受当前用户权限影响,拥有 unmask 权限的用户不受脱敏规则影响可以访问实际数据,没有 unmask 权限的用户受脱敏规则影响只能访问到脱敏后的数据。
脱敏只对投影列有效。
以下将内容详细介绍相关脱敏功能:
- 语法格式
- 函数介绍
- 相关属性
- 投影列函数脱敏说明
- 示例
语法格式
MASKED WITH(FUNCTION = ‗TYPE(参数)‘) |
动态数据脱敏支持四种参数 TYPE 数据脱敏函数, 如下:
1. 默认脱敏 default;
2. 随机脱敏 random;
3. 自定义脱敏 partial;
4. 哈希脱敏 sha。
1. default 类型。
这种类型没有参数。
MASKED WITH(FUNCTION = ‗DEFAULT()‘) |
2. random 类型。
random(min,max)有两个参数标定随机范围,最小值(1)和最大值(100)。
MASKED WITH(FUNCTION = ‗RANDOM(1,100)‘) |
3. partial 自定义类型。
这种类型包含三个参数, partial(prefix, padding, suffix),参数详细如下:
- prefix 表示前缀保留显示字符数量;
- padding 表示脱敏显示字符;
- suffix 表示结尾保留显示字符数量。
MASKED WITH(FUNCTION = ‗PARTIAL(1,‘XXXX‘,1)‘) |
sha 类型。
这个类型没有参数。
MASKED WITH(FUNCTION = ‗SHA()‘) |
函数介绍
默认脱敏函数
默认脱敏函数, 是针对基本类型的数据列进行脱敏的。
1. 若数据类型包含 date、 datetime 和 time。
- date 会以“ 1900-01-01”显示,
- datetime 会以―1900-01-01 00:00:00‖显示,
- time 会以“ 00:00:00”显示;
2. 若数据类型是整型、浮点型和 decimal。
- 整型和浮点型会显示 0,
- decimal 会显示为 0.000..., 带有结果小数位(定义的类型或者评估的类型)个数 0;
3. 若是字符串类型的。
将会替换为固定 4 个 X 字符“ XXXX”。
4. NULL 值。
不做脱敏处理,显示为 NULL。
5. Sql 函数。
如果任一参数含有脱敏属性,则按照结果类型,执行默认脱敏。
单行数据:
姓名(varchar) | 出生日期(datetime) | 年龄(int) |
Jone smith | 1989-03-04 12:31:24.123000 | 29 |
应用默认脱敏后数据后显示:
姓名(varchar) | 出生日期(datetime) | 年龄(int) |
XXXX | 1900-01-01 00:00:00 | 0 |
随机脱敏
随机脱敏函数只对数字类型起作用。
它会将随机显示某一个范围内的值,并多次执行,但同一行的随机值会不同。
先设置脱敏范围: 1-4
年龄(int) |
29 |
19 |
应用随机脱敏后显示:
年龄(int)
|
自定义脱敏
自定义脱敏是对字符列进行脱敏,用户可以设定三个参数, prefix 开始保留字符数量, suffix 结尾保留显示字符数量以及 padding 遮挡字符,如果实际内容长度小于等于 prefix+suffix+length(padding)长度,则直接显示 padding 的字符内容。
设定 prefix 为 3, suffix 为 6, padding 字符“XXXX”
内容(varchar(255)) |
This is a book on the desk. |
Hello |
应用自定义脱敏显示:
内容(varchar(255)) |
ThiXXXX desk. |
XXXX |
SHA 脱敏
SHA 脱敏对所有类型列都起作用,对列内容应用 SHA 算法处理。
插入内容
内容(varchar(255)) |
abc |
应用 SHA 脱敏后显示:
内容(varchar(255)) |
―a9993e364706816aba3e25717850c26c9cd0d89d‖ |
相关属性
语法格式
masked with(function=’脱密函数及参数’)) |
有两种方式可以添加字段的脱敏属性。
1. 建表, 只需要有 create 权限:
Create table t(a int masked with(function=‘default()‘)); Create table t(a int masked with(function=‘sha()‘)); Create table t(a int masked with(function=‘random(1,10)‘)); Create table t1(a varchar(255) masked with(function=‘partial(2,‖XXX‖, 3)‘)); |
投影列函数脱敏说明
脱敏规则
函数按照不同的处理逻辑,脱敏规则的获取方式也不相同,大致可分为两类。
1. 控制流函数可以直接返回脱敏列,而非对脱敏列进行比较和计算,这时函数将使用脱敏列的脱敏规则应用到其他返回值。这类函数有 case when/decode、 if、ifnull、 nvl 和 coalesce 函数。举例如下:
select case col when 1 then ‗123‘ when 2 then ‗456‘ when 3 then mask_col else ‗789‘ from t; 其中 col 为非脱敏列。 mask_col 为脱敏列, ―123‖、 ―456‖、 ―789‖ 为常量。 |
上面查询中 case when 函数可能的返回值为‘123‘、 ‘456‘、 ‘789‘和 mask_col,返回值中包含了脱敏列,这时会对常量‘123‘、 ‘456‘和‘789‘按照脱敏列 mask_col的脱敏规则进行脱敏。
当这类函数的返回值中有多个脱敏列(不同列)时,该函数将使用默认脱敏规则(不考虑多列脱敏规则是否完全相同)。
比如 :
select nvl(mask_col1, mask_col2) from t; |
nvl 函数将使用默认脱敏规则。
而
select nvl(mask_col1, mask_col1) from t; |
nvl 函数仍将使用 mask_col1 的脱敏规则。
当这类函数的返回值中有即包含脱敏列,同时也包含非脱敏列(不是常量)时,该函数也将使用默认脱敏规则。
比如:
select coalesce(col, mask_col) from t; |
coalesce 函数将使用默认脱敏规则。
当这类函数的返回值中类型不完全相同时,将会依据数据类型的转换规则进行转换,如果转换后的数据类型与脱敏列的原始类型不一致(只考虑 string、 real、decimal 和 int 四个级别,而不考虑更细的数据类型),则使用默认脱敏。
比如:
select coalesce(mask_int_col, 'abcdef') from t; |
coalesce 函数返回值为 string。
与 mask_int_col 的类型(int)不一致,所以 coalesce 将使用默认脱敏。
默认脱敏时,并不是将 mask_int_col 的值转换为 string,而是直接返回 string 类型的默认脱敏值(xxxx)。
附控制流函数类型转换规则:
- 任何一个参数为 string 时,则按 string 进行运算
- 没有 string 时,如果存在 real,按 real 进行运算
- 没有 string 和 real 时,如果存在 decimal,按 decimal 进行运算
- 日期时间类型算作 string 类型
控制流函数只对所有可能的返回值进行脱敏,对控制逻辑中的其他参数不脱敏,比如 case when 函数中只对 then 和 else 进行脱敏,对 case 和 when 分支中的参数不脱敏。
2. 绝大部分函数是对参数进行比较或者计算,比如一些字符串函数、比较函数、数值函数、时间和日期函数、 OLAP 函数和聚集函数等,这类函数的参数如果有脱敏列,这时函数将使用默认脱敏规则对返回值进行脱敏,而非对脱敏列脱敏后参与运算。
举例如下:
select concat(mask_col, ‗123‘) from t; |
其中 mask_col 为脱敏列, ‘123‘为常量。
上面查询中 concat 函数并非将脱敏后的 mask_col 字符串连接常量‘123‘,而是对 concat 返回值进行默认脱敏。由于 concat 返回值是字符类型,所以上述结果除 mask_col 为 NULL 的情况外( NULL 值情况返回值为 NULL),始终返回‘xxxx‘。
再比如 select mask_col > 1 from t; 将依据函数“ >”的返回值类型使用默认脱敏规则,所以除 mask_col 为 NULL 值外,始终返回 0。
脱敏规则继承
1. 函数嵌套使用时,内层函数的脱敏规则可以传递到外层。
这种传递也只限于非比较计算类的函数。
举例如下:
select case col when 1 then nvl(mask_col, ‗123‘) when 2 then ‗456‘ else ‗789‘ from t; |
上面查询中, nvl 函数可能的返回值有 mask_col 和‘123‘,所以 nvl 函数使用mask_col 的脱敏规则对 mask_col 和‘123‘脱敏,此脱敏规则同时也外层传递到
case when 函数中,所以‘456‘和‘789‘也会使用 mask_col 的脱敏规则脱敏。
2. 脱敏规则继承还出现在子查询的使用场景中,外层投影列的脱敏规则继承自子查询投影列的脱敏规则。
举例如下:
select col from (select reverse(mask_col) as col from t3) as tmp; |
其中 mask_col 为脱敏列。
上面查询中, reverse 函数会对参数进行比较或运算操作,所以当参数为脱敏列时 , 函 数 的 脱 敏 规 则 为 默 认 脱 敏 。 外 层 的 col 脱 敏 规 则 继 承 自 子 查 询reverse(mask_col)的脱敏规则,所以外层的 col 脱敏规则也为默认脱敏。
场景示例
为便于理解以上概念,下表举例说明每种典型场景下查询和结果节,用例使用的建表语句和数据为:
create table t (i1 int, vc1 varchar(10) masked with (function='partial(2,"*****",0)'), vc2 varchar(10) masked with (function='partial(2,"*****",0)')); insert into t values (1, 'nblknabpa', 'pombkaia'); insert into t values (2, '.mapkna', '0jbadflk'); insert into t values (); |
示例 1:第 i 类函数 case when 脱敏列规则;
gbase>select case i1 when 1 then vc1 when 2 then '12345' else '67890' end as res from t; +---------+ | res | +---------+ | nb***** | | 12***** | | 67***** | +---------+ |
示例 2:第 i 类函数 coalesce 脱敏列规则;
gbase>select coalesce(vc1,'12345') as res from t; +---------+ | res | +---------+ | nb***** | | .m***** | | 12***** | +---------+ |
示例 3:第 i 类函数 case when 多脱敏列默认脱敏;
gbase> select case i1 when 1 then vc1 when 2 then vc2 else '67890' end as res from t; +------+ | res | +------+ | xxxx | | xxxx | | xxxx | +------+ |
示例 4:第 ii 类函数 substring 默认脱敏;
gbase> select substring(vc1, 1, 2) as res from t; +------+ | res | +------+ | xx | | xx | | NULL | +------+ |
示例 5:第 ii 类函数 concat 默认脱敏;
gbase> select concat(vc1,'123') as res from t; +------+ | res | +------+ | xxxx | | xxxx | | NULL | +------+ |
示例 6:第 i 类函数嵌套使用;
gbase> select case when i1 > 1 then coalesce(vc1, '12345') else '67890' end as res from t; +---------+ | res | +---------+ | 67***** | | .m***** | | 67***** | +---------+ |
示例 7:第 ii 类函数嵌套使用;
gbase> select concat(substring(vc1,1,2),'123') as res from t; +------+ | res | +------+ | xxxx | | xxxx | | NULL | +------+ |
示例 8:第 i 类和 ii 类函数混合嵌套调用;
gbase> select coalesce(substring(vc1,1,2),'12345') as res from t; (或者 gbase>select substring(coalesce (vc1, '12345'), 1, 2) as res from t;) +------+ | res | +------+ | xxxx | | xxxx | | xxxx | +------+ |
示例 9:子查询内或外调用 i 类;
gbase> select res from (select coalesce(vc1,'12345')as res from t) as tmp; (或者 gbase> select coalesce(vc1, '12345') as res from (select vc1 from t) as tmp;) +---------+ | res | +---------+ | nb***** | | .m***** | | 12***** | +---------+ |
示例 10: 子查询内或外调用 ii 类;
gbase> select res from (select concat(vc1,'123') as res from t) as tmp; (或者 gbase> select concat (vc1, '123') as res from (select vc1 from t) as tmp;) +------+ | res | +------+ | xxxx | | xxxx | | NULL | +------+ |
示例 11: 子查询内外调用 i 类;
gbase> select case when i1 > 1 then res1 else '67890' end as res from (select i1,coalesce(vc1, '12345') as res1 from t) as tmp; +---------+ | res | +---------+ | 67***** | | .m***** | | 67***** | +---------+ |
示例 12: 子查询内外调用 ii 类;
gbase> select concat(res1,'123') as res from (select substring(vc1,1,2) as res1 from t) as tmp; +------+ | res | +------+ | xxxx | | xxxx | | NULL | +------+ |
示例 13: 子查询内外混合调用 i 类和 ii 类。
gbase> select substring(res1,1,4) as res from (select coalesce(vc1, '12345') as res1 from t) as tmp; (或者 gbase> select coalesce(res1, '12345') as res from (select substring(vc1,1,2) a s res1 from t) as tmp; ) +------+ | res | +------+ | xxxx | | xxxx | | xxxx | +------+ |
说明
脱敏列脱敏后如果超过脱敏列的最大长度,则自动截断为脱敏列的最大长度。
比如脱敏列定义为:
mask_col varchar(5) masked with (function ='partial(2,"xxxx",2)') |
则值―abcde‖理论上应脱敏为―abxxxxde‖,脱敏后的长度超过了最大长度 5,自动截断为―abxxx‖。同样对于一些可设置长度的函数脱敏时也会被截断,比如:
select left(mask_col, 2) from t; |
left 函数将使用默认脱敏,理论上应脱敏为―xxxx‖,但超过了 left 函数设置的最大长度,所以自动截断为―xx‖。
Union、 Intersect 和 Minus 运算时,对应列的脱敏规则与控制流函数的脱敏规则选取规则一致。
比如:
select mask_int_col from t union select mask_int_col as col from t; |
将使用 mask_int_col 的脱敏规则,而:
select mask_int_col from t union select mask_int_col+1 from t; |
将使用默认脱敏。