你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Azure 服务总线高级层提供了通过 Azure 存储服务加密 (Azure SSE) 对静态数据进行加密的功能。 服务总线高级层使用 Azure 存储来存储数据。 所有保存在 Azure 存储中的数据都使用 Microsoft 管理的密钥进行加密。 如果你使用自己的密钥(也称为创建自己的密钥 (BYOK) 或客户管理的密钥),则仍使用 Microsoft 托管密钥对数据进行加密,但另外,会使用客户管理的密钥对 Microsoft 托管密钥进行加密。 使用此功能可以创建、轮换、禁用用于加密 Microsoft 托管密钥的客户管理的密钥,以及撤销对这些密钥的访问权限。 启用 BYOK 功能是在命名空间中执行的一次性设置过程。
对于用于服务端加密的客户管理密钥,需要注意一些事项。
- Azure 服务总线高级层支持此功能。 不能为标准层服务总线命名空间启用此功能。
- 只能为新的或空的命名空间启用加密。 如果命名空间包含任何队列或主题,则加密操作会失败。
你可以使用 Azure 密钥保管库(包括 Azure 密钥保管库托管硬件安全模块 (HSM))来管理密钥并审核密钥使用情况。 可以创建自己的密钥并将其存储在 Key Vault 中,或者使用 Azure Key Vault API 来生成密钥。 有关 Azure 密钥保管库的详细信息,请参阅什么是 Azure 密钥保管库?
如果只需要加密消息的部分属性,请考虑使用 NServiceBus 等库。
启用客户管理的密钥(Azure 门户)
若要在 Azure 门户中启用客户管理的密钥,请执行以下步骤:
- 访问你的服务总线高级命名空间。 
- 在你的服务总线命名空间的“设置”页上,选择“加密”。 
- 选择“客户管理的密钥加密(静态)”,如下图所示。  
注意
目前,无法通过门户配置 Azure Key Vault 托管 HSM。
设置包含密钥的密钥保管库
启用客户管理的密钥后,需要将客户管理的密钥关联到 Azure 服务总线命名空间。 服务总线仅支持 Azure Key Vault。 如果启用了上一部分所述的“使用客户管理的密钥进行加密”选项,则需要将密钥导入 Azure Key Vault。 此外,必须为密钥配置“软删除”和“不清除”。 可以使用 PowerShell 或 CLI 配置这些设置。
创建密钥保管库或密钥保管库托管 HSM
重要
为 Azure 服务总线使用客户管理的密钥需要为保管库配置两个必需的属性。 它们是:“软删除”和“不清除”。 在 Azure 门户中创建新的密钥保管库时,默认启用“软删除”属性,而“清除保护”是可选项,因此请确保在创建密钥保管库时选择它。 此外,如果需要针对现有的密钥保管库启用这些属性,必须使用 PowerShell 或 Azure CLI。
- 若要创建新的密钥保管库,请按照 Azure 密钥保管库的快速入门进行操作。 有关 Azure 密钥保管库的信息,请参阅《关于 Azure 密钥保管库》。 
- 若要在创建保管库时启用“软删除”和“清除保护”,请使用 az keyvault create 命令。 - az keyvault create --name contoso-SB-BYOK-keyvault --resource-group ContosoRG --location westus --enable-soft-delete true --enable-purge-protection true
- 若要向现有保管库(已启用“软删除”)添加“清除保护”,请使用 az keyvault update 命令。 - az keyvault update --name contoso-SB-BYOK-keyvault --resource-group ContosoRG --enable-purge-protection true
创建密钥
遵循以下步骤创建密钥:
- 若要创建新密钥,请从“设置” 下的“密钥” 菜单中选择“生成/导入” 。  
- 将“选项” 设置为“生成” 并提供密钥名称。  
- 现在,可以从下拉列表中选择要与服务总线命名空间关联的用于加密的密钥。  - 注意 - 最多可以添加三个密钥以保证冗余。 如果其中一个密钥已过期或无法访问,则可以使用其他密钥加密。 
- 填写密钥详细信息,然后单击“选择”。 这会允许使用你的密钥(客户管理的密钥)来加密 Microsoft 托管密钥。 - 重要 - 如果要将客户管理的密钥与异地灾难恢复一起使用,请查看本部分。 - 为了使用客户管理的密钥对 Microsoft 管理的密钥进行加密,已在指定的 Azure KeyVault 中为服务总线的托管标识设置了一个访问策略。 这可确保能够控制从 Azure 服务总线命名空间对 Azure KeyVault 的访问。 - 此行为会导致: - 如果已经为服务总线命名空间启用了异地灾难恢复,并且你想要启用客户管理的密钥,那么 - 断开配对
- 为密钥保管库设置针对主要和辅助命名空间的托管标识的访问策略。
- 在主要命名空间上设置加密。
- 将主要和辅助命名空间重新配对。
 
