配置客户管理的密钥来加密Azure 服务总线的静态数据

Azure 服务总线高级版通过Azure 存储服务加密(Azure SSE)提供静态数据的加密。 服务总线 Premium 使用Azure 存储来存储数据。 存储在Azure 存储中的所有数据都使用Azure管理的密钥进行加密。 如果使用自己的密钥(也称为自带密钥(BYOK)或客户管理的密钥),则数据仍使用Azure管理的密钥进行加密,但此外,Azure管理的密钥使用客户管理的密钥进行加密。 使用此功能,可以创建、轮换、禁用和撤销对用于加密Azure托管密钥的客户管理的密钥的访问权限。 启用 BYOK 功能是在命名空间中执行的一次性设置过程。

对于用于服务端加密的客户管理密钥,需要注意一些事项。

  • Azure 服务总线 Premium 层支持此功能。 不能为服务总线标准层命名空间启用它。
  • 只能为新的或空的命名空间启用加密。 如果命名空间包含任何队列或主题,则加密操作会失败。

可以使用Azure 密钥保管库(包括Azure 密钥保管库托管硬件安全模块 (HSM)来管理密钥并审核密钥使用情况。 可以创建自己的密钥并将其存储在密钥保管库中,也可以使用Azure 密钥保管库 API 生成密钥。 有关Azure 密钥保管库的详细信息,请参阅 什么是 Azure 密钥保管库?

如果只需要加密消息的部分属性,请考虑使用 NServiceBus 等库。

Note

在以下方案中,客户管理的密钥被视为已禁用:

  • 撤消访问权限:如果服务总线不再有权访问Azure 密钥保管库中的密钥。
  • 禁用密钥:手动禁用密钥保管库中的密钥会使密钥不可用。
  • 让密钥过期:如果密钥在未续订的情况下达到其到期日期。 让密钥过期的效果与撤消或禁用密钥的效果相同。 在密钥过期之前始终轮换或续订密钥,以避免意外中断。
  • 删除密钥:删除后,密钥将永久无法访问。

启用客户管理的密钥(Azure门户)

若要在 Azure 门户中启用客户管理的密钥,请执行以下步骤:

  1. 导航到 服务总线 高级版命名空间。

  2. 在服务总线命名空间的 Settings 页上,选择 Encryption

  3. 选择“客户管理的密钥加密(静态)”,如下图所示。

    显示如何启用客户管理的密钥的屏幕截图。

    Note

    目前无法通过门户配置Azure 密钥保管库托管 HSM。

设置密钥保管库与密钥

启用客户管理的密钥后,需要将客户管理的密钥与Azure 服务总线命名空间相关联。 服务总线仅支持Azure 密钥保管库。 如果使用客户管理的密钥启用 Encryption 选项,则需要将密钥导入Azure 密钥保管库。 此外,密钥必须配置“软删除”和“禁止清除”功能。 可以使用 PowerShell 或 CLI 配置这些设置。

创建密钥保管库或密钥保管库托管 HSM

Important

在 Azure 服务总线 上使用客户管理的密钥要求保管库配置两个必要的属性。 它们是:“软删除”和“不清除”。 在 Azure 门户中创建新保管库时,默认启用软删除属性,而清除保护是可选的,因此请确保在创建保管库时选择它。 此外,如果需要在现有密钥保管库上启用这些属性,则必须使用 PowerShell 或Azure CLI。

  • 若要创建新的密钥保管库,请遵循 Azure 密钥保管库 Quickstart。 有关 Azure KeyVault 的信息,请参阅 About Azure KeyVault

  • 若要在创建保管库时启用“软删除”和“清除保护”,请使用 az keyvault create 命令。

    az keyvault create --name contoso-SB-BYOK-keyvault --resource-group ContosoRG --location chinanorth --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
    

创建密钥

遵循以下步骤创建密钥:

  1. 若要创建新密钥,请从“设置” 下的“密钥” 菜单中选择“生成/导入” 。

    显示“生成/导入”按钮的屏幕截图。

  2. 将“选项” 设置为“生成” 并提供密钥名称。

    显示如何命名密钥的屏幕截图。

  3. 现在,可以选择此密钥以与服务总线命名空间相关联,以便从下拉列表中加密。

    显示如何从密钥保管库中选择密钥的屏幕截图。

    Note

    最多可以添加三个密钥以保证冗余。 如果其中一个密钥已过期或无法访问,则可以使用其他密钥加密。

  4. 填写密钥详细信息,然后单击“选择”。 它使您能够用您自己的密钥(客户管理的密钥)加密由Azure管理的密钥。

    Important

    如果要将客户管理的密钥与异地灾难恢复一起使用,请查看本部分。

    若要使用客户管理的密钥对 Azure 托管密钥进行加密,需要在指定的 Azure 密钥库中为 服务总线 的托管标识设置一个访问策略。 这可确保从Azure 服务总线命名空间控制对 Azure KeyVault 的访问。

    此行为会导致:

    • 如果已为 服务总线 命名空间启用了 Geo-Disaster Recovery,并且希望启用客户管理密钥,则

      • 断开配对
      • 为密钥保管库设置针对主要和辅助命名空间的托管标识的访问策略。
      • 在主要命名空间上设置加密。
      • 将主要和辅助命名空间重新配对。
    • 如果要在已设置客户管理密钥的服务总线命名空间上启用地理灾难恢复,则可以启用地理灾难恢复。

      • 为辅助命名空间的托管身份设置访问策略至密钥保管库。
      • 将主要和辅助命名空间配对。
    • 配对后,辅助命名空间使用为主命名空间配置的密钥保管库。 如果在异地灾难恢复配对之前,这两个命名空间的密钥保管库不同,则用户必须在与主命名空间关联的密钥保管库中,为辅助命名空间的托管标识委派访问策略或角色访问控制 (RBAC) 角色。

托管标识

有两种类型的托管标识可以分配给服务总线命名空间。

  • 系统分配的:可以直接在 服务总线 命名空间上启用托管身份。 启用系统分配的托管标识时,会在Microsoft Entra中创建一个标识,并将其绑定到该服务总线命名空间的生命周期。 因此,删除命名空间时,Azure会为您自动删除身份。 根据设计,只有Azure资源(命名空间)才能使用此标识从Microsoft Entra ID请求令牌。
  • 用户分配:还可以将托管标识创建为独立的Azure资源,称为用户分配标识。 可以创建用户分配的托管标识并将其分配给一个或多个服务总线命名空间。 使用用户分配的托管标识时,标识与使用它的资源分开管理。 它们不与命名空间的生命周期相关联。 可以显式删除不再需要的用户分配身份。

有关详细信息,请参阅 Azure 资源的托管标识是什么?

使用系统分配的标识(模板)进行加密

本节介绍如何执行以下任务:

  • 创建premium 服务总线命名空间,该命名空间具有 托管服务标识
  • 创建密钥保管库并向服务标识授予对密钥保管库的访问权限。
  • 使用密钥保管库信息(密钥/值)更新服务总线命名空间。

使用托管服务标识创建高级服务总线命名空间

本部分介绍如何使用Azure 资源管理器模板和 PowerShell 创建具有托管服务标识的Azure 服务总线命名空间。

  1. 创建模板以使用托管服务标识创建服务总线高级层命名空间:

    创建包含以下内容的名为 CreateServiceBusPremiumNamespace.bicep 的文件:

    @description('Name for the Namespace.')
    param namespaceName string
    
    @description('Specifies the Azure location for all resources.')
    param location string = resourceGroup().location
    
    resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
      name: namespaceName
      location: location
      identity: {
        type: 'SystemAssigned'
      }
      sku: {
        name: 'Premium'
        tier: 'Premium'
        capacity: 1
      }
      properties: {}
    }
    
    output serviceBusNamespaceId string = serviceBusNamespace.id
    
  2. 运行以下命令以部署模板以创建高级服务总线命名空间。 然后,检索服务总线命名空间的 ID,以便稍后使用它。

    outputs=$(az deployment group create --name CreateServiceBusPremiumNamespace --resource-group <ResourceGroupName> --template-file ./CreateServiceBusPremiumNamespace.bicep --parameters namespaceName='<ServiceBusNamespaceName>' location='<Location>' --query properties.outputs)
    
    serviceBusNamespaceId=$(echo $outputs | jq -r '.serviceBusNamespaceId.value')
    

