
生产数据对于日常运营至关重要,包括支持、故障排除、分析和开发。但是,当这些数据包含敏感字段,例如社会安全号码、电子邮件地址、电话号码或其他标识符时,广泛的读取权限很快就会导致不必要的风险暴露。
同样重要的是,许多组织在监管和合同要求下运营 ,这些要求对敏感数据的访问进行严格控制------通常包括数据脱敏, 作为履行隐私和安全义务的一部分(例如,在符合GDPR、HIPAA、PCI DSS、SOX 和类似内部安全标准的项目中)。
动态数据脱敏 (DDM) 现已在MySQL 9.7 LTS中正式发布,并可在MySQL企业版和OCI MySQL HeatWave中使用。借助 DDM,您可以将脱敏策略直接附加到基表列,以便MySQL在查询时根据执行用户或活动角色返回原始值或脱敏值 ,而无需更改应用程序,也无需维护单独的脱敏数据副本。
为什么需要动态数据 脱敏 ?
在MySQL中,数据脱敏通常是通过SQL函数和/或用户自定义函数 (UDF) 结合视图来实现的。虽然这种方法有效,但通常需要:
创建和维护其他数据库对象(视图)
确保用户无法通过直接查询基表来绕过脱敏。
随着库表模式的演变,持续的运维工作也在进行中。
动态数据脱敏通过在基表的列级别强制执行脱敏来简化该模型,帮助组织实施最小权限访问并减少敏感数据泄露------这是安全态势和合规性计划的重要组成部分。(与以往一样,实际合规性取决于您更广泛的控制措施、流程和配置。)
工作原理:
脱敏策略和gatekeeper 功能
脱敏 策略 定义为一个 CASE 表达式,其中包含:
gatekeeper功能:
CURRENT_USER_IN('...') 基于用户的匹配
CURRENT_ROLE_IN('...') 用于基于角色的匹配(活跃角色)
一个用于在应用脱敏时转换值的脱敏表达式(对于SSN ,我们将使用 MySQL 的内置函数 mask_ssn())。
当查询引用一个被屏蔽的列时,MySQL 会评估网关并返回以下结果之一:
原始列值(未屏蔽),或 脱敏值(由策略计算得出)
由于强制执行发生在MySQL服务器内部,因此该行为在应用程序和查询路径中是一致的。
端到端示例(复制/粘贴):屏蔽除授权用户/角色以外的所有人的社会安全号码
以下是一个最小可运行示例。它展示了基于用户和基于角色的访问控制;您可以根据您的运营模式选择使用其中一种(或两种都用)。
在创建脱敏策略之前,请运行
Connect as Admin
SOURCE install_component_object_policy.sql安装 Enterprise object_policy 组件;
创建、显示或删除脱敏策略的用户需要MANAGE_DATA_MASKING_POLICY权限。
-- Run once per server as an administrative user.
-- Requires permission to create tables in the mysql schema
-- and execute INSTALL COMPONENT.
SOURCE install_component_object_policy.sql;
-- Grant this to the user who will create, show, or drop masking policies.
GRANT MANAGE_DATA_MASKING_POLICY ON *.* TO '<mask_admin>'@'%';
- 设置:模式 + 表 + 示例数据
CREATE SCHEMA IF NOT EXISTS protected;
USE protected;
DROP TABLE IF EXISTS user_profiles;
CREATE TABLE user_profiles (
id INT PRIMARY KEY,
first_name VARCHAR(32),
last_name VARCHAR(32),
ssn VARCHAR(16),
zip_code VARCHAR(10)
);
INSERT INTO user_profiles VALUES
(1,'James','Smith','900-01-0001','10001'),
(2,'Mary','Johnson','900-01-0002','90210'),
(3,'Robert','Williams','900-01-0003','60601'),
(4,'Patricia','Brown','900-01-0004','30301');
1)设置身份:用户和角色
CREATE USER IF NOT EXISTS 'seeall'@'%' IDENTIFIED BY 'Welcome_123!';
CREATE USER IF NOT EXISTS 'noseeall'@'%' IDENTIFIED BY 'Welcome_123!';
GRANT SELECT ON protected.user_profiles TO 'seeall'@'%';
GRANT SELECT ON protected.user_profiles TO 'noseeall'@'%';
CREATE ROLE IF NOT EXISTS 'pii_read'@'%';
GRANT SELECT ON protected.user_profiles TO 'pii_read'@'%';
GRANT 'pii_read'@'%' TO 'seeall'@'%';
2)创建脱敏策略(基于用户)
CREATE MASKING POLICY mask_ssn_policy(ssn_col)
CASE WHEN CURRENT_USER_IN('seeall')
THEN ssn_col
ELSE mask_ssn(ssn_col)
END;
- 将该策略应用于SSN 列
ALTER TABLE protected.user_profiles
ALTER COLUMN ssn
SET MASKING POLICY mask_ssn_policy;
4)验证行为
SELECT id, first_name, last_name, ssn, zip_code
FROM protected.user_profiles
ORDER BY id;
由于 noseeall,SSN 已被屏蔽(例如, XXX-XX-0001)
当 seeall (和/或拥有相应的活跃角色时)SSN 是可见的
用户"noseeall"------数据已屏蔽
mysql> select * from user_profiles;
+----+------------+-----------+-------------+----------+
| id | first_name | last_name | ssn | zip_code |
+----+------------+-----------+-------------+----------+
| 1 | James | Smith | XXX-XX-0001 | 10001 |
| 2 | Mary | Johnson | XXX-XX-0002 | 90210 |
| 3 | Robert | Williams | XXX-XX-0003 | 60601 |
| 4 | Patricia | Brown | XXX-XX-0004 | 30301 |
| 5 | John | Jones | XXX-XX-0005 | 75201 |
| 6 | Jennifer | Garcia | XXX-XX-0006 | 85001 |
| 7 | Michael | Miller | XXX-XX-0007 | 33101 |
| 8 | Linda | Davis | XXX-XX-0008 | 19101 |
| 9 | William | Rodriguez | XXX-XX-0009 | 94101 |
| 10 | Elizabeth | Martinez | XXX-XX-0010 | 98101 |
+----+------------+-----------+-------------+----------+
10 rows in set (0.000 sec)
用户"查看全部"数据不会被屏蔽。
mysql> select * from user_profiles;
+----+------------+-----------+-------------+----------+
| id | first_name | last_name | ssn | zip_code |
+----+------------+-----------+-------------+----------+
| 1 | James | Smith | 900-01-0001 | 10001 |
| 2 | Mary | Johnson | 900-01-0002 | 90210 |
| 3 | Robert | Williams | 900-01-0003 | 60601 |
| 4 | Patricia | Brown | 900-01-0004 | 30301 |
| 5 | John | Jones | 900-01-0005 | 75201 |
| 6 | Jennifer | Garcia | 900-01-0006 | 85001 |
| 7 | Michael | Miller | 900-01-0007 | 33101 |
| 8 | Linda | Davis | 900-01-0008 | 19101 |
| 9 | William | Rodriguez | 900-01-0009 | 94101 |
| 10 | Elizabeth | Martinez | 900-01-0010 | 98101 |
+----+------------+-----------+-------------+----------+
10 rows in set (0.000 sec)
为什么服务器端强制执行很重要
代理层脱敏虽然有用,但它通常位于数据库前端 。如果用户直接连接到 MySQL(或以其他方式绕过代理),敏感数据仍然可能泄露。
动态数据脱敏在MySQL内部强制执行 ,即在解析列值以执行查询时执行。这样,无论查询是通过交互式 SQL、应用程序还是数据库对象(具有预期的调用者/定义者语义)发出,都能确保脱敏的一致性。
适用于分析和人工智能工作负载
由于数据脱敏是在查询时应用 并由服务器强制执行的,因此动态数据脱敏还可以帮助减少下游工作流程(例如 分析提取、报告和 AI 辅助查询/代理)中敏感数据的暴露,而无需每个使用工具都实现和维护自己的脱敏逻辑。团队可以使用相同的数据集和管道,而MySQL会返回与执行身份和活动角色相适应的值。
了解更多/立即尝试
MySQL 9.7 发行说明: https://dev.mysql.com/doc/relnotes/mysql/9.7/en/
试用 OCI MySQL HeatWave(免费试用): https://www.oracle.com/heatwave/free/

引用官方英文文档地址: