[Oracle Database 12c New Feature] Advanced Security – Oracle Data Redaction

作者:张乐奕

2014 年 12 月发布

1. 什么是 Oracle Data Redaction

不确认正式的中文翻译是什么,我翻译为数据改写。这是一项在 12c 中出现的 Oracle 高级安全新组件,其作用是限制 SQL 语句的返回结果样式,对于特定的用户可以限制某些字段显示被自动改写过的值。这是一项非常有用的安全功能,而在 12c 之前如果要实现相同的功能,可能需要创建特定的视图,或者在存储到数据库的时候就用加密算法进行加密。而 12c 的数据改写功能则在最后数据返回到客户端的前一刻将数据改写,这并不会影响到数据真实的存储。看一个简单的例子就明白了。

原本存储的数据记录如下:

SQL> SELECT * FROM EMPLOYEES;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      247-85-9056       7000
        101 Neena                Kochhar                   334-08-6578       5000

在设置完 Data Redaction 之后,再次执行相同的语句,可以看到有隐私性质的列-社会保障号被遮盖了,只显示最后 4 位,这就实现了安全的目的。

SQL> SELECT * FROM kamus.employees;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      ***-**-9056       7000
        101 Neena                Kochhar                   ***-**-6578       5000

2. 如何设置 Oracle Data Redaction

设置用户的合适权限,由于 Oracle Redaction 对于 DBA 用户不起效果,因此需要将 DBA 角色收回。

REVOKE dba FROM kamus;
GRANT CONNECT, resource, unlimited tablespace TO kamus;
GRANT SELECT ON sys.redaction_policies TO kamus;
GRANT SELECT ON sys.redaction_columns TO kamus;
GRANT EXECUTE ON dbms_redact TO kamus;

创建测试环境,包括测试表和测试数据。

CREATE TABLE "EMPLOYEES" (
"EMPLOYEE_ID" NUMBER(6,0), 
"FIRST_NAME" VARCHAR2(20), 
"LAST_NAME" VARCHAR2(25), 
"SOCIAL_SECURITY" VARCHAR2(11), 
"SALARY" NUMBER(4,0)
)
/
 
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SOCIAL_SECURITY,SALARY) VALUES (100,'Steven','King','247-85-9056',7000);
INSERT INTO EMPLOYEES (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SOCIAL_SECURITY,SALARY) VALUES (101,'Neena','Kochhar','334-08-6578',5000);
commit;
 
SQL> SELECT * FROM EMPLOYEES;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      247-85-9056       7000
        101 Neena                Kochhar                   334-08-6578       5000

Oracle Redaction 针对单张表的某个字段进行设置,分别通过 ADD_POLICY 存储过程的 object_namecolumn_name 来控制;Redaction 有多种类型,第一种为 FULL,也就是完全改写,对于字符类型的字段将改写为一个空格,对于数字类型的字段改写为 0,对于日期类型的字段改写为 2001-01-01,类型通过 function_type 参数来控制。

BEGIN
DBMS_REDACT.ADD_POLICY (
   object_schema          => 'KAMUS',
   object_name            => 'EMPLOYEES',
   policy_name            => 'REDACT_EMP',
   column_name            => 'SOCIAL_SECURITY',
   function_type          => DBMS_REDACT.FULL,
   expression             => '1=1',
   enable                 => TRUE
   );
END;
/
 
SQL> SELECT * FROM employees;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                                        7000
        101 Neena                Kochhar                                     5000

Redaction 的第二种类型是 RANDOM,对于字符类型的字段将改写为随机字符,对于数字类型的字段改写为具有相同长度的随机数字,对于日期类型的字段改写为随机日期(永远不会跟真实日期相同)。

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'KAMUS',
   object_name            => 'EMPLOYEES',
   policy_name            => 'REDACT_EMP',
   column_name            => 'SOCIAL_SECURITY',
   action                 => DBMS_REDACT.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.RANDOM
);
END;
/
 
SQL> SELECT * FROM kamus.employees;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      wa};w~ZC i&       7000
        101 Neena                Kochhar                   Q9N]##T/YAV       5000

Redaction 的第三种类型是 PARTIAL,将改写为按照 function_parameters 参数指定的格式。

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'KAMUS',
   object_name            => 'EMPLOYEES',
   policy_name            => 'REDACT_EMP',
   column_name            => 'SOCIAL_SECURITY',
   action                 => DBMS_REDACT.MODIFY_COLUMN,
   function_type          => DBMS_REDACT.PARTIAL,
   function_parameters    => 'VVVFVVFVVVV,VVV-VV-VVVV,*,1,5'
);
END;
/
 
SQL> SELECT * FROM kamus.employees;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      ***-**-9056       7000
        101 Neena                Kochhar                   ***-**-6578       5000

3. 如何精细化设置哪些用户才启用数据改写

通过 expression 参数设置,比如如下所示,所有不是 KAMUS 的用户都启用在 EMPLOYEES.SOCIAL_SECURITY 字段上的数据改写,而如果是 KAMUS 用户进行检索,则还是返回真实的数据。

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'KAMUS',
   object_name            => 'EMPLOYEES',
   policy_name            => 'REDACT_EMP',
   column_name            => 'SOCIAL_SECURITY',
   action                 => DBMS_REDACT.MODIFY_EXPRESSION,
   expression             => 'SYS_CONTEXT ( ''USERENV'',''SESSION_USER'' ) !=''KAMUS'''
);
END;
/

expression 参数非常灵活,通过此参数可以使 Data Redaction 发挥巨大的作用。expression 参数可选值如下图所示。
Screen Shot 2013-07-31 at 6.27.12 PM

4. 如何增加数据改写策略

通过 DBMS_REDACT.ALTER_POLICY 存储过程可以增加多个字段的数据改写策略,比如下例,增加在 SALARY 字段上的全数据改写。

BEGIN
DBMS_REDACT.ALTER_POLICY (
   object_schema          => 'KAMUS',
   object_name            => 'EMPLOYEES',
   policy_name            => 'REDACT_EMP',
   column_name            => 'SALARY',
   action                 => DBMS_REDACT.ADD_COLUMN,
   function_type          => DBMS_REDACT.FULL,
   expression             => 'SYS_CONTEXT ( ''USERENV'',''SESSION_USER'' ) !=''KAMUS'''
);
END;
/
 
SQL> SELECT * FROM kamus.employees;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      ***-**-9056          0
        101 Neena                Kochhar                   ***-**-6578          0

5. 数据改写到底是发生在哪一阶段,有哪些限制

--where 条件中的字段并不会受数据改写影响,可以看到即使最后都是显示 SALARY=0,但是 where 条件还是正常执行并筛选出正确结果的。
SQL> SELECT * FROM kamus.employees WHERE SALARY>5000;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        100 Steven               King                      ***-**-9056          0
 
SQL> SELECT * FROM kamus.employees WHERE SALARY<5000;
 
no ROWS selected
 
SQL> SELECT * FROM kamus.employees WHERE SALARY=5000;
 
EMPLOYEE_ID FIRST_NAME           LAST_NAME                 SOCIAL_SECU     SALARY
----------- -------------------- ------------------------- ----------- ----------
        101 Neena                Kochhar                   ***-**-6578          0
 
--在启用了数据改写策略的表上无法进行全表的 CTAS 操作。
SQL> CREATE TABLE t AS SELECT * FROM kamus.employees;
CREATE TABLE t AS SELECT * FROM kamus.employees
                         *
ERROR at line 1:
ORA-28081: Insufficient privileges - the command REFERENCES a redacted object.
 
--如果 CTAS 操作中的字段上没有启用数据改写策略,CTAS 可以正常进行。
SQL> CREATE TABLE t AS SELECT EMPLOYEE_ID,FIRST_NAME FROM kamus.employees;
 
TABLE created.
 
SQL> DROP TABLE t;
 
TABLE dropped.
 
--如果包含了启用数据改写策略的列,则会报 ORA-28081 错误。
SQL> CREATE TABLE t AS SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM kamus.employees;
CREATE TABLE t AS SELECT EMPLOYEE_ID,FIRST_NAME,SALARY FROM kamus.employees
                                                *
ERROR at line 1:
ORA-28081: Insufficient privileges - the command REFERENCES a redacted object.

鼓励发表数据库选件 (DBO) 相关的内容或在 Oracle 技术网上发表文章。参见在 Oracle 技术网上发表技术文章