1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RBACだけでは足りない。AIエージェントの権限は「委任」と「自律」で考える ~ Entra ID で OBO を検証

1
Last updated at Posted at 2026-11-08

Entra ID で AI エージェントに ID を持たせよう! ~ Foundry × Claude で検証(その1)、(その2) で Entra ID で AI エージェントに ID を付与し、ロールを付与しました。いわゆる RBAC (ロールベースのアクセス制御) です。
IMG_3618.JPG

1. AI エージェントのセキュリティを考える

AI エージェントは業務効率を大きく向上させる一方で、エージェント自体が意図しない操作をしたり、攻撃者に悪用されるリスクが指摘されています。

AI エージェントはあなたに寄り添った口調で回答をくれるけれど、残念ながら人ではありません。

  • 動作が非決定的: 同じ指示でも毎回同じ行動をとらないことがある
  • 他人の意図で動くことがある: 読み込んだデータに指示が埋め込まれている場合、その指示に従ってしまう (プロンプトインジェクション、Confused deputy problem)
  • 高速、そして大量: 処理が速いため、被害が高速に拡大する

AI エージェントに与える権限は、「モデルが正しく振る舞うこと」を前提とせず、誤動作しても被害が限定される範囲で考える必要があります。

RBAC が決めるのは、「何ができるか」のみです。エージェントに権限を設計するには、さらに「誰の代わりに動くのか」と「人の承認なしにどこまで動くのか」という 2 つの問いが残ります。本記事では、これを「委任」と「自律」の 2 軸として整理していきます。

2. 権限モデルの 2 つの軸: 委任と自律

「誰の代わりに動くのか」が委任、「人の承認なしにどこまで動くのか」が自律となります。

例えば、Mail.Read という権限で、「委任されたアクセス許可」ならサインインしたユーザーの代わりに動き、そのユーザー自身のメールだけを読めます。
「アプリケーションの許可」として付けるとエージェントは自分の権限として動き、テナント全員のメールが読めるようになります。
01.jpg

自律の軸は、また別の話になります。例えば、読んだメールをもとに返信するとき、送信前に確認を挟むのか、エージェントが自分の判断で送ってしまうのか -- 同じ権限であっても、この設計によって誤動作したときの被害は大きく変わります。

ではこの 2 つの軸が実際にどのようなものか、具体的に紹介していきたいと思います。
まずは、「委任」です。アプリケーションを登録して、委任されたアクセス許可でどのような動きになるかを確認します。
「自律」については、次回の公開で書きたいと思います。
IMG_3603.JPG

3. 検証: 委任 (On-Behalf-Of)

3-1: アプリ登録と設定

同意設定

テナント全体の同意設定を行います。ユーザーの同意設定は、ユーザーが自分の判断でアプリに委任アクセス許可 (delegated permission) を与えられる範囲を決める設定です。
同意を制御する設定は複数あり、組み合わせで挙動が変わります。今回は「ユーザーの同意を許可しない」 + スコープを「管理者のみ」 + Azure CLI を承認済みクライアントに登録という構成とします。
(スコープと承認済みのクライアントは、後のアプリ登録の手順で設定します)

この設定は、テナント内のすべてのユーザーとアプリに影響します。また、変更には特権ロール管理者などの権限が必要です。

設定の詳細については、Microsoft が公開するドキュメントを参照してください。

  1. Azure portal にサインインし、[Microsoft Entra ID] を選択します
  2. 左ペインにて [エンタープライズアプリケーション] を選択します
    02.jpg
  3. 左ペインにて [セキュリティ] - [同意とアクセス許可] を選択し、左ペインで [ユーザーの同意設定] を選択します
    03.jpg
  4. 「ユーザーの同意を許可しない」を選択し、[保存] をクリックします
    04.jpg
ユーザーの同意設定の選択肢について

ユーザーの同意を許可しない
アプリに同意を付与する権限を含むディレクトリロールを持つユーザーだけが新しいアプリに同意できます。一般ユーザーは同意画面で先に進めず、管理者の承認が必要となります。
こちらを選択すると、新しい SaaS や Graph 連携ツールを使うたびに管理者対応が必要になりますが、同意フィッシング (illicit consent grant) のリスクを大きく下げられます。

検証済みの発行元からのアプリに対して、選択したアクセス許可についてユーザーの同意を許可する
確認済みの発行元のアプリ、またはこの組織に登録されているアプリに限り、「低影響」と分類されたアクセス許可について、すべてのユーザーが同意できます。
「低影響」と分類するアクセス許可は [アクセス許可の分類] で設定します。

Microsoft による同意設定の管理を許可する (推奨)
Microsoft が管理する同意ポリシーを適用する方式で、どのアクセス許可を危険とみなしてブロックするかを Microsoft が脅威動向に応じて随時更新します。
※ ある程度危険なアクセスはブロックできると想定できますが、ユーザーの組織の基準と一致するとは限らないため、準拠要件がある場合は他の選択肢を検討してください。

  1. 左ペインにて [管理者の同意設定] を選択します
  2. [管理者の同意要求] で「いいえ」を選択し、[保存] をクリックします
    05.jpg
    • はい: ユーザーは同意画面から承認を要求でき、管理者がレビューします ※ レビュー担当者 (ユーザー・グループ・ロール) の指定も必要になります
    • いいえ: ユーザーは「管理者の承認が必要です」と表示されて止まります

