iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
AI Security

Microsoft Foundry 的 AI Agent 攻防實戰:建立高資安與可治理的 Agent 系統系列 第 18 篇

Day 18|Microsoft Foundry 的 AI Agent 攻防實戰:Azure Owner 不是宇宙萬能管理員,Foundry RBAC 到底管哪一層?

  • 分享至 

  • xImage
  •  

前兩天已分開「誰在呼叫」與「代表誰操作」。今天把這些 principal 放進角色與 scope,確認每一層究竟允許什麼。

工程司的 platform admin 能部署資源,不代表程式就能替他讀 Search 或 Key Vault。這次要重現的漏洞就在本機 executor:看到 control plane 的 Owner,便把其他資料平面的操作一起放行。

管理者在測試裡叫 platform-owner,和業務使用者 Alice 分開。下面依序比較 Foundry、Search、Key Vault,再核對 scope。測試只操作本機角色資料,沒有向 Azure 指派角色。

角色要搭配 Principal、Plane 與 Scope

  • RBAC:以角色決定某個 principal 在特定 scope 能做什麼;角色名稱很大,不代表能跨越所有 scope 與資料平面。
  • Control plane/Data plane:前者管理資源設定,後者讀寫資源內的資料。能建立 Key Vault,不代表能讀取 vault 裡的 secret。
  • Actions/DataActions:Azure role definition 分別描述控制平面與資料平面的操作。
  • Scope:角色生效的資源邊界,例如 subscription、resource group、project 或單一資源。授權鍵還必須綁 immutable tenant 與 object ID,不能只比對容易碰撞的顯示名稱。

用四個授權平面建立對照

Control plane assignment

先讓 control-plane 的 platform-owner 分別要求部署、呼叫 Agent、搜尋與讀取 secret。

platform-owner 在 control/foundry/search/keyvault 四種 request 上的矩陣。

這份 control assignment 只允許 deploy,另外三個資料平面的請求都得到 RBAC_DATA_ACTION_DENIED,摘要與呼叫次數也一併保留。以下四張矩陣都使用本機合成角色,沒有模擬完整的 Azure RBAC,也沒有量測真實環境的有效權限。

Foundry data-plane assignment

換成 Foundry User,再送出相同的四種請求。

Foundry User 對 deploy、invoke、search、secret 的四格矩陣。

這份 foundry-data assignment 只允許 invoke_agent,部署、Search 與 Key Vault 的請求都被拒絕。可以看到,本機政策沒有把 Foundry 的資料權限沿用到其他平面。

Search data-plane assignment

接著用 Search Index Data Reader,檢查四種請求的結果。

Search Index Data Reader 的四格 cross-plane matrix。

search-data assignment 只允許 search;deploy、invoke_agent、read_secret 都被拒絕。讀取 Search 的權限沒有一起變成其他服務的權限。

Key Vault data-plane assignment

最後換成 Key Vault Secrets User,比較同一組請求。

Key Vault Secrets User 的四格 cross-plane matrix。

keyvault-data assignment 只允許 read_secret,另外三個動作都被拒絕。四張圖要一起看,才能確認各平面的權限沒有被混用。

authorization_plane_matrix_evidence() 讓四個合成 principal,分別帶著 control、Foundry、Search、Key Vault assignment,對四種請求產生 16 個結果。這份矩陣還沒有執行工程司的業務 PEP;費用單的 owner 與金額限制,是接上應用程式後仍要檢查的另一層。

Microsoft Foundry 的 authentication 文件把 control plane 與 data plane 明確分開:resource、project、model deployment 與 connection 建立屬於控制平面;建立 Agent、evaluation、tracing 等工作則屬資料平面。Azure RBAC role definition 以 Actions 表達 control-plane 操作,以 DataActions 表達 data-plane 操作。Foundry authentication and authorization

在工程司案例中,還要再加上 connected resources 與業務政策:

