Webhook は、高スループットのシナリオで変更通知を受信する場合や、受信者が一般公開されている通知 URL を公開できない場合には適していません。 別の方法として、Azure Event Hubsを使用できます。
Azure Event Hubsを使用できる高スループットシナリオの例としては、大規模なリソースセットをサブスクライブするアプリケーション、頻繁に変更されるリソースをサブスクライブするアプリケーション、大規模な組織のリソースをサブスクライブするマルチテナント アプリケーションなどがあります。
この記事では、Microsoft Graph サブスクリプションを管理するプロセスと、Azure Event Hubsを通じて変更通知を受け取る方法について説明します。
重要
共有アクセス署名 (SAS) を使用して Event Hubs を認証することは、今後非推奨になる予定です。 代わりに、Microsoft Entra IDロールベースのアクセス制御 (RBAC) を使用して Event Hubs を認証することをお勧めします。
Azure Event Hubsを使用して変更通知を受信する
Azure Event Hubs は、一般的なリアルタイム イベントの取り込みと配布サービスであり、規模に合わせて構築されています。 変更通知の受け取りに Azure Event Hub を使用する方法は、次のような点で Webhook とは異なります。
- 公開されている通知 URL には依存しません。 Event Hubs SDK は、アプリケーションに通知を中継します。
-
通知 URL の検証に返信する必要はありません。 受信した検証メッセージは無視してかまいません。
- イベント ハブをプロビジョニングする必要があります。
- Azure Key Vaultをプロビジョニングするか、Microsoft Graph Change Tracking サービスをイベント ハブのデータ送信者ロールに追加する必要があります。
Azure Event Hubs認証を設定する
Azure Event Hubsでは、共有アクセス署名 (SAS) またはロールベースのアクセス制御 (RBAC) Microsoft Entra IDによる認証がサポートされます。 詳細については、「Azure Event Hubsへのアクセスを承認する」を参照してください。
このセクションでは、Azure portal Microsoft Entra IDロールベースのアクセス制御 (RBAC) を使用してAzure Event Hubs認証を設定する方法について説明します。
- Azure サブスクリプションにリソースを作成する権限を持つAzure portalにサインインします。
- [ リソースの作成] を選択し、検索バーに 「Event Hubs 」と入力し、 Event Hubs の提案を選択します。
- [Event Hubs の作成] ページで、[作成] を選択 します。
- Event Hubs 名前空間の作成の詳細を入力し、[ 作成] を選択します。
- Event Hubs 名前空間がプロビジョニングされたら、名前空間のページに移動します。
- [ Event Hubs ] を選択し、[ + イベント ハブ] を選択します。
- 新しいイベント ハブに名前を付けて、[ 作成] を選択します。
- イベント ハブが作成されたら、Event Hubs 名前空間に移動し、サイドバーから [Access Control (IAM)] を選択します。
- [ ロールの割り当て] を選択します。
- [ + 追加] を選択し、[ ロールの割り当ての追加] を選択します。
- [ロール] の [ジョブ関数ロール] に移動し、[Azure Event Hubsデータ送信者] を選択し、[次へ] を選択します。
- [ メンバー ] タブで、[ ユーザー、グループ、またはサービス プリンシパルへのアクセスを割り当てる] を選択します。
- [+ メンバーの選択] を選択し、[Microsoft Graph Change Tracking] を検索して選択します。
- [ 確認と割り当て] を選択してプロセスを完了します。
このセクションでは、Azure CLI を使用して共有アクセス署名 (SAS) を使用してAzure Event Hubs認証を設定する方法について説明します。
Azure CLI を使用すると、Azure の管理タスクをスクリプト化して自動化できます。 CLI は、ローカル コンピューターにインストールされているか、Azure Cloud Shell で直接実行することができます。
重要
共有アクセス署名 (SAS) を使用して Event Hubs を認証することは、今後非推奨になる予定です。 代わりにMicrosoft Entra IDロールベースのアクセス制御 (RBAC) を使用することをお勧めします。 ガイダンスに従って RBAC に移行します。
# --------------
# 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 portalを介して共有アクセス署名 (SAS) を使用してAzure Event Hubs認証を設定する方法について説明します。
重要
共有アクセス署名 (SAS) を使用して Event Hubs を認証することは、今後非推奨になる予定です。 代わりにMicrosoft Entra IDロールベースのアクセス制御 (RBAC) を使用することをお勧めします。 ガイダンスに従って RBAC に移行します。
このセクションでは、次の操作を行います。
- Event Hub 名前空間を作成します。
- その名前空間にハブを追加して、通知を中継して配信します。
- 新しく作成したハブに接続文字列を取得できる共有アクセス ポリシーを追加します。
手順:
- Azure サブスクリプションにリソースを作成する権限を持つAzure portalにサインインします。
- [ リソースの作成] を選択し、検索バーに 「Event Hubs 」と入力し、 Event Hubs の提案を選択します。
- [Event Hubs の作成] ページで、[作成] を選択 します。
- Event Hubs 名前空間の作成の詳細を入力し、[ 作成] を選択します。
- Event Hubs 名前空間がプロビジョニングされたら、名前空間のページに移動します。
- [ Event Hubs ] を選択し、[ + イベント ハブ] を選択します。
- 新しいイベント ハブに名前を付けて、[ 作成] を選択します。
- イベント ハブが作成されたら、イベント ハブの名前を選択し、[ 共有アクセス ポリシー ] と [+ 追加] を選択して新しいポリシーを追加します。
- ポリシーに名前を付け、[送信] をチェックし、[作成] を選択します。
- ポリシーが作成されたら、ポリシーの名前を選択して詳細パネルを開き、[ 接続文字列-主キー ] の値をコピーします。 値を記録します。次の手順で必要になります。
イベント ハブに安全にアクセスし、キーのローテーションを許可するために、Microsoft Graph は Azure Key Vaultを介してイベント ハブに接続文字列を取得します。
このセクションでは、次の操作を行います。
- シークレットを格納するための Azure Key Vaultを作成します。
- 接続文字列をシークレットとしてイベント ハブに追加します。
- Microsoft Graph がシークレットにアクセスするためのアクセス ポリシーを追加します。
手順:
- Azure サブスクリプションにリソースを作成する権限を持つAzure portalにサインインします。
- [リソースの作成] を選択し、検索バーに「Key Vault」と入力し、Key Vault候補を選択します。
- [Key Vault作成] ページで、[作成] を選択します。
- Key Vault作成の詳細を入力し、[確認と作成と作成] を選択します。
- 通知で [リソースに移動] を使用して、新しく作成されたキーのキー コンテナーに移動します。
-
DNS 名をコピーします。この記事の後半で必要になります。
-
[シークレット] に移動し、[+ 生成/インポート] を選択します。
- シークレットに名前を付け、後で名前を保持します。この記事の後半で必要になります。 値として、Event Hubs 手順で生成した接続文字列を貼り付けます。
[作成] を選択します。
- [ アクセス ポリシー] を選択し、[ + アクセス ポリシーの追加] を選択します。
-
[シークレットのアクセス許可] 場合、[取得] を選択し、[プリンシパルを選択] の場合、[Microsoft Graph の変更追跡] を選択します。
[追加] を選択します。
サブスクリプションを作成し、通知を受信する
必要な Azure KeyVault サービスとAzure Event Hubs サービスを作成した後、変更通知サブスクリプションを作成し、Azure Event Hubs経由で変更通知の受信を開始できるようになりました。
サブスクリプションを作成する
Event Hubs で変更通知を受信するサブスクリプションの作成は、Webhook サブスクリプションの作成とほぼ同じですが、 notificationUrl プロパティに重要な変更があります。 続行する前に、まず Webhook サブスクリプションの作成手順 を確認します。
サブスクリプションの作成時に、 notificationUrl は Event Hubs の場所をポイントする必要があります。
ロールベースのアクセス制御を使用している場合、 notificationUrl プロパティは次のようになります。
EventHub:https://<eventhubnamespace>.servicebus.windows.net/eventhubname/<eventhubname>?tenantId=<domainname>
-
<eventhubnamespace>
は、Event Hubs 名前空間に付ける名前です。 [イベント ハブの概要] ページの [ホスト名] にあります。
-
<eventhubname>
は、イベント ハブに付ける名前です。 Event Hubs -> 概要 -> Event Hubs にあります。
-
<domainname>
はテナントの名前です。たとえば、 contoso.com
。 このドメインはAzure Event Hubsにアクセスするために使用されるため、Azure Event Hubsを保持する Azure サブスクリプションで使用されるドメインと一致することが重要です。 この情報を取得するには、Azure portalの [Microsoft Entra ID] メニューを選択し、[概要] ページをチェックします。 ドメイン名はプライマリ ドメインの下に表示されます。
Key Vaultを使用している場合、notificationUrl プロパティは次のようになります。 EventHub:https://<azurekeyvaultname>.vault.azure.net/secrets/<secretname>?tenantId=<domainname>
、次の値を使用します。
-
<azurekeyvaultname>
- 作成時にキー コンテナーに指定した名前。 DNS 名で確認できます。
-
<secretname>
- 作成時にシークレットに指定した名前。 Azure Key Vault シークレットページにあります。
-
<domainname>
- テナントの名前。たとえば、 contoso.com
。 このドメインは Azure Key Vaultにアクセスするために使用されるため、Azure Key Vaultを保持する Azure サブスクリプションで使用されるドメインと一致することが重要です。 この情報を取得するには、作成した Azure Key Vaultの概要ページに移動し、サブスクリプションを選択します。 ドメイン名がディレクトリ フィールドの下に表示されます。
注:
重複するサブスクリプションは許可されません。 サブスクリプション要求に、既存のサブスクリプションに含まれている changeType と リソース に同じ値が含まれている場合、要求は HTTP エラー コード 409 Conflict
で失敗し、エラー メッセージ Subscription Id <> already exists for the requested combination
。
イベント ハブ認証を RBAC にMicrosoft Entra ID移行する
共有アクセス署名 (SAS) を使用して Event Hubs を認証することは、今後非推奨になる予定です。 代わりに、Microsoft Entra IDロールベースのアクセス制御 (RBAC) を使用して Event Hubs を認証することをお勧めします。
このセクションでは、SAS 認証を使用して既存の Event Hubs を RBAC 認証をMicrosoft Entra IDに移行する方法について説明します。
Azure CLI または Azure portalを使用して、SAS 認証で使用したのと同じイベント ハブ名前空間を使用します。
- 既存のサブスクリプションに使用しているのと同じイベント ハブ名前空間の下に、新しいイベント ハブを作成します。
- URL の前の手順の新しいイベント ハブの名前を使用する以外は、既存のサブスクリプションと同じ詳細を持つ新しいサブスクリプションを作成します。 詳細については、「 サブスクリプションの作成: RBAC の使用」を参照してください。
新しいイベント ハブで通知を受け取ります。 イベント ハブの [メッセージ ] グラフを調べることで、トラフィックが古いサブスクリプションに似ているかどうかを検証できます。 また、通知を受信する際のエラーまたはエラーについても検証します。
通知を受け取り、新しいイベント ハブが正しく動作することを検証したら、古いサブスクリプション、古いイベント ハブ、SAS ベースの認証を削除して、新しいサブスクリプションの使用を開始できます。
通知を受信する
変更通知が Event Hubs によってアプリケーションに配信されるようになりました。 詳細については、Event Hubs ドキュメントで「イベントの受け取り」を参照してください。
アプリケーションで通知を受信するには、「イベント ハブの構成」に記載されている手順と同様に、"リッスン" アクセス許可を持つ別の共有アクセス ポリシーを作成し、接続文字列を取得する必要があります。
ヒント
Azure KeyVault で設定したのと同じ接続文字列を再利用するのではなく、Event Hubs メッセージをリッスンするアプリケーション用の別のポリシーを作成します。 この分離は、ソリューションの各コンポーネントが必要なアクセス許可のみを持っていることを確認することで、最小限の特権の原則に従います。
検証通知の処理
アプリケーションは、新しいサブスクリプションを作成するたびに検証通知を受け取ります。 これらの通知は無視してください。 次の例は、検証メッセージの本文を表します。
{
"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"
}
}
]
}
大きなペイロードを持つリッチ通知のサブスクリプション
Event Hubs の最大メッセージ サイズは 1 MB です。
リッチ通知を使用すると、この制限を超える通知が予想される場合があります。 Event Hubs を介して 1 MB を超える通知を受信するには、サブスクリプション要求に BLOB ストレージ アカウントを追加する必要もあります。
ストレージを設定し、サブスクリプションを作成する
-
ストレージ アカウントを作成します。
-
ストレージ アカウントにコンテナーを作成します。 コンテナー名は、
microsoft-graph-change-notifications
に設定する必要があります。
-
ストレージ アカウントのアクセス キーまたは接続文字列を取得します。
- 接続文字列をキー コンテナーに追加し、名前を付けます。 この値はシークレット名です。
- 次の構文で blobStoreUrl プロパティを含め、サブスクリプションを作成または再作成します。
blobStoreUrl: "https://<azurekeyvaultname>.vault.azure.net/secrets/<secretname>?tenantId=<domainname>"
リッチ通知を受け取る
Event Hubs が 1 MB を超える通知ペイロードを受信すると、通知には、リッチ通知に含まれる リソース、 resourceData、 および encryptedContent プロパティは含まれません。 通知には、代わりに、これらのプロパティが格納されているストレージ アカウント内の BLOB を指す ID を持つ additionalPayloadStorageId プロパティが含まれています。
Microsoft Graph Change Tracking アプリケーションが見つからない場合はどうなりますか?
Microsoft Graph Change Tracking サービス プリンシパルは、テナントの作成時と管理操作によっては、テナントに存在しない可能性があります。 サービス プリンシパルのグローバルに一意の appId が 0bf30f3b-4a52-48df-9a82-234910c4a086
され、次のクエリを実行して、テナントに存在するかどうかを確認できます。
GET https://graph.microsoft.com/v1.0/servicePrincipals(appId='0bf30f3b-4a52-48df-9a82-234910c4a086')
// Code snippets are only available for the latest version. Current version is 5.x
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipalsWithAppId("{appId}").GetAsync();
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
//other-imports
)
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
appId := "{appId}"
servicePrincipals, err := graphClient.ServicePrincipalsWithAppId(&appId).Get(context.Background(), nil)
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ServicePrincipal result = graphClient.servicePrincipalsWithAppId("{appId}").get();
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
<?php
use Microsoft\Graph\GraphServiceClient;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$result = $graphServiceClient->servicePrincipalsWithAppId('{appId}', )->get()->wait();
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
result = await graph_client.service_principals_with_app_id("{appId}").get()
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
サービス プリンシパルが存在しない場合は、次のように作成します。 この操作を実行するには、呼び出し元アプリに Application.ReadWrite.All アクセス許可を付与する必要があります。
方法 1
POST https://graph.microsoft.com/v1.0/servicePrincipals
Content-type: application/json
{
"appId": "0bf30f3b-4a52-48df-9a82-234910c4a086"
}
// Code snippets are only available for the latest version. Current version is 5.x
// Dependencies
using Microsoft.Graph.Models;
var requestBody = new ServicePrincipal
{
AppId = "0bf30f3b-4a52-48df-9a82-234910c4a086",
};
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.ServicePrincipals.PostAsync(requestBody);
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
// Code snippets are only available for the latest major version. Current major version is $v1.*
// Dependencies
import (
"context"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphmodels "github.com/microsoftgraph/msgraph-sdk-go/models"
//other-imports
)
requestBody := graphmodels.NewServicePrincipal()
appId := "0bf30f3b-4a52-48df-9a82-234910c4a086"
requestBody.SetAppId(&appId)
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=go
servicePrincipals, err := graphClient.ServicePrincipals().Post(context.Background(), requestBody, nil)
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
ServicePrincipal servicePrincipal = new ServicePrincipal();
servicePrincipal.setAppId("0bf30f3b-4a52-48df-9a82-234910c4a086");
ServicePrincipal result = graphClient.servicePrincipals().post(servicePrincipal);
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
const options = {
authProvider,
};
const client = Client.init(options);
const servicePrincipal = {
appId: '0bf30f3b-4a52-48df-9a82-234910c4a086'
};
await client.api('/servicePrincipals')
.post(servicePrincipal);
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\Models\ServicePrincipal;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new ServicePrincipal();
$requestBody->setAppId('0bf30f3b-4a52-48df-9a82-234910c4a086');
$result = $graphServiceClient->servicePrincipals()->post($requestBody)->wait();
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
Import-Module Microsoft.Graph.Applications
$params = @{
appId = "0bf30f3b-4a52-48df-9a82-234910c4a086"
}
New-MgServicePrincipal -BodyParameter $params
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
# Code snippets are only available for the latest version. Current version is 1.x
from msgraph import GraphServiceClient
from msgraph.generated.models.service_principal import ServicePrincipal
# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
request_body = ServicePrincipal(
app_id = "0bf30f3b-4a52-48df-9a82-234910c4a086",
)
result = await graph_client.service_principals.post(request_body)
プロジェクトに SDK を追加し、authProvider インスタンスを作成する方法の詳細については、SDK のドキュメントを参照してください。
方法 2
POST https://graph.microsoft.com/v1.0/servicePrincipals(appId='0bf30f3b-4a52-48df-9a82-234910c4a086')
Content-type: application/json
Prefer: create-if-missing
{
"displayName": "Microsoft Graph Change Tracking"
}
関連コンテンツ
-
通知の変更の概要
- 次の Azure Event Hubs クイック スタートをご覧ください。