このエントリは2024/04/30現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
問い合わせ
以下の2エントリを読んでくれたお初の人からのお問い合わせ。
いま、Blob storageのREST APIの認証周りの手間を軽くするために、API Management(以下APIM)を挟むことを検討している。以前のエントリを読んで、Managed Identityを使う方法はよく理解できたが、資格情報マネージャーも利用可能なのだろうか?資格情報マネージャーを使うとどんないいことがあるのか。
「ユーザー委任かそうでないか、の違いだと思うのだが」という言葉は飲み込みつつ、果たしてどうなのか、ということで試してみた(自分の理解のため、と言い聞かせる)。結論から言うと、利用可能ではあるが、Azureリソースに対して使う場合にはManaged Identityのほうが便利かつ簡単である。
資格情報マネージャーについて
先ほどのエントリにも記載の通り、OAuth 2.0での認可が必要なバックエンドサービスに対して、トークンを取得したり、更新したりしてくれるもの。
API 資格情報と資格情報マネージャーについて / About API credentials and credential manager
https://learn.microsoft.com/azure/api-management/credentials-overview
Authorization code grant flow、Client credential grant flowのいずれかを利用できるが、それぞれで当然挙動が異なる。
| 種類 | 誰の権限・ロールを使うか | 想定ユースケース |
|---|---|---|
| Authorization code grant flow | User impersonation(言葉の意味はユーザー偽装だが、ユーザー委任がしっくりくる)なので、APIを呼び出すユーザーの権限でアクセスする。 | Webアプリ(UIでの操作など) はじめて操作する場合には、権限を付与するか否かの同意が必要 |
| Client credential grant flow | クライアントアプリの権限・ロールでアクセスする。Microsoft Entra IDの場合、アプリの登録(App registrations)で登録したアプリのService Principalに付与した権限・ロール。 | バックエンドアプリ(UIの操作無し) |
今回は、Put Blobを使った操作をラップしたAPIの作成を通じて説明することにした。Blob REST APIのPut BlobのReferenceは以下を参照。
Put Blob
https://learn.microsoft.com/rest/api/storageservices/put-blob?tabs=microsoft-entra-id
API作成のために、以下の作業が必要である。
- Microsoft Entra ID
- アプリ登録
- シークレットの作成
- APIの許可
- Blob storage
- コンテナーに対する権限付与(RBAC)
- APIM
- 資格情報マネージャーへの登録
- APIの作成
作業は以下のチュートリアルとほぼ同じ。Graph API固有の部分以外はそのまま使える内容である。以下ではStorage APIに特化した部分を加えつつ、備忘録として記載しておく。
資格情報マネージャーの構成 – Microsoft Graph API / Configure credential manager – Microsoft Graph API
https://learn.microsoft.com/azure/api-management/credentials-how-to-azure-ad
1. Microsoft Entra IDでの作業
アプリの登録
Authorization code grant flow、Client credential grant flowのいずれを使う場合でも、アプリを登録する必要がある。今回はMicrosoft Entra IDに登録するため、Entra ID>アプリの登録(App registrations)を選択し、下表に従って設定しておく。
| 項目 | 設定内容 |
|---|---|
| 名前 (Name) | 任意 |
| アカウントの種類 (Supported account types) | Single tenant |
| リダイレクトURI (Redirect URI) | https://authorization-manager.consent.azure-apim.net/redirect/apim/{APIMサービス名} |

作成すると、Client IDが生成され、表示されるので、メモしておく(この値は後からでも確認できる)。
シークレットの作成
アプリのPrincipal作成完了後、シークレットを作成する。Certificates & secrets > Client secrets を選択し、New client secretをクリックすると、Add a client secretという画面がAzure Portalの右側に現れるので、Descriptionと期限を設定して【Add】(追加)をクリックする。するとシークレットが現れるが、このシークレットは再表示できないので、必ずメモを取っておくこと。


APIの許可(API Permissions)
どのAPIのどのスコープを使えるようにするか、を設定する。まず【Add permission】をクリックし、Azure Portal右側に現れる画面から、【Azure storage】を選択する。


API許可のリクエスト画面が現れるので、user_impersonationにチェックを入れて、【Add permissions】を選択。このスコープは管理者による同意が不要なので、管理者に作業依頼する必要はない。