Azure control plane
├─ 建立 Foundry resource/project
├─ 部署模型與建立 connection
└─ 建立 role assignment、network resource

Foundry data plane
├─ 建立/更新 Agent
└─ 呼叫指定 Agent endpoint

Connected-resource data plane
├─ Search query
└─ Key Vault secret get

Magic Panda business PEP
└─ subject × tenant × canonical object × action × state

各層可能都使用 Entra 身分,但處理的資源不同。Foundry Agent Consumer 不包含工程司費用的 owner、核准限額或採購狀態;endpoint 存取通過後,業務 PEP 仍要檢查這筆交易。

重現 Owner 被錯誤套用到其他平面

Flat Owner:Search data attack

回到有漏洞的 Owner 判斷,先比較 Search 修補前後的結果。

flat Owner 修補前後的 Search data-plane 比較。

Search 在修補前得到 allowed/LEGACY_OWNER_SPANS_DATA_PLANE,修補後則是 denied/RBAC_DATA_ACTION_DENIED。external_calls=0 是本機資料中的宣告值;這組合成角色沒有描述 Azure Owner 的完整實際權限。

Flat Owner:Key Vault attack

同一個漏洞也用讀取 Key Vault secret 再測一次。

flat Owner 修補前後的 secret read 比較。

read_secret 從 allowed 變成 denied,Receipt 由 1 張降為 0。cloud_calls=0 仍是本機宣告值;這筆結果只說明範例 executor 的修補,不能用來推論 Azure Owner 的完整權限。

如果前面接聊天介面,管理者可能只會要求:「剛部署完,幫我跑一下供應商連線檢查。」今天先略過模型如何理解這句話,直接檢查 executor 收到操作後怎麼授權。

本篇故意不拿模型能否把這句話翻成工具呼叫來評分,而是直接測 executor 的授權邊界。vulnerable profile 的錯誤不在 Azure 服務端,也不在 user message,而在本機 executor:只要 assignments 中看到同一 principal 在 control plane 擁有 Owner,舊版 _rbac_decision() 就把它推成其他 plane 的 allow。於是 platform-owner 原本只在合成 subscription control plane 擁有 deploy,卻被舊 executor 放行去讀 Key Vault secret。read_secret、target scope 與預期結果都由測試框架提供,不塞回對話裡提示答案。

先呼叫 stage API 重現這個結果:

from magic_panda_agent.stages.day18 import flat_owner_attack_evidence

evidence = flat_owner_attack_evidence()
search, keyvault = evidence["comparisons"]

assert search["before"]["reason_code"] == "LEGACY_OWNER_SPANS_DATA_PLANE"
assert keyvault["before"]["reason_code"] == "LEGACY_OWNER_SPANS_DATA_PLANE"
assert search["after"]["reason_code"] == "RBAC_DATA_ACTION_DENIED"
assert keyvault["after"]["reason_code"] == "RBAC_DATA_ACTION_DENIED"

其中 Key Vault 的 before outcome 是:

{
  "action": "read_secret",
  "actor": "platform-owner",
  "allowed": true,
  "resource_id": "/vault/magic-panda/secrets/vendor-token",
  "reason_code": "LEGACY_OWNER_SPANS_DATA_PLANE",
  "receipt_count": 1,
  "side_effect_count": 0,
  "details": {
    "plane": "keyvault-data",
    "rbac_enforced": false
  }
}

這次沒有連接 Azure Key Vault。結果指出的是本機 executor 錯把角色名稱套用到其他平面,不能據此推論 Azure 服務端的 Owner 可以直接讀取 secret。

同一類錯誤也會發生在 Foundry:Microsoft 官方角色表顯示,Azure Owner/Contributor 具有大量控制平面能力,卻不因此取得 Foundry project 的 build/develop DataActions 或 Agent endpoint interaction。只需呼叫 Agent 的 consumer,應使用 Foundry Agent Consumer,不必升成 Foundry User。Foundry RBAC