今回は検証のため、管理者の同意要求は「いいえ」とします。本番環境などでユーザーの同意を止める場合は、ユーザーが管理者に承認を要求できるよう「はい」にしておくなどもご検討ください (止めるだけでは、業務が止まる、シャドー IT に流れるなどの原因になります)

アプリケーションの登録

次に検証に使うアプリケーションを登録します。

  1. Azure portal にサインインし、[Microsoft Entra ID] を選択します

  2. 左ペインにて [管理] - [アプリの登録] を選択します

  3. [新規登録] をクリックします
    06.jpg

  4. [名前] に任意の名前を入力します ※ ここでは agent-api

  5. [サポートされているアカウントの種類] では今回は「シングルテナントのみ - 既定のディレクトリ」を選択しました

  6. [登録] をクリックします
    07.jpg

API の公開

アプリケーションを登録したら、このアプリケーションを API (リソース) として公開するための設定を行います。具体的には、アプリケーション ID URI と、クライアントが要求するスコープ (委任されたアクセス許可) を定義します。

  1. [Microsoft Entra ID] - [管理] - [アプリの登録] - [すべてのアプリケーション] タブから、作成した「agent-api」を選択します
  2. 左ペインにて [概要] を選択し、[アプリケーション (クライアント) ID] を控えておきます
  3. 左ペインにて [管理] - [API の公開] を選択します
  4. [アプリケーション ID の URI] には api://<手順 2 で控えた ID> がデフォルトで入力されています。[保存してから続ける] をクリックします
    ※ この手順は初回のみです
  5. [Scope の追加] をクリックします
  6. [スコープ名] に任意の名称を入力します ※ ここでは access_as_user
  7. [同意できるのは誰ですか] では以下のうちいずれかを選択します ※ ここでは「管理者のみ」
    • 管理者とユーザー: ユーザーが同意できるかどうかをテナントの同意設定に従います
    • 管理者のみ: テナントの設定に関係なく、このスコープは常に管理者の同意が必要です
  8. [管理者の同意の表示名]、および [管理者の同意の説明] に任意の表示名、説明を入力し、[状態] で「有効」を選びます
  9. [スコープの追加] をクリックします
管理者の同意の表示名・説明について
  • 管理者の同意の表示名: 管理者がこのスコープに同意すると、スコープは同意画面でこのように呼ばれます
  • 管理者の同意の説明: テナント管理者が同意画面でスコープを展開するときに表示される、スコープに関する詳細な説明です

承認済みクライアントアプリケーションの追加

今回の検証では Microsoft Azure CLI をクライアントとして使用してアクセストークンを取得します。そのため、作成した agent-api に Azure CLI を承認済みクライアントアプリケーションとして追加します。承認済みクライアントとして登録すると、Azure CLI がこのスコープのトークンを要求したときにユーザーへの同意画面が表示されなくなります。
Microsoft Azure CLI のクライアント ID は「04b07795-8ddb-461a-bbee-02f9e1bf7b46」です。

  1. agent-api の [管理] - [API の公開] を開きます
  2. [承認済みクライアントアプリケーション] セクションで [クライアントアプリケーションの追加] をクリックします
  3. [クライアント ID] に「04b07795-8ddb-461a-bbee-02f9e1bf7b46」を入力し、[承認済みのスコープ] で作成したスコープを選択します
  4. [アプリケーションの追加] をクリックします

Microsoft Graph の委任されたアクセス許可

次に、agent-api がユーザーの代理で Microsoft Graph を呼び出せるよう、委任されたアクセス許可を追加します。OBO ではトークン交換の途中で同意画面を表示できないため、事前に管理者の同意を与えておく必要があります。

  1. agent-api の [管理] - [API のアクセス許可] を開きます
  2. デフォルトで Microsoft Graph の「User.Read」が追加されています。ない場合は [アクセス許可の追加] をクリックし、[Microsoft Graph] - [委任されたアクセス許可] で「User.Read」にチェックを入れ、[アクセス許可の追加] をクリックします
  3. [<テナント名> に管理者の同意を与えます] をクリックし、[はい] をクリックします

クライアントシークレットの作成

最後に、agent-api が自分自身を証明するための資格情報を作成します。(その2)ではフェデレーション資格情報(FIC)を設定しましたが、FIC は Azure のマネージド ID など、信頼した発行元のトークンが必要です。ローカル PC からはこのトークンを取得できないため、今回の検証ではクライアントシークレットを使用します。

  1. agent-api の [管理] - [証明書とシークレット] を開きます
  2. [クライアント シークレット] タブで [新しいクライアント シークレット] をクリックします
  3. [説明] に用途が分かる名前を入力します ※ ここでは obo-test
    ※ 空欄のままにすると「Password uploaded on <日付>」という名前になり、後から何のためのシークレットか分からなくなります
  4. [有効期限] で「カスタム」を選択し、検証期間に合わせて短い期間を設定します
  5. [追加] をクリックします
  6. 一覧の「値」列に表示された文字列をコピーします
    ※ 値は作成直後にしか表示されません。隣の「シークレット ID」ではなく「値」をコピーしてください

