はじめに
Graph API のデルタ クエリを利用すると、ポーリング処理によってテナント内のリソースが変更されたことを検知することができます。この記事ではデルタ クエリについてまとめてみました。
リソースの変更を検知するもう 1 つの方法として変更通知があります。そちらは以下の記事で紹介しています。
デルタ クエリ
デルタ クエリをサポートしているリソース
デルタ クエリをサポートしているリソースは、以下の公開情報に記載されています。
変更通知 よりもサポートしているリソースが少ないですが、デルタ クエリでは Entra ID アプリケーションや サービスプリンシパル といったリソースもサポートされています。
(参考:サポートされているリソース)
https://learn.microsoft.com/ja-jp/graph/delta-query-overview#supported-resources
デルタ クエリの利用方法
デルタ クエリを使用してポーリングによってリソースの変更を検知するには、以下のように Graph API を実行する必要があります。
- 対象のリソースの delta API (/delta) に対してリクエストを送信する
-
@odata.nextLink が返されなくなるまで繰り返しリクエストを送信する
現在のリソースの情報をすべて取得 (同期) します
情報がすべて取得されると @odata.deltaLink が返されます - @odata.deltaLink を使用してリクエストを送信する
-
@odata.nextLink が返されなくなるまで繰り返しリクエストを送信する
前回から変更されたリソースの情報をすべて取得 (同期) します
情報がすべて取得されると @odata.deltaLink が返されます - 一定時間待機し、3 に戻る
変更されたリソースの情報は応答に含まれる @odata.deltaLink に対してリクエストを送信することで取得できます。
@odata.deltaLink を取得するためには、ページング によって @odata.nextLink が返されなくなるまで、すべての情報を取得する必要があります。
(参考:デルタ クエリを使用して、Microsoft Graph データの変更を追跡する)
https://learn.microsoft.com/ja-jp/graph/delta-query-overview
ポーリング処理のフローチャート
デルタ クエリを利用する手順のフローチャートを作ってみました。
ユーザーやグループなどのリソースの場合は、1 のリクエストに "$deltaToken=latest" を付けて実行すると 2 の手順をスキップすることができます。
(参考:デルタ クエリを使用して、Microsoft Graph データの変更を追跡する)
https://learn.microsoft.com/ja-jp/graph/delta-query-overview
ユーザーやグループなどのMicrosoft Entra IDリソースでは、"今からの同期" シナリオがサポートされています。 この機能を使用すると、手順 1 と手順 2 をスキップし (リソースの完全な状態を取得しない場合)、代わりに最新の @odata.deltaLink を要求できます。
@odata.deltaLink の有効期限
対象のリソースによっては @odata.deltaLink に有効期限があり、期限が切れた場合には @odata.deltaLink へリクエストを送信した際に 40x のエラーが返されます。また公開情報にはクラウド側のメンテナンスでも同様にエラーが返されると記載されていました。
このような場合には 1 から再度処理を行う必要があります。
(参考:トークン期間)
https://learn.microsoft.com/ja-jp/graph/delta-query-overview#token-duration
ユーザー情報の変更
例として、指定した間隔でポーリングを行ってユーザー情報の変更を検知する PowerShell スクリプトを作ってみました。
PowerShell へコピー & ペーストして実行した状態で、ユーザーの情報が変更されると内容が表示されます。
ユーザーに割り当てられたライセンスの変更はデルタ クエリでまだ検知できないようです。
(参考:user: delta)
https://learn.microsoft.com/ja-jp/graph/api/user-delta?view=graph-rest-1.0&tabs=http
現在、licenseAssignmentStates プロパティの変更は追跡されません。
スクリプト例
# 対象のリソースの Delta API を指定してください
$DeltaAPI = "/users/delta"
# 特定のプロパティの変更のみを検知したい場合は $select にプロパティを指定してください
# $DeltaAPI = "/users/delta?$select=displayName,jobTitle,mobilePhone"
# 必要なアクセス許可を指定してください
$Scopes = "User.ReadBasic.All"
# ポーリング間隔 (秒) を指定してください
$Interval = 10
# Invoke-MgGraphRequest で'@odata.deltaLink' を取得するためにページング処理を行うコマンド(関数) です
Function Invoke-MgGraphRequestWithPaging($Method, $Uri, $OutputType) {
$responses = @()
$response = Invoke-MgGraphRequest -Method $Method -Uri $Uri -OutputType $OutputType
$responses += $response
# ページング処理を行います
# '@odata.nextLink' が返されなくなるまで情報を取得します
while($response.'@odata.nextLink' -ne $null){
$nextLink = $response.'@odata.nextLink'
$response = Invoke-MgGraphRequest -Method "GET" -Uri $nextLink -OutputType $OutputType
$responses += $response
}
# 取得したレスポンスをすべて返します
return $responses
}
# ダイアログが表示されたらサインインしてください
Connect-MgGraph -Scopes $Scopes
# delta API でページングを行いすべての情報を取得します
$responses = Invoke-MgGraphRequestWithPaging -Method "GET" -Uri "/v1.0/$DeltaAPI" -OutputType "PSObject"
# 最後のレスポンスから deltaLink を取得します
$deltaLink = $responses[-1].'@odata.deltaLink'
# ポーリング処理を開始します (Ctrl-C で停止してください)
while($true){
# deltaLink を使用して情報を取得します
$responses = Invoke-MgGraphRequestWithPaging -Method "GET" -Uri $deltaLink -OutputType "PSObject"
# 変更されたリソースがあれば表示します
$responses | % {echo $_.value | fl}
# deltaLink を新しい URL に更新します
$deltaLink = $responses[-1].'@odata.deltaLink'
# 指定された間隔でポーリングします
Sleep $Interval
}
ユーザーの新規作成
displayName : デルタクエリ テストユーザー
givenName : テストユーザー
surname : デルタクエリ
userPrincipalName : deltatestuser@atsmin.net
id : 9d9c313a-e80e-44fd-a180-0c35d3c4c559
ユーザー情報の変更
デルタ クエリの応答には変更された属性の情報が含まれています。
displayName : デルタクエリ テストユーザー
givenName : テストユーザー
jobTitle : 変更テスト
surname : デルタクエリ
userPrincipalName : deltatestuser@atsmin.net
id : 9d9c313a-e80e-44fd-a180-0c35d3c4c559
ユーザーの削除
id : 9d9c313a-e80e-44fd-a180-0c35d3c4c559
@removed : @{reason=changed}
ユーザーが復元できる状態でも削除されたことが検知されました。ユーザーを復元すると、ユーザーを新規に作成した場合と同様に検知されました。
displayName : デルタクエリ テストユーザー
givenName : テストユーザー
jobTitle : 変更テスト
surname : デルタクエリ
userPrincipalName : deltatestuser@atsmin.net
id : 9d9c313a-e80e-44fd-a180-0c35d3c4c559