檢查完整授權條件與 Scope 邊界

Scope:child 與 lookalike

再比較真正的子資源,以及只有字串前綴相似的 scope。

合法 child scope 與 lookalike prefix 的對照。

child_scope=allow,lookalike_scope=RBAC_DATA_ACTION_DENIED。名稱看起來像,不代表它位於同一個資源範圍。這裡的 external_calls=0 沒有網路觀測器,下面兩張 scope 圖也沒有涵蓋 Azure deny assignments、PIM、權限傳播或條件運算式。

Scope:traversal 與 foreign tenant

接著檢查帶有路徑跳脫與外租戶資訊的 scope。

path traversal 與跨 tenant scope 的拒絕。

traversal_scope 與 foreign_tenant 都被拒絕,Receipt 為 0。cloud_calls=0 是本機宣告值;可以確認的是這兩筆請求未通過本機 scope 檢查。

本機 RoleAssignment 不以角色名字直接決定一切,而是把授權輸入固定為:

tenant + principal + plane + role + scope

執行時再帶入 action + target_scope:

from magic_panda_agent.stages.day18 import RoleAssignment, rbac_allows

assignments = (
    RoleAssignment(
        principal="platform-owner",
        plane="control",
        role="Owner",
        scope="/subscriptions/synth",
        tenant_id="bamboo-hq",
    ),
    RoleAssignment(
        principal="vault-agent",
        plane="keyvault-data",
        role="Key Vault Secrets User",
        scope="/vault/magic-panda",
        tenant_id="bamboo-hq",
    ),
)

assert rbac_allows(
    assignments,
    principal="platform-owner",
    tenant_id="bamboo-hq",
    plane="control",
    action="deploy",
    scope="/subscriptions/synth/resourceGroups/lab",
)

assert not rbac_allows(
    assignments,
    principal="platform-owner",
    tenant_id="bamboo-hq",
    plane="keyvault-data",
    action="read_secret",
    scope="/vault/magic-panda/secrets/vendor-token",
)

Scope 按完整 path segment 比對。例如 /vault/magic-panda 可以涵蓋真正的子資源,卻不能涵蓋 /vault/magic-panda-evil 或含 .. 的路徑。Assignment、decision、Receipt 與 audit event 也保留 tenant,避免不同租戶剛好使用同一 principal alias 就共用權限。

這仍只是 deterministic policy fixture,不是 Azure RBAC emulator。它的用途是讓「不能跨 plane 推導」成為 regression contract;真實 Azure allow/deny 必須另外執行。

Foundry built-in role 怎麼選

前面四格矩陣使用本機 assignment 資料,適合先抓出「Owner 被誤當成所有 data role」的程式錯誤。到 Foundry 實測時,則要用不同 principal 對同一個 Agent endpoint 做允許與拒絕,並分開測 Search、Key Vault 的 data plane;一個 Azure 200 不能替四個平面一起蓋章。應用程式自己的費用授權仍用同一張 canonical transaction 對照。

核心角色可先依 persona 拆成:

Persona 建議 Foundry role/scope 仍需另外處理
只呼叫 Agent 的 FastAPI/使用者 Foundry Agent Consumer,project 或個別 Agent scope 使用者業務授權、下游 OBO
建立與測試 Agent 的開發者 Foundry User,project scope;resource 另給必要 Reader 外部 Search/KV data role
管理 project 與發布工作的負責人 Foundry Project Manager,依官方要求選 scope 不自動取得業務核准權
resource/account 管理者 Foundry Account Owner/經審查的管理角色 不自動讀下游資料
production Agent runtime 該 Agent 自己的 Agent identity(新模型建立時就有) 目標資源最小 DataActions

Owner 沒有因此直接取得所有 DataActions,但擁有廣泛 role-assignment 能力的人可能替自己或他人加上 data role。正式環境仍要用 PIM、條件/deny assignment、權限定期覆核與 separation of duties 控制這條間接升權路徑。