- 如果想要对已设置客户管理密钥的服务总线命名空间启用异地灾难恢复,请执行以下操作: - 为密钥保管库设置针对辅助命名空间的托管标识的访问策略。
- 将主要和辅助命名空间配对。
 
- 配对后,辅助命名空间使用为主命名空间配置的密钥保管库。 如果在异地灾难恢复配对之前,这两个命名空间的密钥保管库不同,则用户必须为与主命名空间关联的密钥保管库中的辅助命名空间的托管标识委托访问策略或 RBAC 角色。 
 
托管标识
有两种类型的托管标识可用于分配给服务总线命名空间。
- 系统分配的标识:可以直接在服务总线命名空间中启用托管标识。 在启用系统分配的托管标识时,系统会在 Microsoft Entra 中创建一个与该服务总线命名空间的生命周期相关联的标识。 因此,命名空间被删除时,Azure 会自动删除此标识。 按照设计,只有该 Azure 资源(命名空间)可使用此标识从 Microsoft Entra ID 请求令牌。
- “用户分配”:你也可以创建作为独立 Azure 资源的托管标识,这称为用户分配的标识。 可以创建用户分配的托管标识,并将其分配给一个或多个服务总线命名空间。 使用用户分配的托管标识时,标识与使用它的资源分开管理。 它们不与命名空间的生命周期相关联。 当你不再需要用户分配的身份时,可以显式删除它。
有关详细信息,请参阅什么是 Azure 资源的托管标识?。
使用系统分配的标识(模板)进行加密
本节介绍如何执行以下任务:
- 创建具有托管服务标识的高级服务总线命名空间。
- 创建密钥保管库并向服务标识授予对密钥保管库的访问权限。
- 使用密钥保管库信息(密钥/值)更新服务总线命名空间。
创建具有托管服务标识的高级服务总线命名空间
本部分介绍了如何使用 Azure 资源管理器模板和 PowerShell 创建具有托管服务标识的 Azure 服务总线命名空间。
- 创建 Azure 资源管理器模板,以创建具有托管服务标识的服务总线高级层命名空间。 将文件命名为:CreateServiceBusPremiumNamespace.json: - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "type":"string", "metadata":{ "description":"Name for the Namespace." } }, "location":{ "type":"string", "defaultValue":"[resourceGroup().location]", "metadata":{ "description":"Specifies the Azure location for all resources." } } }, "resources":[ { "type":"Microsoft.ServiceBus/namespaces", "apiVersion":"2018-01-01-preview", "name":"[parameters('namespaceName')]", "location":"[parameters('location')]", "identity":{ "type":"SystemAssigned" }, "sku":{ "name":"Premium", "tier":"Premium", "capacity":1 }, "properties":{ } } ], "outputs":{ "ServiceBusNamespaceId":{ "type":"string", "value":"[resourceId('Microsoft.ServiceBus/namespaces',parameters('namespaceName'))]" } } }
- 创建一个模板参数文件,名为:CreateServiceBusPremiumNamespaceParams.json。 - 注意 - 请替换以下值: - <ServiceBusNamespaceName>- 你的服务总线命名空间的名称
- <Location>- 你的服务总线命名空间的位置
 - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "value":"<ServiceBusNamespaceName>" }, "location":{ "value":"<Location>" } } }
- 运行以下 PowerShell 命令以部署用于创建高级服务总线命名空间的模板。 然后检索该服务总线命名空间的 ID 供稍后使用。 在运行该命令之前,请将 - {MyRG}替换为资源组的名称。- $outputs = New-AzResourceGroupDeployment -Name CreateServiceBusPremiumNamespace -ResourceGroupName {MyRG} -TemplateFile ./CreateServiceBusPremiumNamespace.json -TemplateParameterFile ./CreateServiceBusPremiumNamespaceParams.json $ServiceBusNamespaceId = $outputs.Outputs["serviceBusNamespaceId"].value
向服务总线命名空间标识授予对密钥保管库的访问权限
设置密钥保管库访问策略,使服务总线命名空间的托管标识可以访问密钥保管库中的密钥值。 使用在上一部分创建的服务总线命名空间的 ID。
$identity = (Get-AzureRmResource -ResourceId $ServiceBusNamespaceId -ExpandProperties).Identity
Set-AzureRmKeyVaultAccessPolicy -VaultName {keyVaultName} -ResourceGroupName {RGName} -ObjectId $identity.PrincipalId -PermissionsToKeys get,wrapKey,unwrapKey,list
使用密钥保管库中客户管理的密钥加密服务总线命名空间中的数据
到目前为止,你执行了以下步骤:
- 创建了具有托管标识的高级命名空间。
- 创建了密钥保管库,并向托管标识授予了对该密钥保管库的访问权限。
在此步骤中,你要使用密钥保管库信息更新服务总线命名空间。
- 创建名为 UpdateServiceBusNamespaceWithEncryption.json 的 JSON 文件,其中包含以下内容: - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "type":"string", "metadata":{ "description":"Name for the Namespace to be created in cluster." } }, "location":{ "type":"string", "defaultValue":"[resourceGroup().location]", "metadata":{ "description":"Specifies the Azure location for all resources." } }, "keyVaultUri":{ "type":"string", "metadata":{ "description":"URI of the KeyVault." } }, "keyName":{ "type":"string", "metadata":{ "description":"KeyName." } } }, "resources":[ { "type":"Microsoft.ServiceBus/namespaces", "apiVersion":"2018-01-01-preview", "name":"[parameters('namespaceName')]", "location":"[parameters('location')]", "identity":{ "type":"SystemAssigned" }, "sku":{ "name":"Premium", "tier":"Premium", "capacity":1 }, "properties":{ "encryption":{ "keySource":"Microsoft.KeyVault", "keyVaultProperties":[ { "keyName":"[parameters('keyName')]", "keyVaultUri":"[parameters('keyVaultUri')]" } ] } } } ] }
- 创建模板参数文件:UpdateServiceBusNamespaceWithEncryptionParams.json。 - 注意 - 请替换以下值: - <ServiceBusNamespaceName>- 你的服务总线命名空间的名称
- <Location>- 你的服务总线命名空间的位置
- <KeyVaultName>- 你的密钥保管库的名称
- <KeyName>- 密钥保管库中密钥的名称
 - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "value":"<ServiceBusNamespaceName>" }, "location":{ "value":"<Location>" }, "keyName":{ "value":"<KeyName>" }, "keyVaultUri":{ "value":"https://<KeyVaultName>.vault.azure.net" } } }
