Azure Event Grid REST APIの呼び出し

このエントリは2022/05/26現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。

問い合わせ

例によって以下のような問い合わせが届いた。

Azure ADに登録したアプリケーションから、Event Gridに対してイベントを発行させようとしていて、SDKでの動作は確認した。理解のため、Event GridデータプレーンのREST APIを使って挙動を確認したいのだが、どうしてもアクセストークンの取得がうまくいかない。どうしたらよいか?

問い合わせ主が呼び出しにあたって使っていたコードを拝見したところ、以下のようだった。

# (1)-a Azure ADに登録したアプリを利用
curl -X POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token \
 -F grant_type=client_credentials \
 -F client_id=${​​​​​​​​APP_ID}​​​​​​​​ \
 -F client_secret=${​​​​​​​​CLIENT_SECRET}​​​​​​​​ \
 -F scope={登録したアプリケーションIDのURI}/.default

# (1)-b Managed identitiesを利用
curl -g "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://eventgrid.azure.net" -H "Metadata: true"

# (2) REST APIを呼び出す
curl -X POST https://<EventGrid topicのエンドポイント>?overload=EventGridEvent&api-version=2018-01-01 \
-H "Content-Type: application/json" \
-H "Authorization: bearer {(1)-a/bで取得したアクセストークン}" \
-d '{データ}'

たぶん詳しい方は「おや?」と思われたかもしれない。

どこに問題があったのか?

問題は3件。

  1. Managed Identitiesを使う方法だと問題なくアクセストークンを取得できるのだが、登録アプリのときに設定されたスコープに問題があった。基本的に、スコープはトークンを取得したいリソースを指定する必要があるが、この指定だと、登録したアプリのアクセストークンを自身が取りに行く、というよくわからないことになってしまう。
  2. REST APIのURLが異なっていた。REST API Referenceによると、Topicホスト名を指定するような記載があるが、実際にはTopicエンドポイントを指定しなければならない。
  3. PublishするAPIのデータが配列ではなかった。これはREST API Referenceに明記されているが、1件だけなので配列ではなくJSONをそのまま送りつけたよう。

Publish Event Grid Events – Publish Event Grid Events
https://docs.microsoft.com/rest/api/eventgrid/dataplane/publish-event-grid-events/publish-event-grid-events
要求本文 / Request Body
https://docs.microsoft.com/rest/api/eventgrid/dataplane/publish-event-grid-events/publish-event-grid-events#request-body

REST APIの呼び出しのお作法

REST APIを使う流れは以下のような感じ。

  1. Managed Identityを構成、もしくはAzure ADにアプリケーションを登録
  2. Event GridにてRBACを構成
    • EventGrid データ送信者/ EventGrid Data SenderロールをService PrincipalやManaged Identityに付与
  3. クライアントはAzure ADに対する認証を実施し、アクセストークンを取得。このとき、スコープやリソースはトークンを取得したいリソースを指定する。
    • 登録アプリの場合、スコープは https://eventgrid.azure.net/.default を指定
    • Managed Identitiesの場合、リソースは https://eventgrid.azure.net を指定
  4. 取得したアクセストークンをBearerトークンとして設定し、REST APIを呼び出す
    • 配信イベントは配列として渡す(1個でも配列として渡す)。配列で渡さないとBad Request (HTTP 400) と以下のようなエラーメッセージが返ってくる。
{
    "error": {
        "code": "BadRequest",
        "message": "This resource is configured to receive event in 'EventGridEvent' schema. The JSON received does not conform to the expected schema. Token Expected: StartArray, Actual Token Received: StartObject. Report 'ab484c09-3292-408b-9daa-4a1843001031:3:5/26/2022 2:17:35 AM (UTC)' to our forums for assistance or raise a support ticket.",
        "details": [{
            "code": "InputJsonInvalid",
            "message": "This resource is configured to receive event in 'EventGridEvent' schema. The JSON received does not conform to the expected schema. Token Expected: StartArray, Actual Token Received: StartObject. Report 'ab484c09-3292-408b-9daa-4a1843001031:3:5/26/2022 2:17:35 AM (UTC)' to our forums for assistance or raise a support ticket."
    }]
  }
}

対策

上記の流れを以下のように修正してガイドした。

# (1)-a Azure ADに登録したアプリを利用
curl -X POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token \
 -F grant_type=client_credentials \
 -F client_id=${​​​​​​​​APP_ID}​​​​​​​​ \
 -F client_secret=${​​​​​​​​CLIENT_SECRET}​​​​​​​​ \
 -F scope=https://eventgrid.azure.net/.default

# (1)-b Managed identitiesを利用
curl -g "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://eventgrid.azure.net" -H "Metadata: true"

# (2) REST APIを呼び出す
curl -X POST https://<EventGrid topicのエンドポイント>?overload=EventGridEvent&api-version=2018-01-01 \
-H "Content-Type: application/json" \
-H "Authorization: bearer {(1)-a/bで取得したアクセストークン}" \
-d '[{データ} の配列]'

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中