openGauss 2.0版本已经内置动态脱敏的特性,相关特性介绍可以参考我写过的这篇文章: <<openGauss数据动态脱敏之不同策略测试>>
PostgreSQL内核目前还不支持里这个特性,但gitlab上有个插件Anonymizer支持该特性,本文参考官方文档进行简单的测试。
1.安装部署Anonymizer
https://postgresql-anonymizer.readthedocs.io/en/latest/INSTALL/#install-from-source
参考上面源码编译方式,本地编译示例如下:
$ make cp anon.sql anon/anon--1.1.0.sql cp data/*.csv anon/ cp python/populate.py anon/
$ make install cp anon.sql anon/anon--1.1.0.sql cp data/*.csv anon/ cp python/populate.py anon/ /usr/bin/mkdir -p '/opt/pg15/share/postgresql/extension' /usr/bin/mkdir -p '/opt/pg15/share/postgresql/extension/anon' /usr/bin/mkdir -p '/opt/pg15/lib/postgresql' install -d /opt/pg15/bin install -m 0755 bin/pg_dump_anon.sh /opt/pg15/bin /usr/bin/install -c -m 644 .//anon.control '/opt/pg15/share/postgresql/extension/' /usr/bin/install -c -m 644 .//anon/* '/opt/pg15/share/postgresql/extension/anon/' /usr/bin/install -c -m 755 anon.so '/opt/pg15/lib/postgresql/'
数据库级别配置动态库
create database foo; alter database foo set session_preload_libraries = 'anon';
在示例数据库foo中创建anon扩展插件,anon依赖加密插件pgcrypto,需要先创建pgcrypto:
\c foo create extension pgcrypto; create extension anon;
创建完后检查扩展插件
foo=# \dx List of installed extensions Name | Version | Schema | Description ----------+---------+------------+------------------------------ anon | 1.1.0 | public | Data anonymization tools pgcrypto | 1.3 | public | cryptographic functions plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language (3 rows)
如果需要使用伪造函数,需要执行下面的初始化函数,生成伪造数据。
SELECT anon.init();
2.anon参数设置
anon插件主要支持如下参数的设置:
进行如下设置:
alter database foo set anon.restrict_to_trusted_schemas = on; alter database foo set anon.salt = 'db_foo_Secret_Salt';
重新连接数据库后执行如下语句:
select anon.start_dynamic_masking();
3.配置脱敏规则
数据脱敏规则通过security labels进行声明:
CREATE TABLE public.player(id SERIAL, name TEXT, points INT); INSERT INTO public.player VALUES ( 1, 'Kareem Abdul-Jabbar', 38387), ( 5, 'Michael Jordan', 32292 ); SECURITY LABEL FOR anon ON COLUMN player.name IS 'MASKED WITH FUNCTION anon.fake_last_name()'; SECURITY LABEL FOR anon ON COLUMN player.id IS 'MASKED WITH VALUE NULL';
如果安全标签声明内容里包含字符串标量,可以使用C风格的转义或使用双美元符号。 使用C风格转义:
SECURITY LABEL FOR anon ON COLUMN player.name IS E'MASKED WITH VALUE \'CONFIDENTIAL\'';
或使用双美元符:
SECURITY LABEL FOR anon ON COLUMN player.name IS 'MASKED WITH VALUE $$CONFIDENTIAL$$';
使用表达式
SECURITY LABEL FOR anon ON COLUMN player.name IS 'MASKED WITH VALUE CASE WHEN name IS NULL THEN $$John$$ ELSE anon.random_string(LENGTH(name)) END';
移除单个列的脱敏规则
SECURITY LABEL FOR anon ON COLUMN player.name IS NULL;
移除所有表的脱敏规则
SELECT anon.remove_masks_for_all_columns();
注意:分区表需要在分区上独立进行设置。
4.脱敏函数
anon提供了8种脱敏策略,可以对不同的列分别使用不同的脱敏策略:
Destruction(重构):替换为单个静态值
SECURITY LABEL FOR anon ON COLUMN users.address IS 'MASKED WITH VALUE ''CONFIDENTIAL'' ';
Adding Noise(噪音化):它是对日期和数值添加一个方差,有两种函数形式:
Randomization(随机化) 基本随机值
边界随机值
基于数组的随机值
Faking(伪造)/Advanced Faking:伪造的想法是用随机但合理的值取代敏感数据。 为了使用伪造函数,需要先调用init函数
SELECT anon.init();
加载数据后,可以访问以下伪造函数:
伪造请查看: PostgreSQL Faker
Pseudonymization(笔名化):类似于伪造,主要区别在于笔名化是确定性的,相同的seed和salt返回相同的值。
为了使用笔名化函数,需要先调用init函数
SELECT anon.init();
加载数据后,可以访问以下函数:
第二个参数salt是可选的,salt可以增加复杂性,避免字典和暴力攻击。seed可以是与主题相关的任何信息。例如,我们可以始终使用给定的登录名作为seed为给定的人生成相同的虚假电子邮件地址。
SECURITY LABEL FOR anon ON COLUMN users.emailaddress IS 'MASKED WITH FUNCTION anon.pseudo_email(users.login)';
Generic Hashing(哈希)
Partial scrambling(部分遗漏) 例如掩盖信用卡中间号码或邮箱地址
Generalization(泛化):泛化是将原始值替换为包含该值的范围。例如,与其说“保罗42岁”,不如说“保罗在40到50岁之间”。
其中value是将要泛化的数据,step是每个范围的步长。
除了上面的八种策略,我们还可以自定义脱敏函数,例如在模式bar内定义脱敏函数foo():
SECURITY LABEL FOR anon ON SCHEMA bar IS 'TRUSTED'; SECURITY LABEL FOR anon ON COLUMN player.score IS 'MASKED WITH FUNCTION bar.foo()';
下面的示例,对JSON类型进行自定义脱敏处理。
SECURITY LABEL FOR anon ON SCHEMA custom_masks IS 'TRUSTED';
CREATE FUNCTION custom_masks.remove_last_name(j JSONB)
RETURNS JSONB
VOLATILE
LANGUAGE SQL
AS $func$
SELECT
json_build_object(
'employees' ,
array_agg(
jsonb_set(e ,'{lastName}', to_jsonb(anon.fake_last_name()))
)
)::JSONB
FROM jsonb_array_elements( j->'employees') e
$func$;
5.静态脱敏
静态脱敏会损坏原始数据,使用时需要额外小心。
定义完脱敏规则后使用下面的函数替换真实数据。
select anon.anonymize_database()
也可使用下面的函数进行局部处理:
SELECT anon.anonymize_table('customer');
SELECT anon.anonymize_column('customer','zipcode');
6.动态脱敏
我们可以将脱敏数据放到一个脱敏用户下,其他用户仍然可以访问原始数据。
示例:
CREATE TABLE people (id TEXT, firstname TEXT, lastname TEXT, phone TEXT);
INSERT INTO people VALUES ('T1','Sarah', 'Conor','0609110911');
步骤一:激活动态脱敏引擎
CREATE EXTENSION IF NOT EXISTS anon CASCADE; SELECT anon.start_dynamic_masking();
步骤二:定义脱敏用户
CREATE ROLE skynet LOGIN; SECURITY LABEL FOR anon ON ROLE skynet IS 'MASKED';
步骤三:定义脱敏规则
SECURITY LABEL FOR anon ON COLUMN people.lastname IS 'MASKED WITH FUNCTION anon.random_string(4)'; SECURITY LABEL FOR anon ON COLUMN people.phone IS 'MASKED WITH FUNCTION anon.partial(phone,2,$$******$$,2)';
步骤四:使用脱敏用户查询
\c - skynet foo=> select * from people; id | firstname | lastname | phone ----+-----------+----------+------------ T1 | Sarah | ROKS | 06******11 (1 row)
更改脱敏列的数据类型:当动态脱敏引擎被激活时,如果列上有脱敏规则,则不允许更改列的数据类型。
修改脱敏列需要临时停止脱敏引擎:
BEGIN; SELECT anon.stop_dynamic_masking(); ALTER TABLE people ALTER COLUMN phone TYPE VARCHAR(255); SELECT anon.start_dynamic_masking(); COMMIT;
删除脱敏表:动态脱敏引擎将在脱敏表上构建脱敏视图,直接删除脱敏表会提示这样的错误:
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;
7.脱敏数据导出
如果需要使用脱敏用户导出数据,需要使用工具pg_dump_anon,工具安装参考:
https://postgresql-anonymizer.readthedocs.io/en/latest/anonymous_dumps/#with-go
8.抽样脱敏
如果是测试目的,仅提取和脱敏10%的数据,示例如下:
CREATE TABLE http_logs ( id integer NOT NULL, date_opened DATE, ip_address INET, url TEXT ); SECURITY LABEL FOR anon ON COLUMN http_logs.ip_address IS 'MASKED WITH VALUE NULL'; SECURITY LABEL FOR anon ON TABLE http_logs IS 'TABLESAMPLE BERNOULLI(10)';
也可以在数据库级别定义抽样:
SECURITY LABEL FOR anon ON DATABASE foo IS 'TABLESAMPLE SYSTEM(33)';
9.术语定义
https://postgresql-anonymizer.readthedocs.io/en/latest/concepts/
10.相关链接
官方链接
https://gitlab.com/dalibo/postgresql_anonymizer/
官方文档
https://postgresql-anonymizer.readthedocs.io/en/stable/
目前该功能还处于测试阶段,作者建议2.0版本才可用于生产,敬请关注。
保持联系
本人组建了一个技术交流群:PG乐知乐享交流群。欢迎关注文章的小伙伴随缘加入,进群请加本人微信skypkmoon并备注PG乐知乐享。