- 运行以下 PowerShell 命令以部署资源管理器模板。 在运行该命令之前,请将 - {MyRG}替换为你的资源组名称。- New-AzResourceGroupDeployment -Name UpdateServiceBusNamespaceWithEncryption -ResourceGroupName {MyRG} -TemplateFile ./UpdateServiceBusNamespaceWithEncryption.json -TemplateParameterFile ./UpdateServiceBusNamespaceWithEncryptionParams.json
使用用户分配的标识进行加密(模板)
- 创建用户分配的标识。
- 创建密钥保管库,并通过访问策略向用户分配的标识授予访问权限。
- 使用托管用户标识和密钥保管库信息创建高级服务总线命名空间。
创建用户分配的标识
按照创建用户分配的托管标识文章中的说明创建用户分配的标识。 也可使用 CLI、PowerShell、Azure 资源管理器模板和 REST 创建用户分配标识。
注意
最多可以将 4 个用户标识分配给命名空间。 删除命名空间或将模板中的 identity -> type 传递到 None 时,将删除这些关联。
授予对用户分配的标识的访问权限
- 使用以下 PowerShell 命令获取用于用户标识的服务主体标识。 在示例中, - ud1是用户分配的标识,用于加密。- $servicePrincipal=Get-AzADServicePrincipal -SearchString "ud1"
- 通过分配访问策略,向用户分配的标识授予对密钥保管库的访问权限。 - Set-AzureRmKeyVaultAccessPolicy -VaultName {keyVaultName} -ResourceGroupName {RGName} -ObjectId $servicePrincipal.Id -PermissionsToKeys get,wrapKey,unwrapKey,list- 注意 - 可以添加最多 3 个密钥,但对于所有密钥,用于加密的用户标识应相同。 目前,仅支持单个加密标识。 
使用用户标识和密钥保管库信息创建高级服务总线命名空间
本节举例说明如何使用 Azure 资源管理器模板执行以下任务。
- 将用户管理的标识分配给服务总线命名空间。 - "identity": { "type": "UserAssigned", "userAssignedIdentities": { "[parameters('identity').userAssignedIdentity]": {} } },
- 通过指定密钥保管库中的密钥和用于访问该密钥的用户托管标识,对命名空间启用加密。 - "encryption":{ "keySource":"Microsoft.KeyVault", "keyVaultProperties":[ { "keyName": "[parameters('keyName')]", "keyVaultUri": "[parameters('keyVaultUri')]", "identity": { "userAssignedIdentity": "[parameters('identity').userAssignedIdentity]" } } ] }
- 使用以下内容创建一个名为 CreateServiceBusNamespaceWithUserIdentityAndEncryption.json 的 JSON 文件: - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "type":"string", "metadata":{ "description":"Name for the Namespace to be created in cluster." } }, "location":{ "type":"string", "defaultValue":"[resourceGroup().location]", "metadata":{ "description":"Specifies the Azure location for all resources." } }, "keyVaultUri":{ "type":"string", "metadata":{ "description":"URI of the KeyVault." } }, "keyName":{ "type":"string", "metadata":{ "description":"KeyName." }, "identity": { "type": "Object", "defaultValue": { "userAssignedIdentity": "" }, "metadata": { "description": "user-assigned identity." } } }, "resources":[ { "type":"Microsoft.ServiceBus/namespaces", "apiVersion":"2021-01-01-preview", "name":"[parameters('namespaceName')]", "location":"[parameters('location')]", "sku":{ "name":"Premium", "tier":"Premium", "capacity":1 }, "identity": { "type": "UserAssigned", "userAssignedIdentities": { "[parameters('identity').userAssignedIdentity]": {} } }, "properties":{ "encryption":{ "keySource":"Microsoft.KeyVault", "keyVaultProperties":[ { "keyName": "[parameters('keyName')]", "keyVaultUri": "[parameters('keyVaultUri')]", "identity": { "userAssignedIdentity": "[parameters('identity').userAssignedIdentity]" } } ] } } } ] }
- 创建一个模板参数文件:CreateServiceBusNamespaceWithUserIdentityAndEncryptionParams.json。 - { "$schema":"https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion":"1.0.0.0", "parameters":{ "namespaceName":{ "value":"<ServiceBusNamespaceName>" }, "location":{ "value":"<Location>" }, "keyVaultUri":{ "value":"https://<KeyVaultName>.vault.azure.net" }, "keyName":{ "value":"<KeyName>" }, "identity": { "value": { "userAssignedIdentity": "/subscriptions/<AZURE SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP NAME>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER MANAGED IDENTITY NAME>" } } } }- 在参数文件中,将占位符替换为相应的值。 - 占位符 - 价值 - <ServiceBusNamespaceName>- 服务总线命名空间的名称。 - <Location>- 要创建命名空间的位置。 - <KeyVaultName>- 密钥保管库的名称。 - <KeyName>- 密钥保管库中密钥的名称。 - <AZURE SUBSCRIPTION ID>- Azure 订阅 ID。 - <RESOURCE GROUP NAME>- 用户托管标识的资源组。 - <USER MANAGED IDENTITY NAME>- 用户托管标识的名称。 
- 运行以下 PowerShell 命令以部署资源管理器模板。 在运行该命令之前,请将 - {MyRG}替换为你的资源组名称。- New-AzResourceGroupDeployment -Name CreateServiceBusNamespaceWithEncryption -ResourceGroupName {MyRG} -TemplateFile ./ CreateServiceBusNamespaceWithUserIdentityAndEncryption.json -TemplateParameterFile ./ CreateServiceBusNamespaceWithUserIdentityAndEncryptionParams.json
同时使用用户分配的标识和系统分配的标识
一个命名空间可同时具有系统分配的标识和用户分配的标识。 在这种情况下,type 属性将为 SystemAssigned、UserAssigned,如下例所示。
"identity": {
    "type": "SystemAssigned, UserAssigned",
    "userAssignedIdentities": {
        "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<userIdentity1>" : {}
    }
}
在此方案中,可以选择系统分配的标识或用户分配的标识来加密静态数据。
在资源管理器模板中,如果未指定 identity 属性,则使用系统托管标识。 下面是一个示例片段。
"properties":{
   "encryption":{
      "keySource":"Microsoft.KeyVault",
      "keyVaultProperties":[
         {
            "keyName":"[parameters('keyName')]",
            "keyVaultUri":"[parameters('keyVaultUri')]"
         }
      ]
   }
}
参见以下使用用户托管标识进行加密的示例。 请注意,identity 属性被设置为用户管理的身份。
"properties":{
   "encryption":{
      "keySource":"Microsoft.KeyVault",
      "keyVaultProperties":[
         {
            "keyName":"[parameters('keyName')]",
            "keyVaultUri":"[parameters('keyVaultUri')]",
            "identity": {
                "userAssignedIdentity": "[parameters('identity').userAssignedIdentity]"
            }
         }
      ]
   }
}
对数据启用基础结构(双重)加密
如果需要更高级别的数据安全保证,则可以启用基础结构级别的加密(也称为双重加密)。
启用基础结构加密后,将对 Azure 服务总线中的数据进行两次加密,分别在服务级别和基础架构级别使用两种不同的加密算法和两个不同的密钥。 因此,Azure 服务总线数据的基础结构加密可以在其中一种加密算法或密钥可能泄露的情况下提供保护。
此外,只有在从“Microsoft托管密钥”切换到“客户管理的密钥”时,才能启用基础结构加密。
甚至可以稍后使用 UpdateServiceBusNamespaceWithEncryption.json 中的属性更新 Azure 资源管理器模板requireInfrastructureEncryption来启用基础结构加密,如以下示例所示。
"properties":{
   "encryption":{
      "keySource":"Microsoft.KeyVault",    
      "requireInfrastructureEncryption":true,         
      "keyVaultProperties":[
         {
            "keyName":"[parameters('keyName')]",
            "keyVaultUri":"[parameters('keyVaultUri')]"
         }
      ]
   }
}
轮换、撤销和缓存密钥
轮换加密密钥
可以使用 Azure Key Vault 轮换机制来轮换密钥保管库中的密钥。 还可以设置激活和过期日期以自动轮换密钥。 服务总线服务会检测新密钥版本,并自动开始使用新版本。
撤销对密钥的访问权限
撤销对加密密钥的访问权限不会从服务总线中清除数据。 但是,将无法从服务总线命名空间访问数据。 可以通过使用访问策略或删除密钥来撤销加密密钥。 在保护对密钥保管库的访问中详细了解访问策略以及如何保护密钥保管库。
撤销加密密钥后,已加密的命名空间中的服务总线服务会无法正常运行。 如果启用了对密钥的访问或者还原了已删除的密钥,则服务总线服务会选取密钥,使你能够从已加密的服务总线命名空间访问数据。
缓存密钥
服务总线实例每 5 分钟轮询一次列出的加密密钥。 它会缓存并使用这些,直至下一次轮询(即 5 分钟后)。 只要至少有一个加密密钥可用,就可以访问队列和主题。 如果所有列出的密钥在轮询时均无法访问,则所有队列和主题都会变为不可用。
下面是更多详细信息:
- 服务总线服务每隔 5 分钟就会轮询命名空间记录中列出的所有由客户管理的密钥:- 如果轮换了密钥,记录就会更新为新密钥。
- 如果撤消了密钥,该密钥则会从记录中被删除。
- 如果撤销了所有密钥,则命名空间的加密状态会设置为“已撤销”。 将无法从服务总线命名空间访问数据。
 
