
# 使用HetuEngine动态脱敏功能
#### 背景介绍
虽然Ranger已经支持了静态脱敏的能力，但是静态脱敏后会出现数据不可用的问题，主要表现为：
- 脱敏的数据无法匹配谓词过滤。
- 脱敏后的数据无法进行Join等联合查询操作。
- 只支持string类型的列脱敏。
静态脱敏场景单一，限制较多，数据在计算前就已经被脱敏，为满足更灵活的脱敏需求，HetuEngine提供支持数据"可算不可见"、集群内脱敏策略自动传递等数据脱敏能力，即动态脱敏。
#### 操作场景
通过MRS Ranger配置HetuEngine脱敏信息，HetuEngine支持数据"可算不可见"、集群内脱敏策略自动传递等数据脱敏能力，包括查询和写入场景。
1. 支持配置脱敏后，对表进行查询，配置脱敏的列数据将进行自动脱敏。配置脱敏的列能正常进行谓词匹配，仅对输出结果进行脱敏。
2. 配置脱敏的列能正常做联合查询（Join、Union、In、Exist等），仅对最后的输出结果进行脱敏。
3. CTS后新表数据自动脱敏。如果数据源为本集群hive数据源，则数据本身不脱敏，同步脱敏策略，查询结果脱敏；其他数据源数据脱敏后输出
4. ITS后新表数据支持脱敏。如果数据源为本集群hive数据源，则数据本身不脱敏，同步脱敏策略，查询结果脱敏；其他数据源数据脱敏后输出。同步脱敏策略时有以下几种情况：若目标表对应列没有脱敏策略，则脱敏策略直接同步；若目标表已有脱敏策略，且与源表相同，则脱敏策略不变；若目标表已有脱敏策略且与源表有冲突，则目标表脱敏策略强制重置为"\*\*\*"。
5. 通过View引用的脱敏列信息，查询View后，数据也是脱敏的。
6. 配置脱敏后，对应函数计算、函数嵌套、以及子查询嵌套结果均脱敏。
7. 查询使用别名、CTS使用别名情况支持脱敏。
 
