MySQL 中的动态数据脱敏:无需更改应用程序即可保护敏感数据

生产数据对于日常运营至关重要,包括支持、故障排除、分析和开发。但是,当这些数据包含敏感字段,例如社会安全号码、电子邮件地址、电话号码或其他标识符时,广泛的读取权限很快就会导致不必要的风险暴露。

同样重要的是,许多组织在监管和合同要求下运营 ,这些要求对敏感数据的访问进行严格控制------通常包括数据脱敏, 作为履行隐私和安全义务的一部分(例如,在符合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>'@'%';

  1. 设置:模式 + 表 + 示例数据

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;

  1. 将该策略应用于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/

引用官方英文文档地址:

https://blogs.oracle.com/mysql/dynamic-data-masking-in-mysql-protect-sensitive-data-without-app-changes

相关推荐
小白说大模型3 小时前
AI驱动的个性化学习路径:知识图谱与知识点关联的存储与推理
大数据·人工智能·学习·mysql·机器学习·prompt·知识图谱
这个DBA有点耶3 小时前
多模数据库深度解读:从“多库拼装”到“一库多能”的架构演进
数据库·mysql·dba
aaajj3 小时前
关于MODIFY_PHONE_STATE权限
android
程序员夏洛3 小时前
MySQL 默认的事务隔离级别是什么?为什么选择这个级别?
数据库·mysql
卓怡学长4 小时前
w180springboot基于Java的悠扬乐器管理
java·spring boot·mysql·spring·maven·intellij-idea
古法安卓4 小时前
Android-高版本 LMKD 源码解析:基于 PSI 的内存压力监控与查杀全流程
android·java·android studio
古法安卓4 小时前
Android-PSI 详解:libpsi 源码解析——116 行代码架起 lmkd 与内核之间的桥
android·java·android studio
( •̀∀•́ )9204 小时前
MySQL 自动备份与恢复方案
数据库·mysql·oracle
这个DBA有点耶4 小时前
大事务的“事前预防”:监控、拦截、Kill,四层防线一次讲透
数据库·mysql·代码规范