用 Okta Cross App Access 与 Amazon Bedrock AgentCore 治理 AI 智能体访问(上篇)
Govern AI agent access with Okta Cross App Access and Amazon Bedrock AgentCore – Part 1
Okta Cross App Access 与 Amazon Bedrock AgentCore 组合,可在 IdP 侧管控 AI 智能体代表哪个用户在哪个应用内行动。
一个 AI 代理更新工单或读取客户记录时,是在该人员可访问的应用程序内代表其行事。随后,你的身份团队必须回答一个按应用 OAuth 授权和共享服务账户无法回答的问题:哪个代理可能在哪个应用中代表哪个用户行事,以及如何阻止它。Okta Cross App Access (XAA) 在你的身份提供商 (IdP) 中回答了这个问题。你在 Okta 中注册代理,管理员批准它可能访问的应用程序,Okta 在代理每次请求代表用户行事时评估策略。在我们的测试中,管理员移除用户对代理的分配后,Okta 在大约 1 秒内拒绝了代理为该用户发出的新请求,已签发的令牌在 5 分钟内过期。
Amazon Bedrock AgentCore 是一个平台,可使用任何框架或模型大规模构建、连接和优化代理。此解决方案使用其两项能力在 AWS 上执行 Okta 的决策。Amazon Bedrock AgentCore runtime 是 Amazon Bedrock AgentCore 的一项能力,负责验证 Okta 的授权。Amazon Bedrock AgentCore Identity 是 Amazon Bedrock AgentCore 的一项能力,使用你的代理代码看不到的凭证将其兑换为短期访问令牌,并将该令牌保存在其令牌保管库中。在我们的测试中,AgentCore Identity 为端到端耗时约 30 秒的请求增加了约 0.6 秒。
在本系列两篇文章的第一篇中,你将在 AgentCore runtime 上构建一个任务代理,通过 XAA 和 AgentCore Identity 代表已登录用户行事。你将配置它所需的 AgentCore Identity 部分,在工具中强制执行每个用户的权限,并了解我们测量的结果:每项检查拒绝什么、我们最终采用的做法,以及 Okta 的控制措施生效速度有多快。第 2 部分随后将同样的治理置于 Amazon Bedrock AgentCore Gateway(Amazon Bedrock AgentCore 的一项能力)之后,使用 Cedar 策略、Amazon Elastic Kubernetes Service (Amazon EKS) 上的第二个代理,以及 Amazon CloudWatch 中的审计跟踪。
解决方案概述
Okta 是治理平面:它决定哪个代理可能代表哪个用户、针对哪个资源行事。AgentCore Identity 是执行平面:它持有代理的凭证,将 Okta 的决策转换为资源接受的令牌,并将两个身份都保留在该令牌中。在图 1 中,代理及其调用的两个 Model Context Protocol (MCP) 服务器都运行在 AgentCore runtime 上。
图 1:解决方案架构,编号与后续步骤对应
每个请求携带三个令牌,每个令牌记录不同的决策:ID 令牌说明用户是谁,Identity Assertion JWT Authorization Grant (ID-JAG) 是 Okta 的决策,访问令牌是资源所接受的内容。一个请求的流程如下:
- 用户通过代理关联的 Okta 应用,使用 OpenID Connect 登录 Web 前端(即前端后端,BFF)。
- 对于每个请求,BFF 在 Okta 的组织授权服务器上以代理身份进行身份验证(RFC 8693 令牌交换),将用户的 ID 令牌兑换为 ID-JAG。Okta 检查代理是否处于活动状态、用户是否已分配给该代理,以及管理员是否已将其连接到目标授权服务器以获取所请求的范围。ID-JAG 是一次性的,并在 5 分钟后过期。
- BFF 以 ID-JAG 作为持有者令牌,在 AgentCore runtime 上调用代理。运行时的 JWT 授权器仅接受 Okta 签发给此代理的 ID-JAG。
- 运行时从 AgentCore Identity 获取一个工作负载访问令牌,该令牌将智能体的工作负载身份与用户绑定,并将其传递给智能体代码。此工作负载访问令牌是 AWS 内部的绑定令牌:Okta 和资源都看不到它,因此它不属于那三个令牌之一。
- 智能体向 AgentCore Identity 请求访问令牌。AgentCore Identity 以智能体身份通过 JWT 授权授予(RFC 7523)在资源的 Okta 自定义授权服务器上兑换 ID-JAG。Okta 返回一个 5 分钟有效的访问令牌,该令牌同时标明用户和智能体,并携带用户的组信息。
- 智能体使用该令牌调用 MCP 服务器。任务管理器检查该令牌是否由已注册的智能体获取,以及用户的组和范围是否允许使用该工具。
图 2 以时序图形式展示了同一请求,以及各方所做的检查。
图 2:三令牌链及各方所做的检查,其中第 4 步的工作负载访问令牌保留在 AWS 内部
先决条件
要跟随本教程操作,你需要以下内容:
| 先决条件 | 我们使用的配置 |
| 一个可访问 Amazon Bedrock AgentCore 且 Amazon Bedrock 中可使用 Anthropic Claude 模型的 AWS 账户 | 美国西部(俄勒冈) |
| 一个启用了 AI 智能体跨应用访问和 API 访问管理(自定义授权服务器)的 Okta 组织 | 一个 Okta Integrator Free Plan 组织 |
| Python、AWS 命令行界面(AWS CLI)、boto3、AgentCore CLI 以及 AgentCore Python SDK(Amazon Bedrock AgentCore 的一项能力) | Python 3.11、AWS CLI 版本 2、boto3 1.43、AgentCore CLI 0.31.1 和 AgentCore Python SDK 1.24.1 |
| AWS Identity and Access Management(IAM)权限 | 创建 AgentCore 资源和 IAM 角色的权限 |
本演练大约需要 1 小时。AgentCore 按使用量收费。请参阅 Amazon Bedrock AgentCore 定价。
本解决方案的基础是 GitHub 上 AgentCore 示例仓库中的 AWS 示例 08-okta-xaa-delegation-chain,你可以在此基础上构建本文所述的解决方案。除该示例外,本文中的代码片段和配置仅从概念上展示该模式。它们并非完整、可部署的解决方案。该代码为示例代码,仅供非生产用途,因此在部署前请与您的安全和法务团队合作,以满足您组织的安全、监管和合规要求。
在 Okta 中注册智能体
Okta 需要为资源提供授权服务器、为智能体提供授权服务器、建立两者之间的连接,并制定允许智能体授予的策略。请在 Okta 管理控制台中完成所有这些步骤:注册智能体会创建其关联应用,因此你无需使用应用集成向导。
- 为资源应用程序创建一个自定义授权服务器,受众为
api://task-manager,自定义范围为xaa:read和xaa:write。仅请求资源的自定义范围:Okta 会拒绝包含 OpenID Connect 范围(如openid或profile)的 ID-JAG 请求(invalid_scope),因此请求需要至少一个自定义范围且不包含 OpenID Connect 范围。 - 向其访问令牌添加一个
groups声明,筛选出以xaa-开头的组。该声明将每个用户对工具的权限传递下去。 - 在管理控制台中,转到 Directory > AI Agents,选择 Register AI agent,然后选择 Register manually,可选地分配所有者,并创建一个关联的 OpenID Connect 应用。在 Client registration 中,选择 Client secret,生成密钥,然后激活该代理。代理和应用共享同一个客户端 ID,并且该应用必须为你的用户登录:来自其他应用的 ID 令牌会导致交换失败,并提示“the client application is not registered for delegation to this agent.”
- 在代理的 Resource connections 选项卡上,将其连接到授权服务器,并限制为其所需的作用域,如图 3 所示。
- 向自定义授权服务器添加一条访问策略规则,允许代理的 JWT Bearer 授权,访问令牌有效期为 5 分钟。如果没有该授权类型,第二次交换会失败并返回
no_matching_policy,而有效期限制了被撤销的委托能继续工作多长时间。 - 分配可能通过该代理操作的用户或组。他们通过关联应用登录,因此请为该应用设置应用登录策略,允许他们使用已注册的身份验证器登录。在我们的沙盒组织中,关联应用有自己的策略,其中包含针对测试组的规则。对于真实用户,请应用你组织的策略,包括多因素身份验证。
图 3:Okta 中任务代理的资源连接,限制为 xaa:read 和 xaa:write 作用域
Okta 的 Cross App Access 指南 涵盖了控制台步骤,AWS 示例 08-okta-xaa-delegation-chain 则通过脚本配置授权服务器及其 JWT bearer 策略。然后 BFF 以代理身份进行身份验证,请求 ID-JAG:
POST /oauth2/v1/token HTTP/1.1
Host: YOUR-ORG.okta.com
Authorization: Basic <the agent's client ID and secret>
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&requested_token_type=urn:ietf:params:oauth:token-type:id-jag
&subject_token=<the user's ID token>
&subject_token_type=urn:ietf:params:oauth:token-type:id_token
&audience=https://YOUR-ORG.okta.com/oauth2/YOUR-CUSTOM-AS-ID
&scope=xaa:read xaa:writeAWS 示例 06-okta-xaa 在 Python 中发送相同的请求(agent/xaa_client.py)。BFF 以代理身份进行身份验证,因此请将代理的客户端密钥存储在 AWS Secrets Manager 中,而不是代码或配置文件中。
设置 AgentCore Identity
AgentCore Identity 为此解决方案保存三项内容,你的代理代码看不到客户端密钥,也不会调用 Okta 的令牌端点:
| AgentCore Identity 的组成部分 | 它保存的内容 | 由谁创建 |
| 工作负载身份 | 代理在 AWS 上的身份,针对每个请求绑定到已登录用户 | AgentCore 运行时,针对每个代理运行时 |
| OAuth2 凭证提供程序 | 代理的 Okta 客户端 ID 和密钥,以及要使用的授权 | 你,每个 Okta 代理一次 |
| 令牌保管库 | 提供程序获取的访问令牌 | AgentCore Identity |
创建凭证提供程序
凭证提供程序执行第二次交换。将其指向自定义授权服务器,以 AI 代理身份进行身份验证,并将代表授权设置为 JWT_AUTHORIZATION_GRANT,AgentCore Identity 会将其作为 jwt-bearer 发送,并以 ID-JAG 作为断言:
control = boto3.client("bedrock-agentcore-control")
provider = control.create_oauth2_credential_provider(
name="okta-xaa-obo",
credentialProviderVendor="CustomOauth2",
oauth2ProviderConfigInput={"customOauth2ProviderConfig": {
"oauthDiscovery": {"discoveryUrl": f"{OKTA_ORG}/oauth2/{CUSTOM_AS_ID}/.well-known/openid-configuration"},
"clientId": AGENT_CLIENT_ID, # the AI agent's Okta client ID
"clientSecret": AGENT_CLIENT_SECRET, # AgentCore Identity stores it in AWS Secrets Manager
"clientAuthenticationMethod": "CLIENT_SECRET_BASIC",
"onBehalfOfTokenExchangeConfig": {"grantType": "JWT_AUTHORIZATION_GRANT"},
}},
)
provider_arn = provider["credentialProviderArn"]Okta 会将两个交换都绑定到 ID-JAG 中指定的客户端,因此每个 Okta 代理都需要自己的提供方:当我们把一个代理的 ID-JAG 当作另一个代理来兑换时,Okta 拒绝并提示“JWT Bearer Grant 中的 'client_id' 必须与用于验证客户端身份的 'client_id' 匹配。”AgentCore Identity 将密钥保存在由服务管理的 AWS Secrets Manager 密钥中,你可以使用 update-oauth2-credential-provider 轮换它。如果你的团队已经在 Secrets Manager 中管理客户端密钥,你可以改为引用该密钥的 ARN。AgentCore Identity 会从中读取客户端密钥,因此你可以在不更新提供方的情况下轮换密钥(参见在 Amazon Bedrock AgentCore Identity 中引用你自己的 AWS Secrets Manager 密钥)。为避免使用共享密钥,请改用私钥进行身份验证。参见使用 Amazon Bedrock AgentCore Identity 通过私钥 JWT 进行身份验证。图 4 显示了 AgentCore 控制台中的提供方。
图 4:凭据提供方以代理身份使用 JWT 授权授予进行身份验证
使用 AgentCore 运行时管理的工作负载身份
AgentCore 运行时为每个代理运行时创建并管理工作负载身份。当请求通过运行时的 JWT 授权器时,运行时会获取该工作负载身份的工作负载访问令牌以及入站令牌的颁发者和主体,并将其传递给你的代码。随后,AgentCore Identity 使用其背后的 ID-JAG 作为交换的断言。
AgentCore Python SDK 将工作负载访问令牌保存在 BedrockAgentCoreContext 中,而不是保存在你的入口点接收到的请求头中。我们的第一个版本在请求头中查找它,什么也没找到,于是在我们检查的全部 21 个请求中都回退到它自己的 GetWorkloadAccessTokenForJWT 调用,并使用了第二个工作负载身份。请改为从上下文中读取它:
from bedrock_agentcore.runtime import BedrockAgentCoreContext
identity = boto3.client("bedrock-agentcore")
def okta_access_token() -> str:
workload_token = BedrockAgentCoreContext.get_workload_access_token() # minted by the runtime
return identity.get_resource_oauth2_token(
workloadIdentityToken=workload_token,
resourceCredentialProviderName="okta-xaa-obo",
scopes=["xaa:read", "xaa:write"], # must equal the ID-JAG's scopes
oauth2Flow="ON_BEHALF_OF_TOKEN_EXCHANGE",
)["accessToken"]AgentCore Identity 会在请求的剩余时间内将访问令牌保存在其令牌保管库中。在 10 个请求中,代理的第一次调用在大约半秒内兑换了 ID-JAG(参见“验证结果”中的延迟表),而第二次调用针对另一个 MCP 服务器,以 58 毫秒的中位数返回了相同的令牌,且没有再次兑换这个一次性 ID-JAG。同一用户的新 ID-JAG 会获得新令牌,因此每个请求都反映了 Okta 的最新决定。示例 08-okta-xaa-delegation-chain 以相同方式读取工作负载访问令牌(agent/agent.py)。
将代理的角色限定到其工作负载身份和提供方
AgentCore Identity 不会在同一账户中将工作负载身份绑定到凭据提供方。代理的 IAM 角色会进行绑定,因此请限定其范围到代理自己的工作负载身份和提供方,以及该提供方的密钥:
[
{
"Sid": "OktaOnBehalfOf",
"Effect": "Allow",
"Action": "bedrock-agentcore:GetResourceOauth2Token",
"Resource": [
"arn:aws:bedrock-agentcore:us-west-2:123456789012:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:us-west-2:123456789012:workload-identity-directory/default/workload-identity/RUNTIME-WORKLOAD-IDENTITY",
"arn:aws:bedrock-agentcore:us-west-2:123456789012:token-vault/default",
"arn:aws:bedrock-agentcore:us-west-2:123456789012:token-vault/default/oauth2credentialprovider/okta-xaa-obo"
]
},
{
"Sid": "ReadProviderSecret",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:us-west-2:123456789012:secret:bedrock-agentcore-identity!default/oauth2/okta-xaa-obo-*"
}
]从 GetAgentRuntime 中的 workloadIdentityDetails 获取工作负载身份的名称,并从 credentialProviderArn 获取提供方的 ARN:该段是 oauth2credentialprovider,而使用带连字符的形式时,每次调用都失败并返回 AccessDeniedException。该角色不需要 GetWorkloadAccessToken 权限,因为获取该令牌的是运行时,而不是代理。我们的测试仅使用这两条语句就通过了。
在 AgentCore 运行时上部署代理
将代理运行时的入站授权器配置为仅接受 Okta 颁发给此代理的 ID-JAG。其颁发者是 Okta 的组织授权服务器,其受众是资源的自定义授权服务器。在 agentcore.json 中:
"authorizerType": "CUSTOM_JWT",
"authorizerConfiguration": {
"customJwtAuthorizer": {
"discoveryUrl": "https://YOUR-ORG.okta.com/.well-known/openid-configuration",
"allowedAudience": ["https://YOUR-ORG.okta.com/oauth2/YOUR-CUSTOM-AS-ID"],
"allowedClients": ["YOUR_AGENT_CLIENT_ID"],
"allowedScopes": ["xaa:read", "xaa:write"]
}
}allowedClients 与 ID-JAG 携带的 client_id 声明匹配。如果没有它,运行时会以 HTTP 200 接纳另一个代理的 ID-JAG,而请求会在稍后的交换阶段失败。有了它,运行时以 HTTP 401 拒绝了该令牌。
除了上一节中的策略外,执行角色还需要 bedrock:InvokeModel 和 bedrock:InvokeModelWithResponseStream。它不需要 MCP 服务器的 bedrock-agentcore:InvokeAgentRuntime 权限:每个服务器都运行在 AgentCore 运行时上,位于各自的 JWT 授权器之后,以自定义授权服务器作为签发者、以 api://task-manager 作为受众,因此代理使用 Okta 访问令牌作为持有者令牌来调用它,而不是使用 AWS Signature Version 4 (SigV4)。
在 MCP 服务器中强制执行每个用户的权限
资源连接为代理的每个用户设置作用域,因此三个测试用户都获得了 xaa:read xaa:write,而每个用户的权限则通过 groups 声明传递:Alice 的令牌携带 xaa-readers,Bob 的携带 xaa-writers,Carol 的则没有。
任务管理器检查两件事:它只接受已注册代理获取的令牌,并且仅当组和作用域同时存在时才允许写入:
REGISTERED_AGENTS = {"YOUR_AGENT_CLIENT_ID"}
def _require_agent() -> None:
claims = _decode_claims() # the runtime's JWT authorizer already validated the token
agent = (claims.get("act") or {}).get("sub")
if agent in REGISTERED_AGENTS and claims.get("cid") == agent:
return
raise ToolError("insufficient_privileges: this server accepts only tokens that a registered "
"AI agent obtained through Okta Cross App Access")
def _require_write() -> None:
_require_agent()
if WRITERS_GROUP in _groups() and "xaa:write" in _scopes():
return
raise ToolError(f"insufficient_privileges: this tool requires membership in '{WRITERS_GROUP}'")两项检查都弥补了我们发现的缺口:一个允许没有 groups 声明的令牌的写入检查,让不属于任何组的 Carol 创建了任务;而在 _require_agent 之前,一个发给没有 act 声明的服务应用的普通令牌交换令牌,为 Bob 创建了任务。服务器之所以能在不再次验证令牌的情况下读取声明,只是因为运行时的 JWT 授权器已经验证了它。没有该授权器在前面的服务器必须自行检查签名、签发者、受众和过期时间,正如 Amazon EKS 上的第 2 部分代理所做的那样。
验证结果
我们针对已部署的解决方案运行了每一项检查。Alice、Bob 和 Carol 各自要求代理创建任务,然后列出项目的任务:
| 调用方 | create_task |
list_tasks |
| Alice | 拒绝:需要 xaa-writers 的成员资格 |
允许 |
| Bob | 已创建 | 允许 |
| Carol | 拒绝:没有 groups 声明 |
允许 |
| Bob,然后紧接着 Alice | 为 Bob 创建,然后拒绝 Alice:没有权限延续 | 允许 |
这些请求在工具运行之前就被阻止了:
| 请求 | 阻止方 | 响应 |
| Agent B 的 ID-JAG 发送给任务代理 | 运行时的 JWT 授权器 | 401:“Claim ‘client_id’ value mismatch with configuration.” |
| 持有 245 秒的 ID-JAG | 运行时的 JWT 授权器 | 401:“Ineffectual token, will expire within the next minute” |
| 格式错误的持有者令牌 | 运行时的 JWT 授权器 | 403:“Failed to parse token” |
| 同一个 ID-JAG 被兑换两次 | Okta 的自定义授权服务器 | 400:“The id-jag was already used.” |
| 第二次交换时使用更窄的作用域 | Okta 的自定义授权服务器 | 400:“The scope parameter must exactly match the scopes in the id-jag.” |
| 连接之外的作用域 | Okta 的组织授权服务器 | 400 invalid_scope |
| MCP 服务器上的普通令牌交换令牌 | MCP 服务器 | 拒绝:仅接受已注册 AI 代理获取的令牌 |
AgentCore Identity 返回的令牌与我们直接在 Okta 兑换的令牌逐项声明匹配:sub 是用户,cid 和 act 指定了代理,scp 持有连接的作用域,groups 持有用户的组,并且有效期为 300 秒。
AgentCore Identity 为一个端到端约需 30 秒的请求增加了约 0.6 秒,其中大部分是模型和工具调用。来自我们测试客户端的五次运行的中位数:
| 调用 | 中位数 |
| 登录,脚本化(授权码流程) | 1,205 ms |
| 在 Okta 的组织授权服务器上将 ID 令牌转换为 ID-JAG | 216 ms |
GetWorkloadAccessTokenForJWT |
135 ms |
GetResourceOauth2Token,包括 Okta 的 JWT 持有者授权 |
508 ms |
在运营中治理代理
Okta 在铸造 ID-JAG 时会评估代理、用户和连接。我们测量了每个管理员操作对下一个请求和已发放令牌的影响:
| Okta 中的管理员操作 | 新请求 | 已签发的令牌 |
| 删除代理的资源连接 | 立即拒绝(invalid_target) |
持续有效直至过期,最长 5 分钟 |
| 移除用户的分配 | 约 1 秒内拒绝,即使用户已持有 ID 令牌 | 最长 5 分钟 |
| 停用代理 | 在 Okta 执行该操作后拒绝,我们的测试组织将其排队了 86 分钟 | 最长 5 分钟 |
对一个代理的操作未影响另一个代理继续工作。当 ID-JAG 被兑换时,Okta 不会重新检查用户:其自定义授权服务器在我们移除某用户 3 秒后,为移除前签发的 ID-JAG 签发了访问令牌。Okta 的 System Log 以代理为操作者记录每次授权,第 2 部分将这些事件流式传输到 CloudWatch。
委托链的最佳实践
这些测量得出了六项实践,每一项都是链的属性而非偏好:
| 实践 | 我们测量到的内容 |
| 为每个请求签发新的 ID-JAG | ID-JAG 是一次性的,有效期为 300 秒。运行时拒绝剩余时间不足 60 秒的 ID-JAG,因此 225 秒可行,245 秒不可行 |
在 groups 声明中携带每用户权限,并为每个请求请求一组作用域 |
Okta 从资源连接设置作用域,因此三个用户获得了相同的作用域,且第二次交换必须请求与 ID-JAG 完全一致的作用域 |
在运行时固定代理,并在工具中检查 act 和 cid |
allowedClients 与 ID-JAG 携带的 client_id 声明匹配。Okta 访问令牌携带的是 cid |
| 直接针对 Okta 复现失败的交换 | 通过 AgentCore Identity,作用域不匹配和客户端错误都表现为“Token exchange failed with HTTP status 400” |
| 授予代理角色读取提供方密钥的权限 | 在角色能够读取之前,GetResourceOauth2Token 一直失败 |
| 保持较短的生命周期,并将资源连接用作你的终止开关 | 删除连接立即生效。停用代理在 Okta 的 beta AI agent API 队列中等待了 86 分钟,且无法取消 |
Cross App Access 与普通令牌交换的对比
普通 RFC 8693 令牌交换也会将用户身份传递到下游。我们在同一 Okta 授权服务器和用户上将其与 XAA 进行了对比:
| 我们观察到的行为 | 普通令牌交换 | Cross App Access |
| 令牌中的代理身份 | 无 act 声明 |
act 指明代理 |
| 作用域 | 被扩大:Alice 自己的令牌具有 xaa:read,交换返回了 xaa:read xaa:write |
管理员批准的作用域 |
交换规则限制为 xaa-writers |
Alice 仍收到了令牌 | Alice 被拒绝 |
| 用户被取消分配,先前令牌被重用 | 仍然交换 | 拒绝 |
| 管理员看到的内容 | 一个具有授权类型的服务应用 | 代理、其连接,以及每个日志事件中的代理 |
这些结果反映了我们的 Okta 配置。Okta 的指南显示交换令牌应带有 act 声明,但我们没有收到。普通令牌交换携带了用户身份,但没有携带用户的权限。
此模式的适用场景
我们与媒体和娱乐公司合作,这也是我们最先遇到该问题的地方。制片厂、流媒体或游戏组织针对制作跟踪、标题和资产元数据、版权和本地化,以及观众或玩家支持运行代理。每个系统都有自己的授权模型和自己的审计员,用户的权限因标题、地区或发布窗口而异,因此“哪个代理可能代表哪个用户在哪个系统中行动”必须在代理上线前得到回答。
这条链路中没有任何环节是特定于某个行业的:agent 是你在 IdP 中的一个身份,目标是 OAuth 2.0 授权服务器,用户的权限承载在一个 claim 中。金融服务、医疗健康和公共部门团队在相同的控制措施背后放置了不同的资源。
清理
为避免持续产生费用,请删除你创建的资源:
- 删除 AgentCore CLI 为 agent 和两个 MCP 服务器创建的 AWS CloudFormation 堆栈。
- 使用
aws bedrock-agentcore-control delete-oauth2-credential-provider --name okta-xaa-obo删除凭证提供程序,并使用delete-workload-identity删除你自行创建的任何工作负载身份。 - 删除你添加到执行角色中的 IAM 策略。
- 在 Okta 中,停用并删除 AI agent 及其关联应用,并移除资源连接、授权服务器的策略规则、scopes 和 claim,以及测试用户和组。
结论
在本文中,你使用 Okta Cross App Access 决定哪个 agent 可以代表哪个用户执行操作,并使用 AgentCore Identity 执行每项决策。运行时只接受 agent 自己的 ID-JAG,凭证提供程序使用 agent 并不持有的密钥兑换每一个 ID-JAG,令牌保管库在单个请求内复用结果,MCP 服务器则根据 groups claim 强制执行每个用户的权限。
这种设计将交换保持在 agent 的角色中,并在每个 MCP 服务器中重复授权检查。请参阅本系列的第 2 部分,了解其设计为何将两者都移到同一个带有 Cedar 策略的 AgentCore Gateway 之后,在 Amazon EKS 上添加第二个 agent,并将 Okta System Log 与 CloudWatch 中的 AgentCore 跟踪记录关联起来。
要开始使用,请浏览 AgentCore 示例和 Okta 的Cross App Access 文档。有关 API 详细信息,请参阅 AgentCore 开发人员指南中的代表用户进行令牌交换。
关于作者
Hammad Ausaf
Hammad 是媒体与娱乐部门的首席解决方案架构师。他是一位充满热情的构建者,致力于为 AWS 客户提供最佳解决方案。
Rajat Jain
Rajat 是 AWS 媒体与娱乐部门的技术客户经理,已在公司工作超过 3 年。他指导客户遵循运营最佳实践,并帮助他们充分利用 AWS 服务。
Madhu Samhitha Vangara
Madhu 是 AWS 的全球生成式 AI 专家解决方案架构师,专注于 Amazon Bedrock AgentCore 和 Strands Agents 的 agentic AI 市场推广。她将新兴的 AI 能力和研究转化为客户可衡量的成果。工作之余,她是一名受过训练的印度古典舞者,也是一名艺术爱好者。
来源:AWS Machine Learning Blog · aws.amazon.com



