当 Bedrock AgentCore 中的智能体需要访问外部 OAuth 2.0 服务时,传统做法通常是保存一个客户端密钥。Private Key JWT 改变了这个模型:智能体不再向身份提供商发送长期共享密钥,而是使用 AWS KMS 中的私钥签署一个短期 JWT,再由身份提供商用已注册的公钥验证。
这套方案的关键价值不只是“换一种登录方式”。私钥可以留在 KMS 内部,签名操作受 IAM 控制,并能通过 AWS CloudTrail 留下审计记录,从而缩小凭证泄露的影响面。
Private Key JWT 实际认证了什么
Private Key JWT 是 OAuth 2.0 客户端认证方式,不是一种独立的授权类型。授权类型决定客户端申请哪类令牌,Private Key JWT 则回答令牌端点的另一个问题:调用方如何证明自己就是已注册的客户端。
客户端向身份提供商的令牌端点提交请求时,通常包含以下字段:
client_id:身份提供商分配的客户端标识。client_assertion_type:固定为urn:ietf:params:oauth:client-assertion-type:jwt-bearer。client_assertion:由客户端私钥签名的短期 JWT。grant_type:实际使用的 OAuth 授权类型。scope:需要申请的权限范围。
JWT 的载荷通常包含:
{
"iss": "agentcore-client-id",
"sub": "agentcore-client-id",
"aud": "https://idp.example.com/oauth2/token",
"iat": 1735689600,
"exp": 1735689900,
"jti": "a-unique-request-id"
}
iss 和 sub 一般对应 OAuth 客户端 ID;aud 必须匹配身份提供商对令牌端点受众的要求;exp 应保持很短;jti 可以帮助身份提供商阻止断言重放。具体字段规则仍应以所使用的身份提供商为准。
授权类型与客户端认证方式需要分开配置。机器到机器场景通常会考虑 client_credentials,涉及最终用户授权的场景则可能使用授权码或刷新令牌流程。AgentCore Identity 控制台中可选择的流程、身份提供商实际支持的组合,以及组织的 OAuth 策略必须同时满足,不能因为启用了 Private Key JWT 就假定所有 grant flow 都可用。
在 KMS 中创建不可导出的签名密钥
可以这样实践:创建一把非对称 RSA KMS 密钥,并只允许它执行签名和验签。下面的命令假设已经配置 AWS CLI;运行前需要修改区域和别名。
set -euo pipefail
AWS_REGION="us-east-1"
KEY_ALIAS="alias/agentcore-private-key-jwt"
KEY_ID=$(aws kms create-key \
--region "$AWS_REGION" \
--key-usage SIGN_VERIFY \
--key-spec RSA_2048 \
--description "Signing key for AgentCore Private Key JWT" \
--query 'KeyMetadata.KeyId' \
--output text)
aws kms create-alias \
--region "$AWS_REGION" \
--alias-name "$KEY_ALIAS" \
--target-key-id "$KEY_ID"
printf 'Created KMS key: %s\n' "$KEY_ID"
这里使用 RSA 是为了便于与支持 RS256 的身份提供商对接。实际创建前,应确认身份提供商接受的 JWT alg、密钥长度和公钥注册格式。不要把算法选择留到联调阶段,因为 KMS 密钥规格创建后不能直接改成另一种非对称算法。
私钥不会被导出。需要提供给身份提供商的是公钥,可以用以下命令将 KMS 返回的 DER 公钥转换成 PEM:
set -euo pipefail
AWS_REGION="us-east-1"
KEY_ALIAS="alias/agentcore-private-key-jwt"
aws kms get-public-key \
--region "$AWS_REGION" \
--key-id "$KEY_ALIAS" \
--query 'PublicKey' \
--output text \
| base64 --decode > agentcore-public-key.der
openssl pkey \
-pubin \
-inform DER \
-in agentcore-public-key.der \
-out agentcore-public-key.pem
openssl pkey \
-pubin \
-in agentcore-public-key.pem \
-text \
-noout
macOS 自带的 base64 参数可能不同,此时可将解码部分改为 base64 -D。生成的 agentcore-public-key.pem 可以提交给支持 PEM 注册的身份提供商;如果对方要求 JWK 或 JWKS,则应使用可靠的密钥转换工具生成 kty、n、e 和稳定的 kid,不要手工拼接 JSON。
连接身份提供商与 AgentCore Identity
配置可以按两个边界推进。
在身份提供商一侧,创建或更新 OAuth 客户端,启用 Private Key JWT 客户端认证,并注册从 KMS 导出的公钥。需要记录客户端 ID、令牌端点、允许的 grant flow、scope、签名算法以及公钥的 kid。若身份提供商要求精确的 audience,也应一并记录。
在 AWS Management Console 的 AgentCore Identity 中创建 credential provider 时,填写身份提供商元数据和客户端标识,选择 Private Key JWT 认证,并关联前面创建的 KMS 签名密钥。控制台中的字段名称可能随身份提供商类型变化,应逐项核对以下关系:
| 配置项 | 必须确认的内容 |
|---|---|
| Client ID | 与 JWT 的 iss、sub 规则一致 |
| Token endpoint | 与 JWT aud 的要求一致 |
| Signing key | 指向正确区域和账户中的 KMS 密钥 |
| Algorithm | 同时被 KMS 密钥与身份提供商支持 |
| Grant flow | AgentCore、身份提供商和目标 API 均支持 |
| Scope | 只授予智能体完成任务所需的最小权限 |
AgentCore 使用 KMS 签名时,执行身份还需要 kms:Sign 和读取公钥所需的权限。可以从下面的最小化策略开始改造,将账户、区域和密钥 ID 替换为真实值:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SignPrivateKeyJwt",
"Effect": "Allow",
"Action": [
"kms:Sign",
"kms:GetPublicKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/11111111-2222-3333-4444-555555555555"
}
]
}
还要检查 KMS key policy。IAM policy 允许某项操作,并不保证 key policy 已经允许对应主体使用该密钥。生产环境中应将权限绑定到实际运行角色,避免对整个账户或通配资源开放 kms:Sign。
从 CloudTrail 验证实际调用链
配置完成后,不要只以“拿到了 access token”作为验收标准。触发一次智能体访问,在相近时间窗口内检查 CloudTrail,可以确认哪个主体使用了哪把 KMS 密钥,以及调用发生在哪个区域。
下面的命令查询最近的 KMS Sign 管理事件,并提取常用审计字段:
set -euo pipefail
AWS_REGION="us-east-1"
aws cloudtrail lookup-events \
--region "$AWS_REGION" \
--lookup-attributes AttributeKey=EventName,AttributeValue=Sign \
--max-results 20 \
--query 'Events[].CloudTrailEvent' \
--output text \
| while IFS= read -r event; do
printf '%s\n' "$event" | jq '{
eventTime,
eventSource,
eventName,
awsRegion,
userIdentity,
requestParameters,
resources
}'
done
重点检查:
userIdentity是否对应预期的 AgentCore 运行角色或服务身份。requestParameters.keyId或resources是否指向预期 KMS 密钥。- 签名算法是否与身份提供商配置匹配。
- 事件时间是否与智能体申请令牌的时间一致。
- 是否存在异常区域、异常主体或非预期的高频签名。
CloudTrail 是否能通过 lookup-events 直接看到所有相关事件,取决于事件类型、区域和组织的 Trail 配置。长期审计应把事件投递到集中式日志存储,并基于 KMS 密钥 ARN、调用角色和错误码建立告警,而不是依赖临时查询。
上线前的检查清单
Private Key JWT 消除了静态客户端密钥的分发问题,但并没有消除身份配置风险。上线时至少确认以下事项:
- KMS 私钥不可导出,并且只允许预期角色调用
kms:Sign。 - JWT 生命周期足够短,系统时钟保持同步,并启用
jti重放防护能力。 aud、iss、sub、kid和签名算法与身份提供商要求完全一致。- grant flow 与客户端认证方式分别经过验证。
- scope 遵循最小权限,不把通用管理员权限交给智能体。
- 已设计公钥轮换流程,允许新旧公钥短暂并存,避免切换时中断令牌申请。
- CloudTrail 已覆盖相关区域,日志具备足够的保留期和告警规则。
这套架构最适合需要集中控制签名权限、避免长期共享密钥,并要求清晰审计链路的智能体系统。它增加了 KMS、IAM、OAuth 和密钥轮换之间的配置工作,但这些显式边界也让客户端身份更容易被限制、观察和撤销。