使用异地灾难恢复时的注意事项
使用系统分配的标识进行加密
为了将客户管理的密钥用于 Microsoft 管理的密钥的加密,已在指定的 Azure KeyVault 上为系统分配的托管标识设置访问策略。 此步骤可确保能够控制从 Azure 服务总线命名空间对 Azure KeyVault 的访问。 因此,需要执行以下步骤:
- 如果已经为服务总线命名空间启用了异地灾难恢复,并且你想要启用客户管理的密钥,那么 - 断开配对。
- 为密钥保管库主命名空间和辅助命名空间的系统分配的托管标识设置访问策略。
- 在主要命名空间上设置加密。
- 将主要和辅助命名空间重新配对。
 
- 如果想要对已设置客户管理的密钥的服务总线命名空间启用异地灾难恢复,请执行以下步骤:- 为密钥保管库设置针对辅助命名空间的托管标识的访问策略。
- 将主要和辅助命名空间配对。
 
使用用户分配的标识进行加密
以下是一些建议:
- 创建托管标识,并向托管标识分配密钥保管库权限。
- 将此标识添加为用户分配标识,并在两个命名空间上使用该标识启用加密。
- 将命名空间配对在一起。
启用异地灾难恢复和使用用户分配的标识加密的条件:
- 如果辅助命名空间要与启用加密的主命名空间配对,则必须已使用用户分配的标识启用加密。
- 即使辅助命名空间具有与已配对的主命名空间关联的用户分配的标识,也无法在此主命名空间上启用加密。
疑难解答
症状
你收到一个错误,指出服务总线命名空间已禁用,因为加密密钥不再有效。
原因
你正在使用连接到特定密钥版本(已过期)的 resource_id 或 version。 如果提供了特定版本,则服务总线会使用该版本的密钥,即便密钥已轮换。
解决方法
使用 resource__versionless_id 或 versionless_id,而不使用 resource_id 或 version。
后续步骤
请参阅以下文章: