通过Azure 事件中心接收更改通知

Webhook 可能不适合在高吞吐量方案中接收更改通知,或者当接收方无法公开可用的通知 URL 时。 或者,可以使用 Azure 事件中心。

高吞吐量方案的不错示例包括订阅大量资源集的应用程序、订阅以高频率更改的资源的应用程序,以及跨大型组织订阅资源的多租户应用程序。

本文介绍如何管理 Microsoft Graph 订阅,并通过Azure 事件中心接收更改通知。

使用 Azure 事件中心接收更改通知

Azure 事件中心是专为大规模部署而构建的常用实时事件引入和分发服务。 你可以使用 Azure 事件中心而不是传统 Webhook 来接收更改通知。
使用 Azure 事件中心接收更改通知与 Webhook 在某些方面有所不同,包括:

  • 不依赖公开显示的通知 URL。 事件中心 SDK 会将通知转发到你的应用程序。
  • 无需恢复通知 URL 验证。 可忽略收到的验证消息。
  • 需要预配 Azure 事件中心。
  • 需要预配 Azure 密钥保管库。

设置 Azure 密钥保管库和 Azure 事件中心

本节将指导你完成所需的 Azure 服务设置。

Azure CLI 允许你在 Azure 中编写脚本并自动执行管理任务。 可以在本地计算机上安装 CLI 或直接从 Azure Cloud Shell 运行。

# --------------
# TODO: update the following values
#sets the name of the resource group
resourcegroup=rg-graphevents-dev
#sets the location of the resources
location='uk south'
#sets the name of the Azure Event Hubs namespace
evhamespacename=evh-graphevents-dev
#sets the name of the hub under the namespace
evhhubname=graphevents
#sets the name of the access policy to the hub
evhpolicyname=grapheventspolicy
#sets the name of the Azure KeyVault
keyvaultname=kv-graphevents
#sets the name of the secret in Azure KeyVault that will contain the connection string to the hub
keyvaultsecretname=grapheventsconnectionstring
# --------------
az group create --location $location --name $resourcegroup
az eventhubs namespace create --name $evhamespacename --resource-group $resourcegroup --sku Basic --location $location
az eventhubs eventhub create --name $evhhubname --namespace-name $evhamespacename --resource-group $resourcegroup --partition-count 2 --message-retention 1
az eventhubs eventhub authorization-rule create --name $evhpolicyname --eventhub-name $evhhubname --namespace-name $evhamespacename --resource-group $resourcegroup --rights Send
evhprimaryconnectionstring=`az eventhubs eventhub authorization-rule keys list --name $evhpolicyname --eventhub-name $evhhubname --namespace-name $evhamespacename --resource-group $resourcegroup --query "primaryConnectionString" --output tsv`
az keyvault create --name $keyvaultname --resource-group $resourcegroup --location $location --enable-soft-delete true --sku standard --retention-days 90
az keyvault secret set --name $keyvaultsecretname --value $evhprimaryconnectionstring --vault-name $keyvaultname --output none
graphspn=`az ad sp list --display-name 'Microsoft Graph Change Tracking' --query "[].appId" --output tsv`
az keyvault set-policy --name $keyvaultname --resource-group $resourcegroup --secret-permissions get --spn $graphspn --output none
keyvaulturi=`az keyvault show --name $keyvaultname --resource-group $resourcegroup --query "properties.vaultUri" --output tsv`
domainname=`az ad signed-in-user show --query 'userPrincipalName' | cut -d '@' -f 2 | sed 's/\"//'`
notificationUrl="EventHub:${keyvaulturi}secrets/${keyvaultsecretname}?tenantId=${domainname}"
echo "Notification Url:\n${notificationUrl}"

注意:此处提供的脚本与基于 Linux 的 命令行管理程序、Windows WSL 和 Azure Cloud Shell 兼容。 它要求在 Windows 命令行管理程序中运行某些更新。

创建订阅并接收通知

创建所需的 Azure 密钥保管库和 Azure 事件中心服务后,你将能够创建订阅并开始通过 Azure 事件中心接收更改通知。

创建订阅

使用事件中心订阅更改通知与使用 Webhook 订阅更改通知几乎相同。 主要区别在于前者依赖事件中心来传送通知。 所有其他操作都类似,包括创建订阅

创建订阅期间的主要区别是 notificationUrl。 必须将其设置为 EventHub:https://<azurekeyvaultname>.vault.azure.net/secrets/<secretname>?tenantId=<domainname>,并使用以下值:

  • azurekeyvaultname - 创建密钥保管库时为其提供的名称。 可在 DNS 名称中找到它。
  • secretname - 创建密钥时为其提供的名称。 可在 Azure 密钥保管库的“密钥”页面上找到它。
  • domainname - 租户的名称;例如,consto.onmicrosoft.com 或 contoso.com。 由于此域将用于访问 Azure 密钥保管库,因此请务必使其与包含 Azure 密钥保管库的 Azure 订阅所使用的域相匹配。 若要获取此信息,可转到你创建的 Azure 密钥保管库的概述页面,并单击该订阅。 域名将显示在“目录”字段下。

接收通知

事件现在将通过事件中心传送到你的应用程序中。 有关详细信息,请参阅事件中心文档中的接收事件

在应用程序中接收通知之前,你需要创建另一个具有“侦听”权限的共享访问策略并获取连接字符串,类似于配置 Azure 事件中心中列出的步骤。

注意:为应用程序创建单独的策略来侦听事件中心消息,而不是重用在 Azure 密钥保管库中设置的相同连接字符串。 这可确保解决方案的每个组件仅具有所需的权限,并遵循最低权限安全原则。

注意:应用程序会在每次创建新订阅时收到验证消息。 应忽略这些通知。 下面的示例表示验证消息的正文。

 {
    "value":[
        {
            "subscriptionId":"NA",
            "subscriptionExpirationDateTime":"NA",
            "clientState":"NA",
            "changeType":"Validation: Testing client application reachability for subscription Request-Id: 522a8e7e-096a-494c-aaf1-ac0dcfca45b7",
            "resource":"NA",
            "resourceData":{
                "@odata.type":"NA",
                "@odata.id":"NA",
                "id":"NA"
            }
        }
    ]
}

如果缺少Microsoft Graph 更改跟踪应用程序,会发生什么情况?

租户中可能缺少 Microsoft Graph 更改跟踪服务主体,这取决于租户的创建时间和管理操作。 要解决此问题,请在 Microsoft Graph 浏览器 中运行 以下查询

查询详细信息: 0bf30f3b-4a52-48df-9a82-234910c4a086 是Microsoft Graph 更改跟踪应用程序的全局 appId。

POST https://graph.microsoft.com/v1.0/servicePrincipals

{
    "appId": "0bf30f3b-4a52-48df-9a82-234910c4a086"
}

注意:运行此查询会导致访问被拒绝。 在这种情况下,请选择左上角帐户名称旁边的齿轮图标。 然后选择“选择权限”并搜索 Application.ReadWrite.All。 检查权限,然后选择“同意”。 同意此新权限后,再次运行请求。

注意:此 API 仅适用于学校或工作帐户,而不适用于个人帐户。 请确保使用域中的帐户登录。

或者,可以在 Microsoft Graph PowerShell 中使用 New-MgServicePrincipal cmdlet 添加缺少的服务主体。 下面是一个示例脚本。

Connect-Graph -Scopes "Application.ReadWrite.All"
New-MgServicePrincipal -AppId "0bf30f3b-4a52-48df-9a82-234910c4a086"

后续步骤

请参阅下面的 Azure 事件中心快速入门: