Azure Cosmos DB for NoSQL 中的动态数据掩码(预览版)

本文介绍如何在 Azure Cosmos DB 帐户上配置动态数据掩码。

重要

动态数据掩码目前处于公共预览阶段。 此功能没有提供服务级别协议。 有关详细信息,请参阅适用于 Azure 预览版的补充使用条款

概述

动态数据掩码(DDM)是 Azure Cosmos DB 中基于策略的服务器端安全功能,可帮助保护敏感数据免受未经授权的访问。 DDM 动态掩码非特权用户的数据,确保在向应用程序呈现之前实时编辑敏感信息,而原始数据在数据库中保持不变。

DDM 通过限制敏感数据(如个人数据和受保护的健康信息)的暴露,帮助组织满足安全、合规性和法规要求。

动态数据掩码如何帮助保护数据

  • 限制敏感数据公开: 只有特权用户才能查看未屏蔽的数据;其他人会看到屏蔽或编辑的值。
  • 基于策略的强制: 根据用户角色和特权应用掩码。
  • 合规性支持: 帮助满足数据隐私和保护的法规要求。
  • 对存储的数据没有影响: 在查询时发生掩码;基础数据保持不变。

支持的掩码策略

类型 Description Example
违约 字符串 值将替换为固定掩码 "XXXX"

数字型数值 会被替换为默认值 0

布尔值始终设置为 false
原文:雷德蒙德
蒙面:XXXX

原始: 95
蒙面:0

原始: 真
蒙面:false
自定义字符串 使用 MaskSubstring(Start、Length) 基于定义的起始索引和长度屏蔽字符串的一部分 MaskSubstring(3,5)

原文:华盛顿
蒙面:WasXXXXXon
Email 只有用户名的第一个字母和域结尾(如.com)保持可见。 所有其他字符都替换为 X 字符。 源语言: alpha@microsoft.com
蒙面:aXXXX@XXXXXXXXX.com

如何在 Azure Cosmos DB 上设置动态数据掩码

注释

动态数据掩码(DDM)需要Microsoft Entra ID 托管标识,不支持帐户密钥。

启用动态数据掩码

可以通过位于“设置”导航窗格下的“功能”选项卡为帐户配置动态数据掩码。

注释

在帐户上启用动态数据掩码后,无法将其关闭。 启用此功能可能需要长达 15 分钟才能在 Azure Cosmos DB 中准备就绪。

使用权限创建角色定义

数据掩码利用 Azure Cosmos DB 数据平面 [基于角色的访问控制] (how-to-connect-role-based-access-control.md)。 若要实现数据掩码,必须创建角色定义并分配用于取消掩码的数据作权限,如示例中所示。 内置数据参与者角色包括取消掩码权限,而默认情况下,数据读取者角色没有 unmask 权限。

  1. 使用 New-Guid PowerShell 中的命令生成新的 GUID,并将生成的 GUID 粘贴到 JSON 正文(之后 /sqlRoleDefinitions/<NEW_GUID_HERE>)。 创建包含以下内容的 JSON 文件 unmasked_role_definition.json

    {
        "Id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/Your-resource-group-name/providers/Microsoft.DocumentDB/databaseAccounts/Your-CosmosDB-account-name/sqlRoleDefinitions/00000000-0000-0000-0000-000000009999",
        "RoleName": "unmaskroledefinition1",
        "Type": "CustomRole",
        "AssignableScopes": [
            "/"
        ],
        "Permissions": [
            {
            "DataActions": [
                "Microsoft.DocumentDB/databaseAccounts/readMetadata",
                "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read",
                "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/unmask",
                "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery"
            ],
            "NotDataActions": []
            }
        ]
    }
    
  2. 运行以下命令以创建角色定义:

    az cosmosdb sql role definition create `
      --account-name "Your-CosmosDB-account-name" `
      --resource-group "Your-resource-group-name" `
      --body "@unmasked_role_definition.json"
    

将用户分配到角色

定义角色后,下一步是将用户分配到每个角色。 根据这些角色定义,用户分为两个组:高特权用户和低特权用户。

高特权用户

授予拥有高级权限的用户在容器级别的 unmask 权限。

az cosmosdb sql role assignment create `
--account-name "Your-CosmosDB-account-name" `
--resource-group "Your-resource-group-name" `
--scope "/" `
--principal-id "zzzzz-yyyy01-xxxx02-www3w3" `
--role-definition-id "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/Your-resource-group-name/providers/Microsoft.DocumentDB/databaseAccounts/Your-CosmosDB-account-name/sqlRoleDefinitions/00000000-0000-0000-0000-000000009999"

低特权用户

低特权用户具有最少的权限,例如内置的 Cosmos DB 数据读取者角色。