授予 服务总线 命名空间标识 对密钥保管库的访问权限

设置密钥保管库访问策略,以便服务总线命名空间的托管标识可以访问密钥保管库中的密钥值。 使用上一部分中的服务总线命名空间 ID。

$identity = (Get-AzureRmResource -ResourceId $ServiceBusNamespaceId -ExpandProperties).Identity

Set-AzureRmKeyVaultAccessPolicy -VaultName {keyVaultName} -ResourceGroupName {RGName} -ObjectId $identity.PrincipalId -PermissionsToKeys get,wrapKey,unwrapKey,list

使用密钥保管库中的客户管理的密钥加密服务总线命名空间中的数据

到目前为止,你执行了以下步骤:

  1. 创建了具有托管标识的高级命名空间。

  2. 创建密钥保管库,并向托管身份授予访问密钥保管库的权限。

在此步骤中,使用密钥保管库信息更新服务总线命名空间。

  1. 创建模板以使用加密更新服务总线命名空间:

    创建包含以下内容的 名为 UpdateServiceBusNamespaceWithEncryption.bicep 的文件:

    @description('Name for the Namespace to be created in cluster.')
    param namespaceName string
    
    @description('Specifies the Azure location for all resources.')
    param location string = resourceGroup().location
    
    @description('URI of the KeyVault.')
    param keyVaultUri string
    
    @description('KeyName.')
    param keyName string
    
    resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
      name: namespaceName
      location: location
      identity: {
        type: 'SystemAssigned'
      }
      sku: {
        name: 'Premium'
        tier: 'Premium'
        capacity: 1
      }
      properties: {
        encryption: {
          keySource: 'Microsoft.KeyVault'
          keyVaultProperties: [
            {
              keyName: keyName
              keyVaultUri: keyVaultUri
            }
          ]
        }
      }
    }
    
  2. 运行以下命令来部署模板。

    az deployment group create --name UpdateServiceBusNamespaceWithEncryption --resource-group <ResourceGroupName> --template-file ./UpdateServiceBusNamespaceWithEncryption.bicep --parameters namespaceName='<ServiceBusNamespaceName>' location='<Location>' keyName='<KeyName>' keyVaultUri='https://<KeyVaultName>.vault.azure.cn'
    

    Note

    对于密钥保管库托管的HSM,请使用https://<KeyVaultName>.managedhsm.chinacloudapi.cn 作为密钥保管库 URI。