これで、Microsoft Entra IDでの作業はおしまい。
2. Blob storageでの作業
Storage accountを作成し、Blob containerを作成しておく。名前は何でもよい。Blob container作成後、Blob containerにRBACを構成する。付与するロールはStorage Blob Data Contributorロールだが、Authorization code grant flowでユーザー委任する場合と、Client credential grant flowで構成する場合では、付与対象のプリンシパルが異なる点に注意。
| 種類 | 付与するロール | 付与するプリンシパル |
|---|---|---|
| Authorization Code grant flow | Storage Blob Data Contributorロール | 登録したアプリ 操作を委任するユーザーアカウント |
| Client credential grant flow | Storage Blob Data Contributorロール | 登録したアプリ |
BLOB データにアクセスするための Azure ロールを割り当てる / Assign an Azure role for access to blob data
https://learn.microsoft.com/azure/storage/blobs/assign-azure-role-data-access?tabs=portal
これで、Blob storageに対する作業はおしまい。
3. APIMでの作業
資格情報マネージャを使って資格情報プロバイダと接続を作成する。APIs > Credential manager (資格情報マネージャ)を選択し、Create(作成)をクリックして資格情報プロバイダを作成する。

必須項目には、アスタリスクが付いているのですぐわかるはず。

入力にあたっての注意点は以下。
| 設定項目 | ポイント |
|---|---|
| Tenant ID | Microsoft 365を管理しているMicrosoft Entra IDと、Azureサブスクリプションを管理しているMicrosoft Entra IDが異なる場合は、明示的にIDを指定するのが吉(無用なエラーに悩まされなくて済む) |
| Authorization URL | https://login.microsoftonline.comでよい |
| Resource URL | 今回はBlob storageなので、Blob storageのエンドポイントを指定する。Blob containerを含むFQDNは不要。 https://<Storage account名>.blob.core.windows.net/ |
| Scopes | 登録済みアプリで構成していれば、自動的に選択してくれるので、記載不要 |
このあと、接続の確認をして、問題なければ、資格情報マネージャでの作業はおしまい。
APIの作成
資格情報マネージャで取得したアクセストークンをHTTP Headerに設定する必要がある。以前のエントリでも記載したが、Provider IDとAuthorization IDはそれぞれ資格情報プロバイダ名、接続名である点に注意。


<policies>
<inbound>
<base />
<get-authorization-context provider-id="{プロバイダ名}" authorization-id="{接続名}" context-variable-name="auth-context" identity-type="managed" ignore-error="false" />
<set-header name="Authorization" exists-action="override">
<value>@("Bearer " + ((Authorization)context.Variables.GetValueOrDefault("auth-context"))?.AccessToken)</value>
</set-header>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Put blobの操作に必要なHTTP Headerもつけておく必要がある。これらはAuthorization code grant flowとClient credential grant flowの操作に共通するので、All Operationsスコープで構成している。
<policies>
<inbound>
<base />
<set-header name="x-ms-version" exists-action="override">
<value>2024-05-04</value>
</set-header>
<set-header name="x-ms-blob-type" exists-action="override">
<value>BlockBlob</value>
</set-header>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
これでAPI Managementでの作業はおしまい。
Let’s try!
Authorization code grant flowの場合、ユーザー委任による操作なので、最初にAPIにアクセスする際に同意(Consent)を求められる(管理者がすでに同意していればその限りではない)。アクセスに使ったBearerトークンを見ると、ユーザー情報が含まれているのに対し、Client credential grant flowの場合は操作を委任していないので、当然ながらユーザー情報は含まれず、登録したアプリのClient IDがJWTのappIdに入っている(さすがにスクリーンショットはご勘弁を)。
どちらのフローを使うべきか?
Client credential flowはバックエンドで利用する(ユーザーによる操作が入らない)ことを想定したものであるため、操作を委譲したユーザーを追跡する必要がない場合には、シンプルに構成できる。
対してAuthorization code grant flowは、「ユーザーによる操作の委任」という形でAPIを実行できる。そのため、Webアプリケーションでユーザーの操作が発生するようなケースと相性がよい。さらに、委任元(操作を委任したユーザー)をバックエンドAPIで取得できるなら、操作委任証跡として利用する、つまり誰がその操作を実施したのか、を追跡するための証跡としても利用できる(実際に操作を立証するには、複数の証跡を合わせて立証することになるだろうが)。
Managed Identityを使って同じことはできないのか?
可能だが、一部制限がある。まず、Managed IdentityはMicrosoft Entra IDで登録されたアプリのように利用可能なプリンシパルである。
Azure リソースのマネージド ID とは / What are managed identities for Azure resources?
https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/overview
このManaged Identityは、Azureをスコープとしており、Microsoft 365などはスコープ外。そのため、バックエンドサービスとしてAzureリソースを活用するようなAPIを作成する場合、APIMのManaged Identityを使ったアクセスのほうがシンプルで、わざわざ
- Microsoft Entra IDでアプリを登録
- 資格情報マネージャで認証を構成し、接続を作成
という作業がなくなるのはその通り。ただし、スコープ外のリソース(Microsoft 365や3rdパーティーAPI)に対しては使えないため、資格情報マネージャを使うしかない。