Azure AI Foundry で GPT-4.1-mini を使って「ナレッジエージェント」を作成できたのに、VS Code や Postman から呼び出すと 401 Unauthorized になる――この症状は、ほとんどの場合 Entra ID(旧 Azure AD)認証の権限不足が原因です。ポータル上で「作れた」ことと「実行できる」ことは別物なので、RBAC を正しく整える手順をまとめます。
起きていること(症状の整理)
今回のケースは、次のような状況が揃っています。
- Azure AI Foundry で GPT-4.1-mini を選び、ナレッジエージェントを作成
- 対象インデックスとして Azure AI Search のインデックスを指定
- ポータル上ではインデックスもエージェントも正常に作成できているように見える
- しかし VS Code から HTTP リクエストを投げると 401 Unauthorized
- Postman で同じエンドポイントを叩いても 401 Unauthorized
ポイントは、実行クライアントを変えても同じ 401 という点です。コードのミスよりも、認証トークンがサービス側で許可されていない(=RBAC で弾かれている)可能性が高い状況です。
結論:401 の主因は「呼び出し元 ID に AI Foundry へのロールがない」
原因は明快で、リクエストに使用しているプリンシパル ID(例:dd016e2c-8438-42de-b918-d60296c7ef77)に、AI Foundry のモデルへアクセスするためのロールが割り当てられていないことです。
Entra ID 認証(OAuth 2.0 / OpenID Connect)でアクセスしている場合、取得したアクセストークンは「ログインできた」ことは証明しますが、そのリソースを呼べる権限があることまでは保証しません。権限が不足していると、サービス実装によって 401(または 403)で拒否されます。
まず押さえる:401 Unauthorized の意味(Azure でよくあるパターン)
401 は「未認証」と訳されがちですが、Azure の各サービスでは “認証はできたが許可されていない” 状態が 401 で返ることもあります。切り分けを速くするために、まず意味を整理しておきます。
| HTTP ステータス | よくある意味 | 現場で多い原因 | 最初に見るべきポイント |
|---|---|---|---|
| 401 Unauthorized | 認証情報が無い/無効/許可されていない | トークンが無い・期限切れ・aud/scope 不一致・RBAC 未付与 | Authorization ヘッダー、トークン再取得、RBAC |
| 403 Forbidden | 認証はできたが権限が無い | RBAC 不足、ポリシー/ネットワーク制限、Private Endpoint 前提 | ロール割り当て、ネットワーク、ポリシー |
| 404 Not Found | エンドポイントやリソースが違う | URL/リソース名/デプロイ名の誤り、リージョン違い | エンドポイント、リソース名、API パス |
今回のように ポータルで作成できているのに実行だけ 401 の場合、最短ルートは「どの ID で呼んでいるか」と「その ID にロールが付いているか」の確認です。
切り分けの第一歩:どの ID(プリンシパル)で呼び出しているかを確定する
Azure では、同じ “ログイン” に見えても、裏では別の ID で実行されていることがあります。ナレッジエージェントを叩くクライアント(VS Code / Postman / アプリ)がどのパターンかを確定しましょう。
| 呼び出し元の代表例 | トークンの中身(目安) | よくある落とし穴 |
|---|---|---|
| 開発者のユーザー(対話ログイン) | oid がユーザー、upn が出る | 自分にロールが付いていない/別テナントでログインしている |
| サービス プリンシパル(アプリ登録) | appid がアプリ、oid が SP | アプリにロールを付け忘れる/証明書・シークレットの期限切れ |
| マネージド ID(Azure VM/Functions/AKS など) | oid が Managed Identity、発行元は同じ | “有効化” していない/付与したのが別の MI(システム/ユーザー割り当て違い) |
手早い方法は、実際に使っているアクセストークン(JWT)をデコードして、oid / appid を見ることです。Postman でも VS Code でも、取得したトークンを JWT デコーダに貼り付ければ確認できます(社内規定で扱いに注意)。
「プリンシパル ID」が分かっているなら、ほぼ勝ち
今回のように、呼び出しに使っているプリンシパル ID が dd016e2c-8438-42de-b918-d60296c7ef77 と特定できているなら、次にやることは その ID に対して AI Foundry リソースで RBAC を付けるだけです。
AI Foundry に付与すべきロール(最小権限は Cognitive Services OpenAI User)
ナレッジエージェントが GPT-4.1-mini(モデル)を呼び出すには、AI Foundry(または関連する AI リソース)側で RBAC の許可が必要です。付与候補は次のいずれかです。
| ロール名 | 向いているケース | 権限の強さ | 運用上のコメント |
|---|---|---|---|
| Cognitive Services OpenAI User | アプリ/開発者に “呼び出し権限だけ” を与えたい | 最小 | 原則これを第一候補にすると、事故が起きにくい |
| Cognitive Services Contributor | モデルや設定の管理も含めて任せたい | 中 | 開発/検証環境で便利だが、本番では慎重に |
| Contributor | リソース全体の変更権限が必要 | 強い | 切り分け目的で一時的に付与し、解決後に最小権限へ戻すのが安全 |
最小権限で済ませたい場合は、Cognitive Services OpenAI User を付けるのが無難です。まずはこのロールで 401 が解消するかを確認し、足りない場合のみ上位ロールを検討する流れが現実的です。
Azure ポータルでのロール割り当て手順(IAM)
ロール付与は、Azure ポータルから数分でできます。重要なのは「どのスコープに」「どのメンバーへ」付与するかです。
- 対象の AI Foundry リソース を開く(リソース グループではなく、まずはリソース直下が確実です)
- 左メニューから アクセス制御 (IAM) を選択
- ロールの割り当てを追加 をクリック
- 検索ボックスで
Cognitive Services OpenAI User(または必要に応じて他ロール)を検索して選択 - 次へ進み、割り当て先の種類で マネージド ID もしくは ユーザー/グループ/サービス プリンシパル を選択
- メンバーを選択 をクリックし、呼び出しに使っている ID を選ぶ
- 今回のプリンシパル ID に対応するマネージド ID
- または、アプリ(サービス プリンシパル)/実行環境のマネージド ID
- 選択 → 確認および割り当て で完了
よくあるミスは、「エージェントを作った人(自分)」にロールを付けたつもりが、実際はアプリ側のマネージド ID が呼んでいた、というパターンです。プリンシパル ID が分かっているなら、その ID が割り当て対象になっているかを最後に必ず見直してください。
追加チェック:AI Foundry リソースの「ID(Identity)」が有効か
ナレッジエージェントの実行や関連機能でマネージド ID を使う構成の場合、AI Foundry リソース自身のシステム割り当てマネージド ID が 無効だと、後々別の場所で権限エラーが出ることがあります。
- AI Foundry リソース → ID(Identity) を開く
- システム割り当てマネージド ID が「有効」になっているか確認
- 無効なら「オン」にして保存
この設定自体が “今回の 401 の直接原因” とは限りませんが、ナレッジエージェントと周辺サービス(Search、Storage、Key Vault など)を組み合わせるときに、ID が無効のままだと別の箇所で詰まりやすいので、早めに整えておくと安全です。
ロール付与後に必ずやる:トークンを取り直して再実行する
RBAC は付けた瞬間から反映されることもありますが、クライアント側が 古いトークン を握ったままだと、いつまでも 401 が続きます。次の点を意識して “新しいトークン” で再試験してください。
- Postman:Get New Access Token をやり直す(キャッシュされたトークンを再利用しない)
- VS Code / Azure CLI:再ログイン、またはトークン再取得を実行する
- アプリ:トークンキャッシュ(MSAL など)をクリア、または期限切れまで待たず強制更新する
特に Postman は「トークンを取得したつもりでも、同じトークンを使い回していた」ケースがよくあります。401 が消えないときは、Authorization ヘッダーの Bearer トークンが本当に更新されているかを確認すると、ムダな時間が減ります。
(例)Azure CLI でトークンの取り直しを行う場合
実環境の制約に合わせてくださいが、切り分け用としては次のような流れが分かりやすいです。
az login
az account show
# 取得したトークンを使うクライアントに貼り付け直す(またはアプリで再取得)
トークン取得の scope / resource がサービスに合っていないと 401 になります。ナレッジエージェントを叩くときは、サービスが要求するスコープ(例:https://cognitiveservices.azure.com/.default など)になっているかも合わせて確認してください。
それでも 401 が消えないときのチェックリスト
ロール付与が最短解ですが、環境によっては別の要因が混ざることもあります。次の表で順に潰すと、原因特定が速くなります。
| 疑うポイント | 具体的な確認方法 | 対処の方向性 |
|---|---|---|
| エンドポイントが違う | ポータルのエンドポイントと、Postman/コードの URL が一致しているか(リージョン、リソース名、パス) | 正しいホスト名・パスへ修正。環境変数の取り違えも要注意 |
| テナントが違う | ログインしている Entra テナントと、リソースが属するテナントが一致しているか | 正しいテナントでサインインし直す。マルチテナント環境は特に注意 |
| トークンの scope/audience 不一致 | JWT の aud、要求している scope がサービス要件に合っているか | Postman の OAuth 設定/アプリの MSAL 設定を修正 |
| 別の ID で実行している | 実際のトークンの oid/appid と、想定しているプリンシパル ID が一致するか | 正しい ID にロール付与。ローカル開発は “自分”、本番は “MI” など混在しがち |
| ネットワーク制限 | Private Endpoint/IP 制限/ファイアウォール設定の有無 | 許可ネットワークから実行する。閉域設計の場合は踏み台や VNet 経由にする |
| ロール付与のスコープがズレている | リソースではなく別スコープ(別サブスク、別 RG)に付けていないか | AI Foundry リソース(または正しい親スコープ)で付け直す |
今回の前提(VS Code でも Postman でも 401)に当てはまる場合、「別の ID で実行している」と「ロール付与のスコープがズレている」が、次に多い落とし穴です。
ナレッジエージェントで見落としやすい関連設定:Azure AI Search 側の権限
401 が解消してエージェントの呼び出し自体が通るようになると、次に出やすいのが「検索インデックスへアクセスできない」系のエラーです。ナレッジエージェントは Azure AI Search を裏で参照するため、構成によっては Search 側にも RBAC が必要です。
| 対象 | 必要になりやすいロール例 | 症状 | 対処 |
|---|---|---|---|
| Azure AI Search(インデックス参照) | Search Index Data Reader(参照のみ) | 検索が空になる/取得で失敗する | エージェント(または実行 ID)に Search 側ロールを付与 |
| Azure AI Search(インデックス更新もする) | Search Index Data Contributor | 取り込みや更新が失敗する | 更新が必要な場合のみ Contributor 系を付与 |
今回の主題は AI Foundry 側の 401 ですが、ナレッジエージェントは “複数サービスの権限が連鎖” します。AI Foundry に入れたから終わりではなく、Search 側も必要最小限で整えると、運用が安定します。
再現・検証のやり方:最小のリクエストから段階的に増やす
トラブルシュートでは、いきなり複雑なプロンプトや検索条件を入れず、最小のリクエストで「認証が通るか」を確認すると早いです。
- まずは “エージェントを呼べるか” だけを確認(401 が消えるか)
- 次に、ナレッジ参照(Search)を有効にして “検索できるか” を確認
- 最後に、本番相当のプロンプトやパラメータへ戻す
HTTP クライアントを問わず、確認すべき最低限はこの 2 点です。
- Authorization: Bearer <access_token> が付いているか
- そのトークンが、ロール付与後に新規取得されたものか
(例)リクエストを作るときの見落としポイント
実際のエンドポイントやボディは環境で異なりますが、見落としやすいのは次のような点です。
- ヘッダーのスペルミス(Authorization ではなく Authorisation など)
- Bearer の後のスペースが欠けている
- 環境変数で URL を切り替えているが、開発/本番が混ざっている
- プロキシや API Gateway がヘッダーを落としている
運用で効くベストプラクティス(“401 を二度と出さない” 設計)
最後に、同じ事故を繰り返さないための運用ポイントをまとめます。ナレッジエージェントは便利ですが、権限設計が雑だと “いつの間にか動かない” 状態になりがちです。
| 観点 | おすすめ | 理由 |
|---|---|---|
| 最小権限 | まず Cognitive Services OpenAI User から始める | 不要な変更権限を与えない。監査や事故対応が楽 |
| 環境分離 | Dev/Stg/Prod で別 ID(MI/SP)を使う | 誰が何を呼んだか追いやすく、漏えい時の影響範囲も限定できる |
| ロール管理 | 人に直接付けず、グループまたは IaC(Bicep/Terraform)で管理 | 属人化を避け、再現性を担保できる |
| 変更の手順化 | ロール変更後は必ずトークン再取得→疎通確認を手順に入れる | “付けたのに直らない” を防ぐ。キャッシュ問題を潰せる |
今回のケースでも、ロール付与とトークン再取得を行うことで、実際に 401 が解消しリクエストが正常に通るようになった、という報告があります。ポータルで作れたからといって、実行権限が自動で付くわけではありません。呼び出し元 ID と RBACをセットで設計することが、Azure AI Foundry 運用の最短コースです。
まとめ
- VS Code と Postman の両方で 401 なら、コードより 認証・権限(RBAC)を疑う
- 原因は「プリンシパル ID に AI Foundry へのロールが無い」ことが多い
- 最小権限なら Cognitive Services OpenAI User を AI Foundry リソースに割り当てる
- 付与後は必ず 新しいトークン を取り直して再実行する
- 次の段階として Azure AI Search 側の RBAC も合わせて整えると安定する

コメント