Microsoft 正在把舊的 Azure AI User/Owner/Account Owner/Project Manager 名稱改為 Foundry ...。官方建議 IaC 使用 role definition ID,避免 rollout 期間顯示名稱不一致;目前兩個常用 ID 為:

Foundry Agent Consumer  eed3b665-ab3a-47b6-8f48-c9382fb1dad6
Foundry User            53ca6127-db72-4b80-b1b0-d745d6d5456d

Role definition ID 可以避免顯示名稱更動造成的比對問題,但內建角色內容仍可能更新。發布紀錄需要一起保存 role ID、查閱日期、有效 scope 與實際操作結果。

兩份官方文件對 Foundry Project Manager 能否管理模型的說明不完全一致:5 月版 authentication 文件與 7 月版 RBAC 矩陣有落差。這裡採較新的矩陣作為規畫依據,實際部署仍要依 deployment type、operation 與 assignment scope 檢查允許和拒絕的結果。

Agent scope 只證明 endpoint access

Foundry 支援在個別 Agent scope 指派角色,適合表達「consumer 能呼叫 Agent A,不能呼叫 Agent B」。但官方文件目前明確限制:agent-scope assignment 只針對 agent endpoint access 評估,不會授予 broader control-plane 或 management permission。Agent-scope role assignments

雲端 matrix 因此至少要有:

Principal Operation Target 預期
Consumer A endpoint interaction Agent A allow
Consumer A endpoint interaction Agent B deny
no-role principal endpoint interaction Agent A deny
Consumer A Agent write/publish operation Agent A deny
developer principal 同一 write operation/payload Agent A allow

同一個 write request 還要由 developer principal 執行一次。這個合法對照成功,才能把 Consumer 的拒絕歸因到權限,排除 endpoint、API version 或 payload 本身出錯。

需要在實際環境指派 Agent-scope Consumer 時,可依官方 scope 格式填入自己的參數:

az role assignment create \
  --assignee-object-id "$PRINCIPAL_OBJECT_ID" \
  --assignee-principal-type ServicePrincipal \
  --role "eed3b665-ab3a-47b6-8f48-c9382fb1dad6" \
  --scope "$AGENT_RESOURCE_SCOPE"

不要把 subscription ID、tenant ID、object ID 或完整 resource scope 放進文章截圖。

外部 Search 與 Key Vault 不會跟著 connection 自動授權

Search + Key Vault combined assignment

先同時給 Search 與 Key Vault 的資料角色,確認兩種操作都能通過。

同時具備兩個 data-plane assignment 時的 search/read-secret allow。

assignment_set=both 時,search 與 read_secret 都得到 RBAC_ALLOW,因為兩份角色是明確指派的。connection_object_exercised=false;以下三張圖都沒有建立或呼叫 Foundry connection,也沒有測量 Azure 的有效權限。

Search-only assignment

拿掉 Key Vault 角色,只保留 Search,再做相同兩個操作。

Search-only principal 對 search 與 read_secret 的分離。

search_only 可以 search,卻不能 read_secret。external_calls=0 是合成資料的宣告值;這筆對照確認本機政策沒有把 Search 角色套用到 Key Vault。

Key-Vault-only assignment

反過來只留 Key Vault 角色,看看 Search 是否仍被拒絕。

Key-Vault-only principal 對 search 與 read_secret 的分離。

keyvault_only 的 search 被拒絕,read_secret 則通過,cloud_calls=0 為本機宣告值。這和上一張一起說明兩種角色各自生效,沒有互相借用權限。

downstream_role_separation_evidence() 讓同一個 downstream-runtime 依序使用 both、search_only、keyvault_only 三組 assignment,得到六個結果。用這個對照,可以確認本機 executor 沒有把 Search 與 Key Vault 的角色混用;這裡沒有建立 Foundry connection。