使用用户分配的标识进行加密(模板)

  1. 创建用户分配的标识。

  2. 创建密钥保管库,并通过访问策略向用户分配的标识授予访问权限。

  3. 使用托管用户标识和密钥保管库信息创建 premium 服务总线 命名空间。

创建用户分配的标识

按照创建用户分配的托管标识文章中的说明创建用户分配的标识。 还可以使用 CLIPowerShellAzure 资源管理器 模板REST 创建用户分配的标识。

Note

最多可以将 4 个用户标识分配给命名空间。 删除命名空间或将模板中的 传递到 时,将删除这些关联。

为用户分配的身份授予访问权限

  1. 使用以下 PowerShell 命令获取用户标识的服务主体 ID。 在示例中, 是用户分配的标识,用于加密。

    $servicePrincipal=Get-AzADServicePrincipal -SearchString "ud1"    
    
  2. 通过分配访问策略,为用户分配的身份授予对密钥保管库的访问权限。

    Set-AzureRmKeyVaultAccessPolicy -VaultName {keyVaultName} -ResourceGroupName {RGName} -ObjectId $servicePrincipal.Id -PermissionsToKeys get,wrapKey,unwrapKey,list    
    

    Note

    可以添加最多 3 个密钥,但对于所有密钥,用于加密的用户标识应相同。 目前,仅支持单个加密标识。

