PostgreSQL 安全管理 数据脱敏 Anonymizer 动态脱敏(Dynamic Masking)
1 背景知识
动态脱敏 (Dynamic Masking)
是一种在数据被访问时实时应用脱敏规则的过程,不修改存储在数据库中的原始数据,而是在查询结果返回给用户之前对数据进行脱敏处理。
本章将使用 Anonymizer 进行动态脱敏。
1.1 动态脱敏的优点
-
灵活性和透明性:可以根据用户的角色或权限动态地显示不同级别的数据细节,而不需要修改原始数据。
-
数据价值保留:原始数据保持不变,确保了数据的完整性和分析价值。
-
即时保护:适用于需要即时保护数据安全的环境,如生产环境中的实时数据访问。
1.2 动态脱敏的缺点
-
性能影响:动态掩码可能会增加数据库查询的处理时间,尤其是在数据量大或访问频繁的情况下。
-
安全性依赖于实现:如果动态掩码规则配置不当,可能会导致敏感信息的意外泄露。
-
管理复杂性:需要维护掩码规则和访问控制策略,对于有大量用户和复杂权限设置的环境来说,管理难度较高。
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();
8 图形工具报错问题
使用 DBeaver 或者 pgAdmin 等图形界面上使用脱敏用户时,使用 数据
面板是可能会产生以下错误:
SQL Error [42501]: ERROR: permission denied for table foo
这是因为这些工具都会直接查询 public.foo
表,而不是被重定向为 mask.foo
视图。
为了能够正常获取数据,你可以有两种方式获取数据。
- 打开SQL 查询窗口编写查询语句
SELECT * FROM people;
注意,这里不要指定模式名称,否则还是会报权限不足的错误。这种解决方式仍然是查询视图。
- 导航至:
Database > Schemas > mask > Views > foo