使用 Amazon Bedrock AgentCore Gateway 為多租户代理實現代理令牌交換
本文詳細介紹瞭如何利用 Amazon Bedrock AgentCore Gateway 和 Identity 實現 OAuth 2.0 令牌交換(RFC 8693),以解決多租户代理中下游 API 調用時的身份傳播問題和 confused deputy 問題。通過參考實現 TravelBot,展示了在 Okta 環境下的完整設置、JWT 聲明轉換以及如何通過受眾綁定實現深度防禦。
在將生成式 AI 代理部署到多租户生產架構中時,您會面臨一個特定的身份問題:當代理代表用户調用下游 API 時,誰的身份隨調用傳遞?以代理的服務身份運行調用會破壞審計追蹤,因為每個下游系統都必須無條件信任該代理。直接轉發用户的令牌而不做更改,則會使得每個下游工具成為混亂的代理(confused deputy)。當單個代理面對多個租户且用户在工具調用時並不在場時,這兩種選擇都無法擴展。
OAuth 2.0 令牌交換規範(RFC 8693)正是為了解決這個問題,Amazon Bedrock AgentCore Identity 原生支持將其作為憑證提供者授權類型。這篇博文是實施指南,它完整地演示了針對 Okta 的多租户 OBO 設置,展示了每個跳轉點的 JSON Web 令牌(JWT)聲明轉換,並説明了受眾綁定如何產生可跨租户擴展的深度防禦。
參考實現 TravelBot 是一個多租户預訂助手,服務於兩個示例租户(Acme 和 Globex)。該參考實現將在發佈後於 aws-samples/sample-obo-flow-poc 倉庫中提供。
OBO 模式在代理面對多個下游服務或租户且入站令牌的受眾與任何單個下游 API 的受眾不同時至關重要。對於單租户代理,如果入站受眾已經匹配下游服務,則直接轉發令牌可能就足夠了。本文其餘部分聚焦於多租户場景。
AgentCore Identity 中的代理令牌交換介紹
Amazon Bedrock AgentCore Identity 支持 OAuth 2.0 令牌交換(RFC 8693)作為原生憑證提供者授權類型。憑藉此能力,AgentCore Gateway 可以在調用下游工具之前透明地將入站用户令牌交換為新的受眾綁定令牌,而無需代理本身實施交換。
此能力提供以下好處:
- 身份跨租户邊界傳播:即使受眾隨租户變化,原始調用者的身份也能通過 sub 聲明端到端保留。
- 密碼學最小權限:每個下游調用攜帶一個通過 aud 聲明綁定到單個下游服務的令牌。為一個租户頒發的令牌不能用於另一個租户。
- 無代理端交換邏輯:代理代碼獲取單個入站令牌並調用工具,AgentCore 執行每次交換。
- 基於標準:實施基於 RFC 8693 令牌交換授權。支持相同授權類型和兼容請求形狀的授權服務器可以作為憑證提供者。
AI 代理中的混亂代理問題
考慮一個處理來自多個租户用户的“顯示我的預訂”等請求的代理。有三種實現選擇,只有一種是正確的:
- 服務賬户模擬:代理以自身身份認證,並在請求頭或路徑參數中聲明用户身份。每個下游 API 都必須無條件信任代理。被攻破的代理可以針對任何租户模擬任何用户。這是典型的混亂代理。
- 直接用户令牌轉發:代理重用入站用户令牌調用下游 API。這僅當入站令牌的受眾已經匹配下游 API 時才有效。在多數系統中很少成立。
- 代理令牌交換:代理的授權中介將入站主題令牌交換為新令牌,其 sub 為原始調用者,aud 為下游 API,簽名來自下游 API 信任的授權服務器。結果是一個加密作用域到單個下游調用、代表單個用户的令牌。
OBO 是唯一能端到端保留用户身份、在受眾邊界強制執行最小權限、併產生下游 API 可獨立驗證且無需信任代理的令牌的選擇。實施 RFC 8693 需要代理運行時、授權服務器和下游 API 之間的協調。Amazon Bedrock AgentCore Gateway 和 AgentCore Identity 消除了這種協調負擔。Gateway 攔截工具調用,識別目標租户,並在下游調用發出前指示 Identity 針對租户的授權服務器執行交換。
模擬與代理令牌交換對比
在 OBO 交換中,入站令牌的 sub 聲明被保留,而 aud 聲明被重寫為下游服務。交換的執行者記錄在單獨聲明中(RFC 8693 中的 act,Okta 中的 cid),因此下游 API 可以通過單個令牌回答兩個問題:代表誰執行操作?(sub 聲明)以及誰在執行操作?(actor 聲明)。授權決策應基於 sub,審計日誌和速率限制決策應基於 actor。
解決方案概述
本文使用以下標識符引用 TravelBot 參考中的特定 Okta 資源:
- TravelBot Provider:發出入站 JWT 給代理的 Okta 授權服務器。
- ACME Travel API:為 Acme 租户鑄造 OBO 令牌的 Okta 授權服務器。
- Globex Travel API:為 Globex 租户鑄造 OBO 令牌的 Okta 授權服務器。
- TravelBot Agent Client:用於代理機器對機器路徑的 Okta API 服務應用。
- TravelBot User Client:用於三方登錄的 Okta OIDC 應用。
- AgentCore Delegate:AgentCore Identity 用來執行令牌交換的 Okta 應用憑證。
TravelBot 參考實現使用 Okta 作為交換雙方。一個 Okta 授權服務器(TravelBot Provider)認證代理,另外兩個(ACME Travel API 和 Globex Travel API)為每個租户鑄造 OBO 令牌。所有三個都是 Okta 自定義授權服務器。Okta 內置的組織授權服務器不支持自定義受眾或作用域,無法服務此模式。
相同的角色可以由其他身份提供商扮演。由於 RFC 8693 是在授權服務器層實現的,支持令牌交換授權的其他授權服務器可以應用相同架構。AgentCore Identity 發送的請求形狀(subject_token_type, audience, actor-token 存在性以及客户端認證方法)通過 customParameters 映射按憑證提供者設置,因此適應不同 IdP 是配置更改而非代碼更改。
架構組件
架構包含六個組件:
- 提供者授權服務器:發出入站 JWT,在 TravelBot 中是 TravelBot Provider。
- AgentCore Gateway:驗證入站 JWT,將工具調用路由到正確租户目標,並編排 OBO 交換。
- AgentCore Identity:持有委託客户端憑證並針對租户授權服務器執行 RFC 8693 令牌交換。
- 每個租户的授權服務器:為每個租户的受眾鑄造 OBO 令牌。在 TravelBot 中,ACME Travel API 和 Globex Travel API 是兩個獨立的 Okta 授權服務器,各有其受眾和訪問策略。
- 每個租户的 API 表面:一個 Amazon API Gateway HTTP API,每個租户有一個 JWT 授權者。每個授權者驗證發行者、受眾和所需作用域,提供防止跨租户令牌重用的最後防線。
- 租户業務邏輯:一個 AWS Lambda 函數,接收驗證後的 OBO 令牌並讀取聲明以做出租户特定決策。它從 per-user authorized_scopes 聲明強制執行寫權限,並將預訂存儲在按 sub 聲明分區的 Amazon DynamoDB 中,因此用户只能讀取自己的記錄。
請求流程
工作流包括以下步驟:
- 用户通過三方 authorization_code 登錄在提供者授權服務器處認證,代理收到入站 JWT,受眾綁定到 Gateway。
- 代理通過模型上下文協議(MCP)調用工具,將入站 JWT 作為 bearer 令牌呈現。
- Gateway 檢索提供者的 JWKS,驗證 JWT 簽名,並確認受眾匹配 travelbot-provider。
- Gateway 選擇與 Acme 目標關聯的憑證提供者,並向 Identity 請求 OBO 令牌。
- Identity 向 Acme 的授權服務器發送 RFC 8693 令牌交換請求。主題令牌是入站 JWT,請求的受眾是 https://api.acme-travel.example。
- Okta 驗證 Acme 的授權服務器信任提供者(通過可信服務器關係),然後為請求的受眾(Acme Travel API)鑄造新的 JWT,其中 sub 設置為原始用户,actor 設置為 AgentCore Delegate 客户端 ID。
- Gateway 將新令牌注入到對 Acme 預訂 API 的調用中。
- 下游 API 驗證 OBO 令牌的受眾和簽名,然後基於 sub 聲明執行授權。
這種配置確保每個租户的授權服務器獨立頒發令牌,且令牌只能用於其預期的 API,從而提供深度防禦。任何跨租户令牌重用嘗試都會因受眾或簽名驗證失敗而被拒絕。