>100 Views
September 09, 26
スライド概要
API Management とFoundry IQ の ACL を使って、ユーザー別アクセス制御 MCPを実装してみました。
前半で Foundry IQ の概要と ACL の仕組みを整理し、後半で API Managementと Foundry IQ を組み合わせた際の実装の工夫点をご紹介します。
プラットフォームエンジニアです。 セキュリティやSRE、インフラなど多岐にやっています。 趣味はタロット。
APIM × Foundry IQ の ACL を使った ユーザー別アクセス制御 MCP を実装 してみた
目次 1. Foundry IQ の概要と ACL 2. APIM × Foundry IQ の ACL を使ったユーザー別ア クセス制御 MCP 3. ハンズオン紹介
Foundry IQ の概要と ACL
Foundry IQ とは エージェントに 社内データへの許可ベースのアクセスを与える、Azure AI Search 上に構築されたマネージド知識レイヤー 中核となる3つのコンポーネント コンポーネント 役割 Knowledge Base ナレッジソースをまとめる最上位リ ソース。検索の推論強度(reasoning effort)などの挙動を定義 Knowledge Source Blob / SharePoint / OneLake / 既存 Indexなど、実データへの接続 Agentic Retrieval 質問を複数のサブクエリに分解し、 並列実行・リランクして統合回答を 返すエンジン
ACL とは何を指すか Foundry IQ / Azure AI Search は クエリ時にユーザー権限を強 制 し、呼び出したユーザーが閲覧を許可されたドキュメント のみを返す キーとなるのが `x-ms-query-source-authorization` ヘッダー 呼び出し元(エージェント/クライアント)が保持する `search.azure.com` スコープのトークンを そのまま Foundry IQへ転送 「ACL判定のためのユーザー識別情報」として利用される。
x-ms-query-source-authorization を軸に整理 ユーザーコンテキストの伝播 クライアントが取得した `search.azure.com` 向けトークンを、 SDKまたは MCP を経由して AI Search まで無加工で運ぶ Search 側での ACL 判定 `permissionFilterOption: "enabled"` を有効化したインデックスが、トークンの ID を `UserIds` / `GroupIds` / `RbacScope` と突き合わせて絞り込む 認証パススルーとの関係 authorizationヘッダーは、マネージドIDかユーザーのトークンだが、この ACL ヘッダーだけは ユーザー本人のトークンをパススルー させる、二層構造 になっている
`x-ms-query-source-authorization`でデータアクセス制御 が可能なナレッジソース ADLS Gen2 / Blob の POSIX ライクな ACL・RBAC スコープ(今回の実装) Microsoft Purview の機密ラベル(Blob / ADLS / SharePoint / Fabric OneLake) SharePoint (M365) の ACL(サイトグループ含む、インデックス済みコンテン ツ) リモート SharePoint ナレッジソース(Copilot Retrieval API でライブに強制) Fabric Data Agent / Fabric IQ(トークンを Fabric 向けに OBO 交換して問い合 わせ)
APIM × Foundry IQ の ACL を 使ったユーザー別アクセス制御
シーケンス図 API Management(APIM) → Azure Functions → Foundry IQ(AI Search) の主要3ホップに絞って整理
工夫点① 実装まわりの要点 コスト/レイテンシの調整 `reasoning_effort` を明示指定(既定値に任せると課金対象の reasoning tokensが増加) `max_runtime_in_seconds` でサーバー側の検索処理時間に上限を設定 `output_mode=EXTRACTIVE_DATA` は固定とし、回答合成はMCP呼 び出し元(エージェント)に委ねる セキュアコーディング: 例外の詳細はログのみに残し、MCP呼び出し元に は `"Forbidden"` などの固定メッセージだけを返却 秘匿情報の扱い: トークンの有無は `acl_header_present` という真偽値の みを記録し、トークン自体は決してログ/トレースに残さない 部分失敗の可視化: AI Search が一部ナレッジソースの取得に失敗しても 例外にならない(HTTP 206)ため、activity配列を明示的に走査して警告 ログを出す
工夫点② Functions は必ず APIM 経由にする設計 Functions 側は Easy Auth(Entra ID)に加え、アプリケーションロール `Mcp.Invoke` の保持をコード内でチェック このロールを持てるのは次の2者のみ APIM の管理ID(システム割り当てMI) — 本番トラフィックはすべてこ こを通る 運用チームの Entra ID グループメンバー — トラブルシュート用の直接ア クセス(実運用では、PIMと併用を推奨) 通常のエンドユーザーは 必ず APIM を経由 し、Function は「ユーザー本人の トークン」を認可判定には使わない構造
工夫点③ APIM を「トークンブローカー」にする狙い apim-mcp-oauth (次ページ参照)が確立したパターンを踏襲 1. 2. 3. `validate-azure-ad-token` で署名・issuer・audience・有効期限を検証 `authentication-managed-identity` で APIM の MI トークンを取得 `Authorization` ヘッダーを MI トークンに差し替えてバックエンドへ転送 → 前頁で説明したように、バックエンド側では Mcp.Invoke ロールを必ず確認するた め、エンドユーザーが直接バックエンドへ到達する経路は存在せず、呼び出しは常に APIM を経由する設計になる。APIM が認証トークンの検証と差し替えを担う一方で、 ACL 判定に必要なユーザー識別情報だけは` x-ms-query-source-authorization` ヘッダーで 別途運ぶことで、「認可の仲介」と「本人性の伝播」を明確に分離している。
ハンズオン紹介 今回のスライドは、以下ハンズオンシリーズの一部(追加MCP編)です。 1 → 2 →3 の順に既存 APIM 環境の上に積み上げてazd upでデプロイします。 ぜひ試してみてください! 1. https://github.com/apc-n-orita/apim-mcp-oauth : APIM × MCP × OAuth のエンドツーエンド保護の土台。`Mcp.Invoke` ロールと MCPツール別認可のトークンブローカーパターンを構築 2. https://github.com/apc-n-orita/apim-mcp-a2a-oauth : 上記に Microsoft Foundry A2A / 追加 MCP(今回の `foundryiq-acl-mcp`, `Foundry toolbox`)を積み増し 3. https://github.com/apc-n-orita/APICenter : APIM 上の API/Agent/MCP を API Center カタログへ集約・公開