#### 约束与限制
- 不支持Hudi表的脱敏。
- 动态脱敏仅支持在集群已启用Kerberos认证（安全模式）中使用。
- 当前Ranger配置CUSTOM自定义策略时，动态脱敏一律按照"\*"策略处理，例如"ABCDE"脱敏为"\*\*\*\*\*"。
- 由于Ranger策略更新检测周期为30s，执行CTS等语句如果涉及到策略同步，Ranger侧新建的策略生效存在一定的延迟。
- 仅支持共部署的Hive数据源。
- 由于查询视图时，实际访问表的是视图owner，所以在为敏感数据表创建视图时，需要对创建视图的用户脱敏。
- 动态脱敏与静态脱敏均基于Ranger配置的脱敏策略，需要开启HetuEngine服务的Ranger功能。Ranger脱敏策略介绍以及配置方法见[配置HetuEngine数据脱敏](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1862.html#mrs_01_1862__section67107593567)。
- 不支持复杂数据类型array、map、struct的脱敏。
- 脱敏策略传递时，若目标表已有脱敏策略且与源表有冲突，则会删除冲突的策略，并自动创建新策略将目标表脱敏策略强制重置为"Custom:"\*\*\*""，删除目标表此策略会删除。
- 字符串字段类型脱敏结果与Ranger上配置的脱敏策略一致，其他类型字段脱敏都按"Nullify"脱敏策略处理。
 
#### 开启动态脱敏操作步骤
1. 使用可访问HetuEngine WebUI界面的用户登录MRS集群Manager。 
   登录集群Manager具体操作，请参考[访问MRS集群Manager](https://support.huaweicloud.com/usermanual-mrs/mrs_01_0128.html)。
   
   
2. 选择"集群 \> 服务 \> HetuEngine"，进入HetuEngine服务页面。
3. 在"概览"页签下的"基本信息"区域，单击"HSConsole WebUI"后的链接，进入HSConsole界面。
4. 在"计算实例"页签，在待操作的实例所属租户所在行的"操作"列单击"配置"。
5. 在"自定义配置"单击"增加"添加如下参数。 
   表1HetuEngine动态脱敏参数 
   | 参数                          | 取值示例 | 参数文件                                                                                                                                                                                                                  | 描述                                                                                                                                                                                                |
   |:---|:---|:---|:---|
   | hetu.dynamic.masked.enabled | true | - coordinator.config.properties  - worker.config.properties   | - 开启HetuEngine动态脱敏功能。  - 默认值：false。   |
      
   
   
6. 添加完成后将"立即启动"设置为"是"，单击"确定"。
7. 开启动态脱敏策略传递功能。 
   1. 单击"数据源"，在数据源名称为"hive"的本地数据源的"操作"列，单击"编辑"。
   
   2. 在"自定义配置"单击"增加"，添加参数"hive.dynamic.masked.policy.sync.enabled"，值为"true"，单击"确定"。
   
   
   
   
 
#### 特性说明（MRS 3.6.0-LTS及之后版本）
- HetuEngine动态脱敏后返回字段类型与输出列的schema类型一致，无法保持一致的使用null表示脱敏后的结果。

- 支持不脱敏UDF名单和强制hash脱敏UDF名单配置。
  
  | 参数名称                       | 说明                                                                                                                               | 默认值                                                                      |
  |:---|:---|:---|
  | hetu.udf.hash.dynamic.mask | 开启动态脱敏后，使用Partial mask: show last 4、Partial mask: show first 4、Custom脱敏策略脱敏时，需要强制使用hash脱敏处理的函数名单。如果有多个函数需要强制使用hash脱敏处理，则以英文逗号隔开。 | substr,substring,concat,concat_ws,lpad,repeat,rpad,reverse,replace,split |
  | hetu.udf.skip.dynamic.mask | 开启动态脱敏后，不需要脱敏处理的函数名单。如果有多个函数不需要脱敏处理，则以英文逗号隔开。                                                                                    | -                                                                        |
     
  "hetu.udf.skip.dynamic.mask"的优先级大于"hetu.udf.hash.dynamic.mask"。如果一个函数名同时配置在"hetu.udf.skip.dynamic.mask"和"hetu.udf.hash.dynamic.mask"中时，会按照"hetu.udf.skip.dynamic.mask"逻辑处理，不进行脱敏处理。
  

- Custom脱敏策略支持配置mask_partial函数：
  **mask_partial函数介绍**
  - 处理数值类型的**mask_partial** 说明。
    ```
    mask_partial(column_name, mask_digital, mask_from[, mask_to])
    ```
    描述：针对数值类型数据（int、decimal、float、bigint、tinyint、smallint、double），将第mask_from到mask_to位的数字部分脱敏成mask_digital对应的数字。
    表2参数说明1 
    | 参数           | 说明                  |
    |:---|:---|
    | mask_to      | 允许缺省，缺省时即脱敏到数据结束位置。 |
    | mask_digital | 只能取\[1,9\]区间内的数字。   |
       
    - 对于decimal、float、double类型，小数点参与计数，但不参与脱敏。如：列内容为:3.1415926，mask_partial('2',1,3），返回值：2.2415926。
    
    - Spark-beeline场景下，使用**mask_partial**对decimal脱敏后，结果会不符合预期，但结果是脱敏的，非原始值。
    
    
    返回值类型：与入参column_name数据类型相同。
    
  
  - 处理字符类型的**mask_partial** 说明。
    ```
    mask_partial(column_name , mask_char, mask_from[, mask_to])
    ```
    描述：针对字符类型数据（char, varchar, string），对照指定的输入输出格式，将第mask_from到mask_to位的数字部分脱敏成mask_char指定的字符。
    表3参数说明2 
    | 参数        | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
    |:---|:---|
    | mask_char | 脱敏字符，仅允许长度为1的任意字符。支持字符范围： - 大写字母：A, B, C, D, E, ..., Z  - 小写字母：a, b, c, d, e, ..., z  - 阿拉伯数字：0, 1, 2, 3, 4, 5, 6, 7, 8, 9  - 标点符号：句号（.）、逗号（,）、问号（?）、感叹号（!）、冒号（:）、分号（;）、引号（"）、括号（( 或 )，\[ 或 \]，{ 或 }）、连字符（-）  - 特殊符号：@ 符号 (@)、井号 、美元符号 ($)、百分号 (%)、和号 (\&)、星号 (\*)、加号 (+)、等号 (=)、波浪号 (\~)、下划线 (_)、竖线 (\|)   |
    | mask_from | 脱敏范围的起始位置，要求大于0。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
    | mask_to   | 脱敏范围的结束位置，允许缺省。缺省时，即脱敏到原始数据结束位置。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
       
    返回值类型：与入参column_name数据类型相同。
    
    
- 处理时间类型的**mask_partial** 说明。
  ```
  mask_partial(column_name, mask_digital, mask_from[, mask_to])
  ```
  描述：针对时间类型数据（Date、TimeStamp），将第mask_from到mask_to位的数字部分脱敏成mask_digital对应的数字。
  表4参数说明3 
  | 参数           | 说明                  |
  |:---|:---|
  | mask_to      | 允许缺省，缺省时即脱敏到数据结束位置。 |
  | mask_digital | 只能取\[1,9\]区间内的数字。   |
     
  - Date只支持年、月、日的脱敏。
  
  - TimeStamp支持年、月、日、时、分、秒、毫秒/微秒/纳秒的脱敏。
    - Date、TimeStamp中的"-"、"/"、空格、":"参与计数，不脱敏。
    
    - Date、TimeStamp中，月、日的值脱敏后超过正常范围后将进行反转处理，例如： 月的值为02，脱敏后为33，最终值为33%12=9。
      日的值为10，脱敏后为44，最终值为44% (脱敏后的年对应的脱敏后的月的天数) , 假设脱敏后的年为2024，脱敏后的月为9(2024年9月有30天)， 最终值为14。
      
     
  
  - TimeStamp中的时、分、秒、毫秒/微秒/纳秒脱敏后，超过正常范围后，也进行反转处理。
    - 时的值为20，脱敏后为66，最终值为66%24=18。
    
    - 分的值为30，脱敏后为66，最终值为66%60=6。
    
    - 秒的值为50，脱敏后为66，最终值为66%60=6。
    
    - 毫秒/微秒/纳秒不涉及超出正常值范围场景。 例如：
      date类型脱敏：值为1920-01-03，使用mask_partial('2',5,8)脱敏后，结果为1920-10-03。
      TimeStamp类型脱敏：值为'2023-12-05 12:34:56.789' ，使用mask_partial('2',5,8)脱敏后，结果为'2023-10-05 12:34:56.789'。
      
     
  
  
  返回值类型：与入参column_name数据类型相同。
  **mask_partial约束与限制**
  - MRS mask_partial的入参中不支持嵌套UDF。
  
  - mask_partial遇到数值、字符、时间之外的不支持的类型时，统一返回null。
  
  - mask_from从1开始计数，即mask_from要求是大于0的整数，小于1时，默认按照1处理。
  
  - mask_to可以不填，不填时，默认为对应字符的结束位置，mask_to可以为负数，-1表示字符的结束位置。
  
  - mask_to对应字符串的位置不能在mask_from之前，遇到该情况时，统一返回null。
  
  - mask_partial处理类型为数值类型时， mask_digital不属于\[1,9\]区间内的数字时，UDF函数返回null。
  
  - mask_partial处理类型为字符类型时， mask_char不支持该字符类型时，UDF函数返回null。
  
  - 遇到mask_partial编写错误、入参不支持、入参有误场景， 引擎直接发生异常。
   
  **mask_partial使用介绍**
  在ranger上配置脱敏策略，Mask Conditions选择Custom，在自定义输入框中填写mask_partial(mask_digital, mask_from\[, mask_to\])，其中mask_digital需要使用单引号括起来，如'9'、'\*'。
  Mask Conditions选择Custom，配置mask_partial脱敏函数时，第一个入参不需要指定列名，直接从mask_partial函数介绍中的第二个入参开始填写。
  例如：mask_partial('\*',1,5)
  ![](https://support.huaweicloud.com/cmpntguide-lts-mrs/zh-cn_image_0000002219681468.png)
  
 