本番環境ではシークレットを使わず、FIC や証明書を使用してください。検証が終わったら、作成したシークレットは必ず削除してください。

3-2: 検証

では、どのようにユーザーが取得したトークンを AI エージェントが使用するのか検証していきます。
IMG_3596.JPG

  1. PowerShell を起動します

  2. 変数をセットします

    $CLIENT_ID = "xxx"
    $TENANT_ID = "xxx"
    

    ※ [Microsoft Entra ID] - [管理] - [アプリの登録] - [agent-api] - [概要] で確認します

  3. ログインします

    az login --tenant $TENANT_ID --allow-no-subscriptions
    
  4. ログインしたユーザーを確認するには以下を実行します

    az ad signed-in-user show --query "{upn:userPrincipalName, id:id, name:displayName, type:userType}"
    
  5. ログインしたユーザーとして、agent-api 宛てのトークン(トークン A)を取得します

    $TOKEN_A = az account get-access-token --scope "api://$CLIENT_ID/access_as_user" --query accessToken -o tsv
    
  6. agent-api のシークレットを入力します。シークレットはコマンドに直接書かず、Read-Host で入力します(直書きすると、コマンド履歴やスクリーンショットに残るため)

    $SECRET = Read-Host "シークレットの値" -AsSecureString | ForEach-Object { [System.Net.NetworkCredential]::new("", $_).Password }
    

    「シークレットの値:」と表示されたら、3-1 の最後の手順でコピーした値を貼り付けます

  7. OBO のトークン交換リクエストを作成します

    $body = @{
      grant_type          = "urn:ietf:params:oauth:grant-type:jwt-bearer"
      client_id           = $CLIENT_ID
      client_secret       = $SECRET
      assertion           = $TOKEN_A
      scope               = "https://graph.microsoft.com/User.Read"
      requested_token_use = "on_behalf_of"
    }
    
    パラメーター 意味
    grant_type 手元の JWT を別のトークンに交換する申請であること
    requested_token_use 交換の目的が「ユーザーの代理」であること。これで OBO になります
    assertion 交換の元になるユーザーのトークン(手順 5 のトークン A)
    client_id / client_secret 申請者が agent-api 本人であることの証明
    scope 交換後に欲しい権限(Graph の User.Read)
  8. Entra ID のトークンエンドポイントにリクエストを送り、Graph 用のトークン(トークン B)を受け取ります

    $res = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" -Body $body
    $TOKEN_B = $res.access_token
    

    ※ 結果は $res に入るため、2 行目でトークン部分を $TOKEN_B に取り出します。この行を忘れると、次の手順で 401 エラーになります

  9. トークン B を使って Graph を呼び出します

    Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/me" -Headers @{ Authorization = "Bearer $TOKEN_B" }
    

    手順 3 でログインしたユーザーの情報が返れば成功です。agent-api が、ユーザー本人として Graph にアクセスできたことになります。

4. OBO 交換の記録

Entra 管理センターのサインインログ([ユーザーのサインイン (非対話型)] タブ)には OBO 交換の記録が残ります。ユーザーは自分、アプリケーションが登録アプリケーション (ここでは agent-api)、そして使用したリソース (ここでは Microsoft Graph) が記録されます。
アクティビティがユーザー本人によるものか、エージェント経由かを判断するには、このログのアプリケーションを確認します。

5. OBO の落とし穴と対策

今回の検証で、OBO の動作を確認しました。
OBO は「誰の権限で動くか」を保ちますが、それだけでは守れない穴があります。OBO の落とし穴と対策を以下にまとめます。

# 落とし穴 発生し得るリスク 主な対策
1 ユーザーの権限を背負う たとえば User.ReadWrite.All を持つエージェントは、一般ユーザーなら自分のプロフィール、管理者なら全ユーザーを変更できる スコープを最小限にする / 特権アカウントではエージェントを使わない
2 ユーザーが自分で同意できてしまう 設定次第で一般ユーザーが委任スコープに同意できる (同意フィッシングの温床となる) [エンタープライズアプリケーション] - [同意とアクセス許可] でユーザー同意を制限し、管理者同意のワークフローを使う
3 範囲は守れても、意図は守れない 正当な権限の範囲内で、本人が望まない操作が実行される (プロンプトインジェクション) 送信系スコープ (Mail.Send など) は必要なときだけに制限。送信・削除の前に人間の承認。Prompt Shields で検出
4 監査ログで「本人がやった」ように見える oid は本人なので操作もユーザー名義で残り、本人かエージェントかの切り分けが難しい サインインログやリソースのアクティビティログ (この検証では Microsoft Graph) などでユーザーだけでなく呼び出し元のアプリ ID まで確認する

今回はここまでです。
次回は「自律」について書きたいと思います。
IMG_3609.JPG

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?