使用用户标识和密钥保管库信息创建高级服务总线命名空间

本部分提供了一个示例,演示如何使用Azure 资源管理器模板执行以下任务。

  1. 将用户管理的标识分配给 服务总线 命名空间。

                "identity": {
                    "type": "UserAssigned",
                    "userAssignedIdentities": {
                        "[parameters('identity').userAssignedIdentity]": {}
                    }
                },
    
  2. 通过指定密钥保管库中的密钥和用于访问该密钥的用户托管标识,对命名空间启用加密。

                    "encryption":{
                       "keySource":"Microsoft.KeyVault",
                       "keyVaultProperties":[
                            {
                                "keyName": "[parameters('keyName')]",
                                "keyVaultUri": "[parameters('keyVaultUri')]",
                                "identity": {
                                    "userAssignedIdentity": "[parameters('identity').userAssignedIdentity]"
                                }
                            }
                       ]
                    }
    
  3. 使用用户分配的标识和加密为服务总线命名空间创建模板:

    创建包含以下内容的名为 CreateServiceBusNamespaceWithUserIdentityAndEncryption.bicep 的文件:

    @description('Name for the Namespace to be created in cluster.')
    param namespaceName string
    
    @description('Specifies the Azure location for all resources.')
    param location string = resourceGroup().location
    
    @description('URI of the KeyVault.')
    param keyVaultUri string
    
    @description('KeyName.')
    param keyName string
    
    @description('Resource ID of the user-assigned identity.')
    param userAssignedIdentity string
    
    resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2024-01-01' = {
      name: namespaceName
      location: location
      sku: {
        name: 'Premium'
        tier: 'Premium'
        capacity: 1
      }
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '${userAssignedIdentity}': {}
        }
      }
      properties: {
        encryption: {
          keySource: 'Microsoft.KeyVault'
          keyVaultProperties: [
            {
              keyName: keyName
              keyVaultUri: keyVaultUri
              identity: {
                userAssignedIdentity: userAssignedIdentity
              }
            }
          ]
        }
      }
    }
    
  4. 运行以下命令来部署模板。

    az deployment group create --name CreateServiceBusNamespaceWithEncryption --resource-group <ResourceGroupName> --template-file ./CreateServiceBusNamespaceWithUserIdentityAndEncryption.bicep --parameters namespaceName='<ServiceBusNamespaceName>' location='<Location>' keyName='<KeyName>' keyVaultUri='https://<KeyVaultName>.vault.azure.cn' userAssignedIdentity='/subscriptions/<SubscriptionId>/resourceGroups/<ResourceGroup>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<UserManagedIdentityName>'
    

    Note

    对于 密钥保管库 托管的 HSM,请使用 https://<KeyVaultName>.managedhsm.chinacloudapi.cn 作为 密钥保管库 URI。

同时使用用户分配的标识和系统分配的标识

一个命名空间可同时具有系统分配的标识和用户分配的标识。 在这种情况下, 属性将为 、,如下例所示。

"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')]"
         }
      ]
   }
}

参见以下使用用户托管标识进行加密的示例。 请注意,该属性已设置为用户管理的标识。

"properties":{
   "encryption":{
      "keySource":"Microsoft.KeyVault",
      "keyVaultProperties":[
         {
            "keyName":"[parameters('keyName')]",
            "keyVaultUri":"[parameters('keyVaultUri')]",
            "identity": {
                "userAssignedIdentity": "[parameters('identity').userAssignedIdentity]"
            }
         }
      ]
   }
}

对数据启用基础结构(双重)加密

如果需要更高级别的数据安全保证,则可以启用基础结构级别的加密(也称为双重加密)。

启用基础结构加密后,Azure 服务总线中的数据会加密两次,一次在服务级别加密,一次在基础结构级别使用两种不同的加密算法和两个不同的密钥。 因此,Azure 服务总线数据的基础结构加密可防止其中一种加密算法或密钥遭到入侵的情况。

此外,只能在从“Azure托管密钥”切换到“客户管理的密钥”时启用基础结构加密。

