使用 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,從而提供深度防禦。任何跨租戶令牌重用嘗試都會因受眾或簽名驗證失敗而被拒絕。