temper / laravel-dbmask
Requires
- php: >=7.4
- doctrine/dbal: ^2.0|^3.0
- laravel/framework: ^6.20.26|^7.30.4|^8.22.1|^9.0|^10.0
Requires (Dev)
- orchestra/testbench: ^6.12
README
一个用于白名单动态数据库掩码的 Laravel 包。
你有没有想过
"如何与公司内的开发人员和分析师共享我们的数据库,同时遵守GDPR等隐私法规?
这个包可能就是你要找的!
在一定程度上,数据库种子脚本可能会有所帮助。但有时候,对公司内许多角色来说,访问真实数据或数据库的最新副本可能是至关重要的,例如快速收集真实世界的统计数据或查找错误。
此包可以从MySQL源连接创建一个只读实时过滤器(通过视图掩码)和/或一个读写过滤副本(物化表)。
为了保持“默认隐私”,它通过白名单而不是黑名单来处理数据。您明确指定要逐字复制的列、要匿名化的列以及要完全排除的列(和行)。
免责声明:此包包含代码,设置不正确时可能会从您的数据库中删除重要数据。在使用之前,请务必自行验证和审核代码,并创建备份以确保生产环境的安全。
欢迎贡献。
重要限制
以下MySQL功能可能会引起问题
- 虚拟或存储生成列在创建掩码视图时可能会泄露数据。如果这是一个问题,请使用物化选项。
- 触发器 & UDFs当前不会从源模式传输到目标。
- 视图将出现在目标上,但应依赖于底层表的掩码配置。
安装
添加仓库
{ "repositories": [{ "type": "vcs", "url": "https://github.com/TemperWorks/laravel-dbmask" }], "require": { "temperworks/laravel-dbmask": "dev-master", } }
使用Composer更新
composer update temperworks/laravel-dbmask
发布示例配置
php artisan vendor:publish --tag=dbmask
测试
此包需要真实MySQL数据库进行测试。请确保您在测试时使用不包含任何重要数据的数据库。
将 phpunit.xml.dist
复制到 phpunit.xml
,并更改DB连接变量。
之后,只需运行 ./vendor/bin/phpunit
。
用法
关于此包
以一个生产数据库为例,其中只有一个用户表
create table users ( id int(10) unsigned auto_increment primary key, email varchar(255) not null, first_name varchar(255) null, last_name varchar(255) null, password varchar(60) null, social_security_num varchar(20) null, birth_date date null, favorite_drink varchar(20) null )
数据科学家可能需要此生产数据库的副本,并且他们可能对按年龄组计算的favorite_drink
等聚合数据感兴趣。问题是,通过授予对生产数据库的访问权限,您也将授予他们对包含social_security_number
和(散列的)password
字符串的数据库列的访问权限。
这是不可取的,因为它增加了个人数据泄露的风险。
更好的解决方案是提供一个(或实时过滤器)掩码敏感字段,例如通过将值设置为null
或用假数据替换值。
实时掩码视图 & 物化掩码表
配置
dbmask.php
配置指定以下配置键
键 | 类型 | 描述 |
---|---|---|
表格 |
[] |
包含表格及其列的数组。省略的表格将不会包含在加密数据库中。 |
表格过滤器 |
[] |
要筛选的行 |
加密 |
数组 |
包含两个数据库连接名称:一个 source 和一个 target |
实体化 |
数组 |
包含两个数据库连接名称:一个 source 和一个 target |
auto_include_fks |
布尔值 |
是否默认包含所有外键 |
auto_include_pks |
布尔值 |
是否默认包含所有主键 |
auto_include_timestamps |
bool 或 [] |
是否默认包含时间戳,可选地包含列名数组 |
连接 |
字符串 |
使用哪个数据库连接,如果不是默认连接 |
mask_datasets |
[] |
可用于随机加密的数据集 |
tables
数组包含所有列转换
'users' => [ // id will be included by default if auto_include_pks is true 'id', // MySQL functions can be used to mask data 'email' => "concat(md5('id'),'@example.com')", // A non-associative array value will be included unmasked 'birth_date', // Sets the column to null 'first_name' => 'null' // Picks a stable, semi-random English last name from a dataset, // using the last_name column as a hash seed 'last_name' => DBMask::random('last_name', 'english_last_names'), // Uses the application key to replace the value with a new generated password hash // In this case, all users end up with their password set to the bcrypt hashed value of `secret`. 'password' => DBMask::bcrypt('secret'), ]
运行转换
在发布和编辑配置后,在 MySQL 中创建所需的模式,编辑配置并运行
php artisan db:mask
and/or
php artisan db:materialize
筛选行
table_filters
数组可以包含排除特定行的规则
// exclude records of people born after 2000 'users' => 'birth_date < 2000-01-01', // include the whole table as a valid view, but truncate to zero records 'audit_log' => 'false'
伪造数据提供者
可以定义自定义随机化集,例如使用 Faker 包
$faker = Faker\Factory::create('nl_NL'); 'tables' => [ 'users' => [ 'social_security_num' => DBMask::random('social_security_num', 'ssn') ] ] 'mask_datasets' => [ // generates a set of form-validatable social security numbers 'ssn' => DBMask::generate(100, function() use ($faker) { return $faker->unique()->idNumber; }), ]
从源到目标传输视图
如果源模式上存在视图,这些视图也可以传输到加密/实体化目标。
例如,如果源有一个 users_view
,它将首名和姓氏连接到全名,并公开 SSN,那么定义表的匿名化配置。包括视图名称,不需要任何列配置--它毕竟没有实际的列,它只是指向加密的用户表。
在启用实时加密匿名化选项时,这也适用。在这种情况下,源视图将传输到目标,在那里它叠加在加密视图之上。
'tables' => [ 'users' => [ 'first_name' => "'Jane'" 'last_name' => "'Doe'" 'social_security_num' => DBMask::random('social_security_num', 'ssn') ], 'users_view' => [], ]
尽管可以使用伪造的种子数据,但仍有一些限制
- 当集合的大小小于表记录数时,无法保证唯一性
- 非常大的数据集在视图中会负面影响性能。