Azure SQL 数据库 中基于正则表达式的动态数据掩码(预览版)

适用于:Azure SQL 数据库

本文将向您展示如何使用REGEXP_REPLACE掩蔽函数在 Azure SQL 数据库 中定义模式驱动的动态数据掩蔽规则。 基于正则表达式的掩码支持对可变长度的字符串数据进行掩码处理,并保留内置掩码无法实现的特定片段。

Important

基于正则表达式的动态数据掩码现已在 Azure SQL 数据库 中提供公开预览。 预览功能以“现状”形式提供,不包含在服务水平协议和有限保修之外。 仅在非生产环境中使用此功能。 有关详细信息,请参阅适用于 Azure 预览版的补充使用条款

概述

Azure SQL 数据库中的动态数据掩蔽(DDM)在查询结果中动态隐藏敏感数据,在数据发送到应用程序之前。 此功能减少了敏感信息的意外暴露,并消除了在应用代码中添加掩蔽逻辑的需求。

DDM 允许数据库管理员和开发者在数据库中中心定义敏感列的遮蔽规则。 非特权用户看到的数值被混淆,而实际数据则保持在存储中。

内置遮罩功能的局限性

Azure SQL 数据库 提供了多个内置的遮蔽函数:default()email()random()partial()datetime()和 。 这些函数中的大多数都采用了固定模式,既无法自定义,也无法灵活处理可变长度的数据。

例如,对于像 email() 这样的电子邮件地址,内置的 aXXX@xxxx.com 掩码始终会生成类似 alice.johnson@example.com 的格式。 该掩码只显示用户名的首字母,并遮蔽域名。 当你需要为业务流程保留域名时,固定输出并不实用。

什么是基于正则表达式的掩码处理?

基于正则表达式的 DDM 将 REGEXP_REPLACE 引入为一种新的掩码函数。 通过使用此功能,你可以为字符串数据(如电话号码、电子邮件地址和识别号)创建自定义的模式驱动掩码。

正则表达式允许你精确定义哪些子字符串需要揭示或遮蔽。 内置函数无法表达这种可变长度的模式。 当你处理电子邮件、电话号码或标识符等结构化数据模式时,这一功能非常有用。 在这种情况下,你通常需要保留特定的可见片段,同时对敏感部分进行掩盖,而内置遮罩对你的业务流程来说过于僵硬。

注释

  • 权限模式保持不变。 此增强不引入新的权限。
  • 你只能在 T-SQL 中配置正则表达式掩码。 Azure门户在本版本中不支持正则表达式掩码配置。

Syntax

在创建表时应用正则表达式掩码:

column_name <data_type> MASKED WITH (FUNCTION = 'REGEXP_REPLACE("<pattern_expression>", "<string_replacement>")')

向现有列添加正则表达式掩码:

ALTER TABLE <schema_name>.<table_name>
ALTER COLUMN <column_name>
ADD MASKED WITH (FUNCTION = 'REGEXP_REPLACE("<pattern_expression>", "<string_replacement>")');

Arguments

pattern_expression

正则表达式用来对列值进行评估。 最大长度为8,000字节。

string_replacement

应用于 pattern_expression 的每个匹配项的替换字符串。

注释

当你用作 REGEXP_REPLACE 掩蔽函数时,只有 pattern_expressionstring_replacement 参数起作用。 原生的 T-SQL REGEXP_REPLACE 函数也支持 startoccurnceflags 参数,但用作掩蔽函数时无法覆盖它们。 固定值分别为 start = 1、occurrence = 0(替换所有匹配项),以及 flags = 'c'(区分大小写)。

REGEXP_REPLACE 掩码函数支持数据类型为 charncharvarcharnvarchar 的列,以及大小不超过 2 MB 的 LOB 类型(varchar(max)nvarchar(max))。

教程:配置基于正则表达式的动态数据掩蔽

以下教程将教你如何创建正则表达式掩码、插入样本数据,以及验证不同用户的遮蔽输出与未遮蔽输出。

步骤 1:创建包含正则表达式掩码的表

以下语句创建了一个 CustomerDetails 表,其中包含两个经过正则表达式掩码处理的列:

  • 电话号码掩码:保留国家/地区代码(例如 +1+44+91),并将其余数字替换为xxxx。 这样可以保留国家代码作为上下文。
  • 电子邮件掩码:将用户名部分(之前 @)替换为 ***** ,同时保留域名。 例如,alice.johnson@example.com 将变为 *****@example.com