甚至可以在以后通过更新包含 requireInfrastructureEncryption 属性的 UpdateServiceBusNamespaceWithEncryption.json 文件中的 Azure 资源管理器模板来启用基础结构加密,如以下示例所示。

"properties":{
   "encryption":{
      "keySource":"Microsoft.KeyVault",    
      "requireInfrastructureEncryption":true,         
      "keyVaultProperties":[
         {
            "keyName":"[parameters('keyName')]",
            "keyVaultUri":"[parameters('keyVaultUri')]"
         }
      ]
   }
}

轮换、撤销和缓存密钥

轮换加密密钥

可以使用Azure密钥保管库轮换机制在密钥保管库中轮换密钥。 还可以设置激活和过期日期以自动轮换密钥。 服务总线服务会检测新的密钥版本,并自动开始使用它们。

撤销对密钥的访问权限

撤消对加密密钥的访问权限不会从服务总线中清除数据。 但是,无法从服务总线命名空间访问数据。 可以通过使用访问策略或删除密钥来撤销加密密钥。 详细了解访问策略和保护密钥保管库的信息,请参阅[安全访问密钥保管库]。

撤销加密密钥后,加密命名空间上的服务总线服务变为不可作。 如果启用对密钥的访问或还原已删除的密钥,服务总线服务会选取密钥,以便可以从加密的服务总线命名空间访问数据。

缓存密钥

服务总线实例每隔 5 分钟轮询其列出的加密密钥。 缓存这些密钥并继续使用,直到下一次轮询,即 5 分钟后。 只要至少有一个加密密钥可用,就可以访问队列和主题。 如果所有列出的密钥在轮询时均无法访问,则所有队列和主题都会变为不可用。

下面是更多详细信息:

  • 服务总线服务每隔 5 分钟轮询命名空间记录中列出的所有客户管理的密钥:
    • 如果轮换了密钥,记录就会更新为新密钥。
    • 如果撤消了密钥,该密钥则会从记录中被删除。
    • 如果撤销了所有密钥,则命名空间的加密状态设置为 “已撤销”。 无法从服务总线命名空间访问数据。

使用异地灾难恢复时的注意事项

使用系统分配的标识进行加密

若要使用客户管理的密钥来启用对 Azure 托管密钥的加密,需要在指定的 Azure KeyVault 中为系统分配的托管标识设置访问策略。 此步骤可确保从Azure 服务总线命名空间控制对 Azure KeyVault 的访问。 因此,需要执行以下步骤:

  • 如果已为 服务总线 命名空间启用了 Geo-Disaster Recovery,并希望启用客户托管密钥,请按照以下步骤进行:
    • 断开配对。
    • 为密钥保管库的主命名空间和辅助命名空间的系统分配的托管标识设置访问策略。
    • 在主要命名空间上设置加密。
    • 将主要和辅助命名空间重新配对。
  • 如果要在已设置了客户管理密钥的 服务总线 命名空间上启用地理灾难恢复,请执行以下步骤:
    • 为辅助命名空间的托管身份设置访问策略至密钥保管库。
    • 将主要和辅助命名空间配对。

使用用户分配的标识进行加密

以下是一些建议:

  • 创建托管标识并将密钥保管库权限分配给托管标识。
  • 将该身份添加为用户分配的身份,并在两个命名空间中使用该身份启用加密。
  • 将命名空间配对在一起。

启用异地灾难恢复和使用用户分配的标识加密的条件:

  • 如果辅助命名空间要与启用加密的主命名空间配对,则必须已使用用户分配的标识启用加密。
  • 即使辅助命名空间具有与已配对的主命名空间关联的用户分配的标识,也无法在此主命名空间上启用加密。

Troubleshoot

Symptom

出现错误,指出服务总线命名空间已禁用,因为加密密钥不再有效。

Cause

你正在使用 或 链接到特定版本的密钥(已过期)。 如果提供了特定版本,则服务总线使用该版本的密钥,即使密钥已轮换也是如此。

Resolution

使用 或 ,而不使用 或 。

后续步骤

请参阅以下文章: