PostgreSQL 安全管理 数据脱敏 Anonymizer 动态脱敏(Dynamic Masking)

1 背景知识

动态脱敏 (Dynamic Masking) 是一种在数据被访问时实时应用脱敏规则的过程,不修改存储在数据库中的原始数据,而是在查询结果返回给用户之前对数据进行脱敏处理。

本章将使用 Anonymizer 进行动态脱敏。

1.1 动态脱敏的优点

  1. 灵活性和透明性:可以根据用户的角色或权限动态地显示不同级别的数据细节,而不需要修改原始数据。

  2. 数据价值保留:原始数据保持不变,确保了数据的完整性和分析价值。

  3. 即时保护:适用于需要即时保护数据安全的环境,如生产环境中的实时数据访问。

1.2 动态脱敏的缺点

  1. 性能影响:动态掩码可能会增加数据库查询的处理时间,尤其是在数据量大或访问频繁的情况下。

  2. 安全性依赖于实现:如果动态掩码规则配置不当,可能会导致敏感信息的意外泄露。

  3. 管理复杂性:需要维护掩码规则和访问控制策略,对于有大量用户和复杂权限设置的环境来说,管理难度较高。

2 如何使用动态脱敏

2.1 环境准备

DROP TABLE IF EXISTS  people CASCADE;
CREATE TABLE people (id TEXT, firstname TEXT, 
					 lastname TEXT, phone TEXT);
INSERT INTO people VALUES ('T1','Sarah', 'Conor','0609110911');
SELECT * FROM people;
//屏幕输出:
CREATE TABLE
=# SELECT * FROM people;
 id | firstname | lastname |   phone
----+----------+----------+------------
 T1 | Sarah    | Conor    | 0609110911
(1 row)

2.2 加载动态脱敏功能

CREATE EXTENSION IF NOT EXISTS anon CASCADE;
SELECT anon.start_dynamic_masking();
//屏幕输出:
NOTICE:  extension "anon" already exists, skipping
CREATE EXTENSION
 start_dynamic_masking 
-----------------------
 t
(1 row)

2.3 声明脱敏用户

CREATE ROLE skynet LOGIN;
SECURITY LABEL FOR anon ON ROLE skynet
IS 'MASKED';
//屏幕输出:
CREATE ROLE
SECURITY LABEL

2.4 声明脱敏规则

SECURITY LABEL FOR anon ON COLUMN people.lastname
IS 'MASKED WITH FUNCTION anon.fake_last_name()';

SECURITY LABEL FOR anon ON COLUMN people.phone
IS 'MASKED WITH FUNCTION anon.partial(phone,2,$******$,2)';

2.5 切换为脱敏用户

使用脱敏用户时,数据已经被脱敏。

\c - skynet; 
SELECT * FROM people;
 id | firstname | lastname  |   phone
----+----------+-----------+------------
 T1 | Sarah    | Stranahan | 06******11
(1 row)

2.6 切换为非脱敏用户

使用其他用户时,数据未被脱敏。

\c - postgres
select * from people ;
 id | firstname | lastname |   phone    
----+-----------+----------+------------
 T1 | Sarah     | Conor    | 0609110911
(1 row)

3 更改脱敏列的数据类型

当开启动态脱敏功能后,是不允许修改有脱敏规则的列的数据类型。如需修改请停止动态脱敏功能。

BEGIN;
SELECT anon.stop_dynamic_masking();
ALTER TABLE people ALTER COLUMN phone TYPE VARCHAR(255);
SELECT anon.start_dynamic_masking();
COMMIT;
//屏幕输出:
COMMIT;
BEGIN
NOTICE:  The previous priviledges of 'dump_anon' are not restored. You need to grant them manually.
NOTICE:  The previous priviledges of 'attacker' are not restored. You need to grant them manually.
NOTICE:  The previous priviledges of 'skynet' are not restored. You need to grant them manually.
 stop_dynamic_masking 
----------------------
 t
(1 row)

ALTER TABLE
 start_dynamic_masking 
-----------------------
 t
(1 row)

COMMIT

4 如何查看动态脱敏规则

SELECT * FROM anon.pg_masking_rules;

更多信息请查看 脱敏规则视图

5 如何删除动态脱敏表

动态脱敏引擎将会在表上简历脱敏视图,这意味着无法直接删除脱敏规则表。

DROP TABLE people ;
//屏幕输出:
ERROR:  cannot drop table people because other objects depend on it
DETAIL:  view mask.people depends on table people
HINT:  Use DROP ... CASCADE to drop the dependent objects too.

可以添加 CASCADE 选项,这样脱敏视图也会被删除。

DROP TABLE people CASCADE;

6 如何让用户解除动态脱敏

解除脱敏规则对 bob 用户的影响。

SECURITY LABEL FOR anon ON ROLE skynet IS NULL;

也可以使用下面的函数一次性解除所有用户。

SELECT anon.remove_masks_for_all_roles();

若想要从表上删除脱敏规则,请参考 Anonyimizer 脱敏规则章节。

7 对于动态脱敏的一些局限性

7.1 无法显示表名称

由于动态脱敏的工作原理,在切换为脱敏用户时,使用 \dt 命令将不会显示任何信息。这是由于更改了 sarch_path 导致的。
你可以使用显式的使用模式名前缀:

\dt *.*
\dt public.*

7.2 只对一个模式生效问题

动态脱敏只适用于一个模式使用。使用 start_dynamic_masking() 函数加载动态脱敏模式时可以指定针对哪一个模式生效。

ALTER DATABASE testdb SET anon.sourceschema TO 'sales';

然后就可以开启动态脱敏功能了。

SELECT start_dynamic_masking();
Important

使用静态脱敏导出脱敏 可以在多个模式下正常工作。

8 图形工具报错问题

使用 DBeaver 或者 pgAdmin 等图形界面上使用脱敏用户时,使用 数据 面板是可能会产生以下错误:

SQL Error [42501]: ERROR: permission denied for table foo

这是因为这些工具都会直接查询 public.foo 表,而不是被重定向为 mask.foo 视图。

DBeaver 查询脱敏表|700

为了能够正常获取数据,你可以有两种方式获取数据。

  1. 打开SQL 查询窗口编写查询语句 SELECT * FROM people;
Warning

注意,这里不要指定模式名称,否则还是会报权限不足的错误。这种解决方式仍然是查询视图。

DBeaver 查询脱敏表|700

  1. 导航至:Database > Schemas > mask > Views > foo