-- Drop the CustomerDetails table if it exists
DROP TABLE IF EXISTS Data.CustomerDetails;

CREATE TABLE Data.CustomerDetails (
    ID INT IDENTITY(1,1) PRIMARY KEY,
    Name varchar(30),
    Phone_Number varchar(30)
        MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
            "(\+\d{1,3})(?:[ -.]?\d){7,14}",
            "(\1)-xxxx")'),
    Email varchar(255)
        MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
            "([a-zA-Z0-9._%+-]+)(@+)([a-zA-Z0-9.-]+)(\.)(\w)",
            "*****\2\3\4\5")')
);

步骤2:插入样本数据

INSERT INTO Data.CustomerDetails (Name, Phone_Number, Email) VALUES
('Alice Johnson', '+1 202-555-0123', 'alice.johnson@example.com'),
('Bob Smith', '+1 415-555-0198', 'bob.smith@contoso.com'),
('Oliver Bennett', '+44 7700 900123', 'oliver.bennett@example.co.uk'),
('Amelia Thompson', '+44 7700 900456', 'amelia.thompson@example.co.uk'),
('Rajeev Mehra', '+91 90000 12345', 'rajeev.mehra@adventure-works.net'),
('John Miller', '+91 98888 45678', 'jon.miller@contoso.net'),
('Lukas Mueller', '+49 151 23456789', 'lukas.mueller@example.de'),
('Daniel Tan', '+65 8123 4567', 'daniel.tan@example.sg'),
('Hiroshi Tanaka', '+81 90 1234 5678', 'hiroshi.tanaka@example.jp');

步骤3:作为特权用户查询

拥有 sysadmindb_owner或明确 UNMASK 权限的用户始终能看到实际数据。

-- As sysadmin or db_owner, you see the real data
SELECT * FROM Data.CustomerDetails;

预期结果:所有电话号码和电子邮件均完整显示(例如, +1 202-555-0123alice.johnson@example.com)。

步骤4:作为非特权用户查询

创建一个测试用户,无需 UNMASK 授权并查询该表。

-- Create a test user without UNMASK permission
CREATE USER SupportEngineer WITHOUT LOGIN;

-- Grant SELECT permission on CustomerDetails to SupportEngineer
GRANT SELECT ON Data.CustomerDetails TO SupportEngineer;

-- Query the table as the nonprivileged user
EXECUTE AS USER = 'SupportEngineer';
SELECT * FROM Data.CustomerDetails;
REVERT;

预期结果:电话号码仅显示国家代码(例如, (+1)-xxxx),电子邮件隐藏用户名(例如, *****@example.com)。

步骤 5:授予 UNMASK 权限并重新查询

授予 UNMASK后,同一用户现在看到完整的未掩码值。 这展示了DDM基于许可的访问控制的工作原理。

-- Grant UNMASK permission to the test user
GRANT UNMASK ON Data.CustomerDetails TO SupportEngineer;

-- Re-run the query as the same user - now sees unmasked data
EXECUTE AS USER = 'SupportEngineer';
SELECT * FROM Data.CustomerDetails;
REVERT;

向现有列添加正则表达式掩码

要向现有列添加正则表达式掩码,请使用 ALTER TABLE

ALTER TABLE Data.CustomerDetails
ALTER COLUMN Phone_Number
ADD MASKED WITH (FUNCTION = 'REGEXP_REPLACE(
    "(\+\d{1,3})(?:[ -.]?\d){7,14}",
    "(\1)-xxxx")');

通过元数据验证掩蔽策略

使用 sys.masked_columns 系统视图检查已配置的掩码。 此视图包含 REGEXP_REPLACE 遮罩定义。

SELECT c.name,
       tbl.name AS table_name,
       c.is_masked,
       c.masking_function
FROM sys.masked_columns AS c
JOIN sys.tables AS tbl
    ON c.[object_id] = tbl.[object_id]
WHERE is_masked = 1;

Considerations

  • 正则表达式掩码依赖于模式。 在应用到生产列之前,先验证代表性数据上的正则表达式模式。
  • 未匹配的数值保持不被掩盖。 未匹配模式会将原始数据返回给非特权用户,这可能会暴露敏感信息。
  • 用具代表性的数据彻底测试。 涵盖诸如空值、空字符串和非典型格式等正则表达式可能捕捉不到的边缘情况。
  • 预览期间请在非生产环境中使用。 在将此功能用于生产工作负载之前,请务必进行充分验证。