az cosmosdb sql role assignment create `
--account-name "Your-CosmosDB-account-name" `
--resource-group "Your-resource-group-name" `
--scope "/" `
--principal-id "zzzzz-yyyy01-xxxx02-www3w3" `
--role-definition-id "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/Your-resource-group-name/providers/Microsoft.DocumentDB/databaseAccounts/Your-CosmosDB-account-name/sqlRoleDefinitions/00000000-0000-0000-0000-000000000001"

(可选)列出角色定义

运行以下命令以显示和验证角色定义。

az cosmosdb sql role definition list `
  --account-name "Your-CosmosDB-account-name" `
  --resource-group "Your-resource-group-name"

应用数据掩码策略

注释

仅当启用了动态数据掩码功能时,才会显示掩码策略部分。

在 Azure 门户中,转到 Azure Cosmos DB 帐户,选择 “容器”,然后在 “设置”下,在“ 屏蔽策略”下创建数据掩码策略。

注释

如果未指定掩码策略,则会自动应用默认策略。

Azure 门户中动态数据掩码策略的屏幕截图。

"dataMaskingPolicy": 
{
  "includedPaths": [
    {
      "path": "/" // Mask all fields
    },
    {
      "path": "/profile/contact/email", 
      "strategy": "Email" //Email strategy overrides the default mask
    },
    {
      "path": "/employment/history/[]/company",
      "strategy": "MaskSubstring", // MaskSubstring overrides the default mask
      "startPosition": 2,
      "length": 4
    }
  ],
  "excludedPaths": [
    {
      "path": "/projects/[]/projectId" //Exclude projectId from masking
    },
    {
      "path": "/id"
    },
    {
      "path": "/department"
    },
    {
      "path": "/employment/history/[]/duration" 
    },
    {
      "path": "/projects/[]/details/technologies"
    }
  ],
  "isPolicyEnabled": true
}

结果

{
    "id": "ab12345-678a-4b7a-8d94-987654321",
    "department": "Marketing",
    "profile": {
        "name": {
            "first": "XXXX",
            "last": "XXXX"
        },
        "contact": {
            "email": "uXXXX@XXXXXXX.com",
            "phone": "XXXX"
        },
        "address": {
            "street": "XXXX",
            "city": "XXXX",
            "zipcode": "XXXX"
        }
    },
    "employment": {
        "role": "XXXX",
        "startDate": "XXXX",
        "history": [
            {
                "company": "CoXXXXy2",
                "duration": "1 year",
                "position": "XXXX"
            }
        ]
    },
    "skills": [
        {
            "name": "XXXX",
            "proficiency": "XXXX"
        },
        {
            "name": "XXXX",
            "proficiency": "XXXX"
        }
    ],
    "projects": [
        {
            "projectId": "1a",
            "name": "XXXX",
            "details": {
                "description": "XXXX",
                "teamSize": 0,
                "durationMonths": 0,
                "technologies": [
                    "MS Word",
                    "MS Excel",
                    "Project Management"
                ]
            }
        },
        {
            "projectId": "2a",
            "name": "XXXX",
            "details": {
                "description": "XXXX",
                "teamSize": 0,
                "durationMonths": 0,
                "technologies": [
                    "Dot Net",
                    "MS Excel"
                ]
            }
        }
    ],
    "_rid": "E1234+Uyj18CAAAACCCCC==",
    "_self": "dbs/E8mBDw==/colls/E8mBD+Uyj18=/docs/E1234+Uyj18CAAAACCCCC==/",
    "_etag": "\"00001000-0000-0400-0000-98y1234z0000\"",
    "_attachments": "attachments/",
    "_ts": 1234567890
}

有效和无效的路径

有效路径

{ "path": "/CreditCard", "strategy": "MaskSubstring", "startPosition": 0, "length": 8 } // Masks first 8 characters using MaskSubstring(startPosition, length)
{ "path": "/profile/contact/phone", "strategy": "MaskSubstring", "startPosition": 4, "length": 6} // Masks characters for a nested field
{ "path": "/SSN", "strategy": "Default"} // Fully masked using default strategy
{ "path": "/PhoneNumber"} // Default masking applied
{ "path": "/Email", "strategy": "Email" } // Email masking strategy applied
{ "path": "/profile/contact/email", "strategy": "Email"} //Email masking strategy applied for a nested field
{ "path": "/Address/ZipCode" } // Masks the nested ZipCode field using the default masking method 
{ "path": "/Projects/[]/name" } // Masks the name field within an array using the default strategy
{ "path": "/projects/[]/details/[]/technologies"} // Masking the technologies field in nested array using default strategy

无效的路径

{ "path": "/projects/[]", "strategy": "Default"} // Path can't end with []
{ "path": "/projects/[1]/name", "strategy": "Default"} // Specific index in array isn't supported

动态数据掩码对容量规划的影响

动态数据掩码(DDM)通过在查询时应用掩码规则来帮助保护敏感数据。 虽然此功能对应用程序是透明的,但计算使用情况有特定的注意事项:

  • 包含屏蔽数据的查询: 应用掩码规则需要在返回结果之前对敏感字段进行额外的处理,这比不屏蔽的查询消耗 的请求单位(RU) 略有增加。

  • 其他方案: 对于不涉及屏蔽列的查询,动态数据掩码对计算使用情况没有影响。

局限和限制

  1. 动态数据掩码仅限于 Azure Cosmos DB 中的 NoSQL API。
  2. 在帐户级别启用数据掩码后,它将保持活动状态,并且无法关闭。
  3. 除非将掩码策略应用于容器,否则启用掩码本身不会增加成本。
  4. 在 MaskSubstring 策略中,只允许正开始位置。 不允许反向索引。
  5. 仅当策略中包含所有路径(/)时,才能使用排除路径。
  6. 不支持对特定数组索引屏蔽值。
  7. 如果 ID 或分区键已屏蔽,则数据资源管理器(门户)中的文档视图不起作用。
  8. 更改源功能(Latest 和 AllVersionsAndDeletes)不适用于权限较低的用户。
  9. 构造镜像、具体化视图和备份(定期或连续)对未屏蔽的数据进行作。
  10. 复杂的查询偶尔可能会公开未屏蔽的数据或启用敏感值的推理。 动态数据掩码旨在最大程度地减少未经授权的用户的数据泄露,而不是防止直接数据库访问或详尽查询。