Foundry connection 解決的是平台如何找到與連接資源;Azure AI Search 與 Key Vault 仍有自己的 data plane、角色、網路與稽核。至少要分開測:

  • Search query:對應的 Search data role,加上 Day 15 的 server-derived tenant filter。
  • Key Vault secret read:runtime principal 使用 Key Vault Secrets User。
  • Key Vault Contributor:控制平面管理,不等於可以讀 secret value。
  • Agent 下游存取:角色指派到實際使用的 Agent identity 或明確 connection identity,不用 Agent 名稱猜 principal。

最後還要進大魔術熊貓工程司的 PEP。Alice 即使可呼叫 Agent endpoint,也只能操作自己被授權的 canonical object;Azure 200 只表示這一層通過。

Foundry Project 是開發資產與 RBAC scope,不是完整的 SaaS tenant boundary。bamboo-hq 與 moon-rabbit-lab 若共用 project,Day 15 的 server-derived tenant filter、cache partition、by-ID read check 與業務 PEP 一項都不能拿掉。

讓合法操作與相鄰的拒絕一起重跑

下面先跑四個平面與 scope 的本機測試。它們用來檢查程式的授權條件,沒有呼叫真實 Agent endpoint。

進入 day18/ 後執行:

uv run pytest tests/stages/day18/test_acceptance.py -q

這組驗收要確認:

  • 四個已實作 plane 的 4×4 runtime matrix 只有四個 matching tuple allow。
  • legacy Owner 對 Search 與 Key Vault 都錯誤 allow,fixed executor 對兩者都 deny。
  • platform-owner 可以在 control plane deploy。
  • 同一個 Owner 不能被推導成 Search reader 或 Key Vault secret reader。
  • 只有 scope 相符的 vault reader 能讀指定 secret reference。
  • lookalike 與 traversal-like scope 都 fail closed。
  • 同一 workload 的 Search-only 與 Key-Vault-only assignments 只允許各自的 plane。
  • before profile 的跨 plane allow 產生 receipt;after profile 得到 RBAC_DATA_ACTION_DENIED 且 receipt 為 0。
  • cumulative replay 中 Day 16 workload identity 與 Day 17 delegated context 仍在,Day 19 secret rotation 尚未偷跑。

本機測試記錄為 7 passed。畫面分別讀取 authorization_plane_matrix_evidence()、flat_owner_attack_evidence()、scope_matrix_evidence() 與 downstream_role_separation_evidence() 的回傳值。Helper 的 external/cloud calls 固定為 0,沒有網路觀測器,因此這些結果仍只涵蓋本機 RBAC fixture。

角色與群組變更後,重新確認有效權限

group 成員、role definition、scope inheritance、緊急指派、舊 Agent 換成新模型後拿到的新 identity,以及 migration 都可能改變 effective permission。剛建立 assignment 後得到的 403 也可能只是 propagation delay;CI 應使用 bounded retry 並標記 timeout,不能固定睡幾秒就把它當成穩定 deny。

NIST SP 800-207/800-207A 關心的是 principal 對特定 resource 與 operation 的當次決策。對大魔術熊貓工程司來說,角色名稱只是輸入之一;plane、scope、operation、business object 與實際副作用要一起留下 evidence。

下一篇把同一組 principal 用到 Key Vault,接著檢查 secret 換版後,adapter、cache 與輸出紀錄還會不會用到舊值。

第一方參考資料


上一篇
Day 17|Microsoft Foundry 的 AI Agent 攻防實戰:三張識別證都是真的,Agent 為什麼仍替 Alice 越權?
下一篇
Day 19|Microsoft Foundry 的 AI Agent 攻防實戰:Secret 搬進 Key Vault,舊影印本為什麼還能用?
系列文
Microsoft Foundry 的 AI Agent 攻防實戰:建立高資安與可治理的 Agent 系統 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言