通过 CredentialProvider 将 RAM 角色统一纳管,由平台按 Agent 身份经 RRSA 扮演角色,为 AI Agent 工作负载签发实例级的短期 Security Token Service(STS)临时凭据,应用侧的代码或镜像无需内置长期 AccessKey。
功能介绍
在 AI Agent 场景下,Agent 常需以阿里云身份访问云服务(如对象存储 OSS、日志、云监控等)。若将长期 AccessKey(AK/SK)直接写入应用代码、镜像或环境变量,所有实例共享同一组密钥、权限无法收敛到实例维度,且存在长期密钥泄露与难以轮转的风险。
CredentialProvider 是 ack-agent-identity 提供的凭据来源自定义资源(CRD)。当类型为 RAM 且来源为 RRSA 时,ack-agent-identity 组件通过 RRSA(RAM Roles for Service Accounts)调用 STS 服务的 AssumeRoleWithOIDC 接口扮演指定 RAM 角色,签发一组短期 STS 临时凭据(AccessKeyId、AccessKeySecret、SecurityToken),并具备以下能力:
应用侧不持有任何长期 AK/SK,实际下发的是有效期受限的 STS 临时凭据,由平台按需签发与自动轮转。
通过
AgentRole/AgentRoleBinding授权机制,精细控制每个 Agent 身份可获取哪些CredentialProvider的凭据。通过
policy(会话策略)将 STS 凭据的权限收缩为 RAM 角色权限的子集,并支持模板变量按 Agent 身份、Sandbox 实例等上下文动态调整权限,实现实例级的最小权限授权。
CredentialProvider除RAM外还支持APIKey等类型。本文仅介绍type: RAM+ RRSA 来源(签发阿里云 STS 临时凭据),其余类型与来源请参见对应文档。
涉及的资源对象
配置一次可用的 STS 凭据下发,通常涉及以下 CR,下文配置 STS 凭据章节将按顺序创建:
资源对象 | 说明 |
| 定义 Agent 身份标识,是授权与凭据下发的主体。 |
| 声明一组凭据的来源与权限范围,供 Agent 身份消费。 |
| 定义权限规则,声明允许获取哪个 |
| 将 |
前提条件
集群版本 >= 1.28。
通过集群组件管理页面,确认
ack-agent-identity组件版本 >= 0.4.0。已通过目标集群集群信息页的基本信息页签开启RRSA OIDC,并记录提供商URL和提供商 ARN,用于后续 RAM 角色信任策略配置。
已配置可访问目标 ACS 集群的 kubeconfig,具体操作请参见通过kubectl快速使用ACS。
本模式依赖 ack-agent-identity 组件访问 STS 服务的
AssumeRoleWithOIDC接口获取临时凭据。请根据实际业务的 Sandbox 实例规模,前往配额中心申请AssumeRoleWithOIDC接口的访问配额,避免因配额不足导致凭据获取失败。评估方法请参见如何预估 AssumeRoleWithOIDC接口的峰值 QPS?。跨账号场景另需:如需通过
targetRoleArn实现跨账号扮演,还需满足ack-agent-identity组件版本 >= 0.5.0,并按实例规模额外申请 STSAssumeRole接口的访问配额。详细配置请参见RRSA 跨账号访问。
配置 STS 凭据
以下集群内资源(AgentIdentity、CredentialProvider、AgentRole、AgentRoleBinding)需创建于同一命名空间。
步骤 1:创建 RAM 角色并配置信任策略
在 RAM 控制台创建 RAM 角色(如 ack-agent-identity-sample-role),并配置信任策略,授权 ack-agent-identity 组件通过 RRSA 扮演此角色。将以下模板中的 <oidc_issuer_url> 和 <oidc_provider_arn> 替换为集群的 RRSA OIDC 信息(可通过集群基本信息页的RRSA OIDC部分获取)。
{
"Statement": [
{
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"oidc:aud": "sts.aliyuncs.com",
"oidc:iss": "<oidc_issuer_url>",
"oidc:sub": [
"system:serviceaccount:ack-agent-identity:credential-provider"
]
}
},
"Effect": "Allow",
"Principal": {
"Federated": [
"<oidc_provider_arn>"
]
}
}
],
"Version": "1"
}步骤 2:为该 RAM 角色授予自定义权限策略
为上一步创建的 RAM 角色授予自定义权限策略(建议按最小权限精细化授权,避免直接绑定 AliyunOSSReadOnlyAccess 等范围过大的系统策略)。此处授予的角色权限是最大权限边界,每个实例最终获得的权限还会被下一步 CredentialProvider 的 policy 进一步收缩。以下示例授予对 my-bucket 的只读权限(将 my-bucket 替换为实际 Bucket 名称):
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:GetObject",
"oss:ListObjects"
],
"Resource": [
"acs:oss:*:*:my-bucket",
"acs:oss:*:*:my-bucket/*"
]
}
]
}步骤 3:创建 CredentialProvider
将以下内容保存为 credential-provider-sts.yaml 并执行 kubectl apply -f credential-provider-sts.yaml 命令,创建 CredentialProvider 引用上述 RAM 角色。policy 字段定义最终颁发的 STS Token 的权限范围(必须是角色权限的子集)。
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
name: aliyun-oss-readonly
namespace: <YOUR_NAMESPACE>
spec:
type: RAM
ram:
source:
provider: RRSA
rrsa:
# 步骤 1 创建的 RAM 角色名称
roleName: ack-agent-identity-sample-role
policy: |
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": ["oss:GetObject"],
"Resource": ["acs:oss:*:*:my-bucket/agent-data/*"]
},
{
"Effect": "Allow",
"Action": ["oss:ListObjects"],
"Resource": ["acs:oss:*:*:my-bucket"],
"Condition": {
"StringLike": { "oss:Prefix": ["agent-data/*"] }
}
}
]
}
tokenValidity: 3600s # STS 凭据有效期,默认 1h,最短 15mpolicy 支持通过模板变量按 Agent 身份等上下文动态收缩权限,实现实例级的权限最小化,详见policy 权限收缩与模板变量。步骤 4:创建 AgentIdentity
将以下内容保存为 agent-identity.yaml 并执行 kubectl apply -f agent-identity.yaml 命令,创建 AgentIdentity 定义 Agent 身份标识。
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentIdentity
metadata:
name: my-agent # Agent 身份名称,后续授权中引用
namespace: <YOUR_NAMESPACE>
spec:
description: "示例 AI Agent 身份"步骤 5:创建 AgentRole 与 AgentRoleBinding
将以下内容保存为 agent-role-sts.yaml 并执行 kubectl apply -f agent-role-sts.yaml 命令,创建 AgentRole 和 AgentRoleBinding,授权 Agent 身份获取该 CredentialProvider 的凭据。
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRole
metadata:
name: get-aliyun-sts
namespace: <YOUR_NAMESPACE>
spec:
rules:
- effect: Allow
action: "GetResourceCredential"
# 与步骤 3 创建的 CredentialProvider 名称保存一致
resource: "CredentialProvider/aliyun-oss-readonly"
---
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRoleBinding
metadata:
name: my-agent-get-aliyun-sts
namespace: <YOUR_NAMESPACE>
spec:
agentRoleRef:
apiGroup: agentidentity.alibabacloud.com
kind: AgentRole
name: get-aliyun-sts
subjects:
- authorizationType: "Agent"
agentAuthorizationConfiguration:
# 与步骤 4 创建的 AgentIdentity name 保持一致
agentName: my-agent 步骤 6:确认 CredentialProvider 已就绪
确认 CredentialProvider 已就绪(Available 列为 True)。
kubectl get credentialprovider aliyun-oss-readonly -n <YOUR_NAMESPACE>预期输出:
NAME AVAILABLE AGE
aliyun-oss-readonly True 30sRRSA 来源的CredentialProvider通过校验后即标记为Available,此时仅表示配置合法,并不代表已成功扮演 RAM 角色。角色不存在、信任策略配置错误、权限不足等问题会在实际获取 STS 凭据时才暴露,详见状态与排查。
步骤 7:验证 RAM 角色扮演可用性
由于 Available=True 仅代表配置合法,建议在进入生产前触发一次实际的凭据签发以验证 RAM 角色能被成功扮演。可通过消费凭据章节任一场景发起一次真实请求,观察是否成功签发凭据;若签发失败,按状态与排查章节的现象与排查方向定位。
消费凭据
创建并授权好的 STS 凭据,通常由以下几类场景消费,均无需应用侧持有长期 AK/SK:
Agent Sandbox 出口流量凭据注入:为
SecurityProfile的tokenTransformation规则引用本CredentialProvider,Sandbox 应用使用伪造的 AK/SK 通过标准阿里云 SDK 发起请求,出口网关在转发时透明替换为真实 STS 三元组并重新计算请求签名。完整端到端配置请参见为Agent Sandbox出口流量注入凭据。OSS 存储挂载:为 Sandbox 声明
authType: agent-identity的存储卷,挂载时通过credentialProviderName引用本CredentialProvider,容器存储接口(CSI,Container Storage Interface)使用签发的 STS 凭据按需挂载 OSS 目录。完整端到端配置请参见为Agent Sandbox挂载OSS存储。AgenticFS 存储挂载:为 Sandbox 声明
authType: agent-identity的存储卷,挂载时通过credentialProviderName引用本CredentialProvider,容器存储接口使用签发的 STS 凭据按需挂载 AgenticFS 目录。完整端到端配置请参见为 Agent Sandbox 挂载 AgenticFS。
policy 权限收缩与模板变量
每个实例最终获得的 STS 凭据权限,为RAM 角色权限与CredentialProviderpolicy 的交集。policy 只能在角色权限范围内进一步收缩,无法放大超出角色的权限。合理配置 policy 是实现实例级最小权限的关键。
policy 的内容为标准的 RAM 权限策略 JSON,共有三种写法:静态 policy 直接声明固定权限,模板变量按当前请求身份上下文替换资源路径,内置函数按 Sandbox 实例的挂载配置自动填充。以下按顺序介绍。
静态 policy
最简单的用法是一段静态 policy,权限范围在编写时就已固定,如配置 STS 凭据步骤 3 所示。适用于不同 Agent 身份权限相同的场景。
模板变量
policy 支持嵌入 ${ack:agent-identity/...} 模板变量,系统签发凭据时按当前请求身份上下文替换为实际值,从而按身份签发不同权限的凭据。支持的变量如下:
模板变量 | 说明 |
| 当前 Agent 身份关联的 |
| 身份 Token 签发时写入的自定义 metadata 中指定 Key 的值, |
以下示例演示按租户动态收缩权限:不同租户的数据分别存放于 OSS Bucket 下以租户标识命名的子目录,policy 通过 ${ack:agent-identity/metadata/tenant-id} 在签发凭据时解析出对应的资源路径。
policy: |
{
"Statement": [
{
"Action": ["oss:GetObject", "oss:PutObject"],
"Effect": "Allow",
"Resource": [
"acs:oss:*:*:my-bucket/${ack:agent-identity/metadata/tenant-id}/*"
]
}
],
"Version": "1"
}metadata 的值来自身份 Token 签发时写入的自定义 metadata;对于 Agent Sandbox 场景,可通过 SandboxClaim 的 security.agents.kruise.io/<key> 注解传入(注解去掉前缀后即为 metadata 的 Key):
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: my-claim
namespace: <YOUR_NAMESPACE>
spec:
templateName: my-sandbox-set
replicas: 1
annotations:
# 以下 annotation 去掉前缀后可通过模板中的 ${ack:agent-identity/metadata/tenant-id} 引用
security.agents.kruise.io/tenant-id: acme
security.agents.kruise.io/agent-name: my-agent上述配置下,当请求身份的 metadata tenant-id 为 acme 时,policy 中的资源路径解析为 acs:oss:*:*:my-bucket/acme/*,即该租户仅能访问自己的子目录。
若模板变量在当前请求上下文下无法解析(例如引用的 metadata Key 不存在),凭据签发请求会失败并返回明确的错误信息,而非静默返回空值或放开权限。
策略生成内置函数
除 ${ack:agent-identity/...} 变量替换外,policy 还支持一组内置函数,以 {{ 函数名() }} 的形式按每个 Sandbox 实例的挂载配置自动填充资源(Resource)与访问条件,从而将权限精确收缩到实例实际挂载的 Bucket、子路径与密钥管理服务(KMS,Key Management Service)密钥。这些函数主要用于存储挂载场景,由平台按挂载配置自动填充,无需为每个子路径单独创建 CredentialProvider。
内置函数写法({{ }})与${ack:agent-identity/...}变量写法不可在同一段policy中同时使用。
OSS 存储挂载场景
OSS 存储挂载场景支持的内置函数如下:
内置函数 | 说明 |
| 按 Sandbox 实例的挂载配置自动填充限制到子路径维度的 假设一个 Sandbox 实例挂载了 |
| 按 Sandbox 实例的挂载配置自动填充限制到 Bucket 维度的 假设一个 Sandbox 实例挂载了 |
| 按 Sandbox 实例的挂载配置自动填充限制到子路径前缀维度的 假设一个 Sandbox 实例挂载了 |
| 按 Sandbox 实例的挂载配置自动填充限制到 KMS 密钥维度的 假设一个 Sandbox 实例挂载时使用了 KMS 密钥 |
| 放宽到请求账号/地域下所有 KMS 密钥(不再按挂载卷的密钥收缩)的 示例结果: |
内置函数按最小权限、fail-closed 设计:当没有可收缩的对象时(例如无挂载卷、无子路径、无 KMS 密钥),函数会报错使凭据签发失败,而非退化为 * 通配符从而静默放开角色的全量权限。完整的端到端配置(存储卷声明、挂载与验证)请参见为Agent Sandbox挂载OSS存储。AgenticBucket 存储挂载场景
AgenticBucket 存储挂载场景除支持 OSS 挂载场景的所有内置函数外,还额外支持如下内置函数:
内置函数 | 说明 |
| 按 Sandbox 实例的挂载配置自动填充限制到子路径维度的 假设一个 Sandbox 实例挂载了 |
| 按 Sandbox 实例的挂载配置自动填充限制到 BucketSpace 维度的 假设一个 Sandbox 实例挂载了 |
AgenticFS 存储挂载场景
AgenticFS 存储挂载场景支持的内置函数如下:
内置函数 | 说明 |
| 按 Sandbox 实例的挂载配置自动填充账号/地域维度的 示例结果: |
| 按 Sandbox 实例的挂载配置自动填充限制到 NAS 接入点维度的 假设一个 Sandbox 实例挂载了 NAS 接入点 |
完整的端到端配置(存储卷声明、挂载与验证)请参见为 Agent Sandbox 挂载 AgenticFS。
RRSA 跨账号访问(targetRoleArn)
默认情况下 RRSA 只能扮演本账号的 RAM 角色。若 Agent 需访问另一个阿里云账号下的资源,可通过 targetRoleArn 开启跨账号扮演:ack-agent-identity 先用 RRSA 扮演本账号的 roleName 获取一个中间 STS 凭据,再用该中间凭据 AssumeRole 到 targetRoleArn 指向的目标账号角色,最终签发目标账号的 STS 凭据。此时 policy、tokenValidity 均作用于第二跳(即最终扮演目标角色)。
整个过程由 ack-agent-identity 组件向 STS 服务发起两次请求:
AssumeRoleWithOIDC(扮演源账号角色roleName)→ 获得中间 STS 凭据(源账号角色身份)AssumeRole(凭中间凭据扮演目标账号角色targetRoleArn)→ 获得最终 STS 凭据(目标账号角色身份)跨账号涉及两个 RAM 角色:源账号角色(第一跳,即
CredentialProvider中roleName指向的角色,位于集群所在账号)与目标账号角色(第二跳,targetRoleArn指向的角色,位于被访问账号)。按以下步骤配置:
步骤 1:为源账号角色授予扮演目标角色的权限
在源账号为源账号角色授予扮演目标角色的权限。源账号角色于跨账号场景下仅作跳板,无需任何资源访问权限,只需授予sts:AssumeRole权限;其信任策略仍为信任集群 RRSA OIDC,与配置 STS 凭据步骤 1 一致。为该角色附加如下自定义权限策略(将 Resource 替换为实际目标角色 ARN):
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": ["acs:ram::123456789012:role/cross-oss-role"]
}
]
}步骤 2:在目标账号创建目标账号角色并配置信任策略
在目标账号创建目标账号角色(如 cross-oss-role),其信任策略仅信任源账号角色(而非整个源账号),只允许该角色扮演。将 <源账号 UID> 替换为源账号的账号 ID,ack-agent-identity-sample-role 替换为实际的源账号角色名:
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Principal": {
"RAM": ["acs:ram::<源账号 UID>:role/ack-agent-identity-sample-role"]
}
}
]
}随后为目标账号角色授予其在目标账号内实际要访问的资源权限(此为最大权限边界,建议按最小权限精细化授权,写法同配置 STS 凭据步骤 2 的自定义策略)。该权限还会被下一步 CredentialProvider 的 policy 进一步收缩。
跨账号角色的创建与信任配置详见通过RAM角色跨阿里云账号授权。
步骤 3:创建引用 targetRoleArn 的 CredentialProvider
创建引用 targetRoleArn 的 CredentialProvider(policy、tokenValidity 作用于第二跳,即于目标角色权限内进一步收缩):
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
name: cross-account-oss
namespace: <YOUR_NAMESPACE>
spec:
type: RAM
ram:
source:
provider: RRSA
rrsa:
# 源账号角色(第一跳)
roleName: ack-agent-identity-sample-role
# 目标账号角色(第二跳)
targetRoleArn: "acs:ram::123456789012:role/cross-oss-role"
policy: |
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": ["oss:GetObject"],
"Resource": ["acs:oss:*:*:cross-bucket/*"]
}
]
}targetRoleArn 须为合法的 RAM 角色 ARN,格式为 acs:ram::<目标账号 UID>:role/<角色名>,可通过目标账号的 RAM 角色详情页查看。
字段说明
type: RAM + RRSA 来源的 spec 结构如下:
spec:
type: RAM # 必填,凭据类型;创建后不可变更
ram:
source:
provider: RRSA # 必填,凭据来源
rrsa:
roleName: <role-name> # 必填,要扮演的本账号 RAM 角色名称
policy: <policy-json> # 必填,会话策略,须为角色权限的子集
tokenValidity: 1h # 可选,STS 凭据有效期,默认 1h
targetRoleArn: <role-arn> # 可选,跨账号扮演的目标角色 ARN关键字段说明如下:
字段 | 是否必填 | 说明 |
| 是 | 凭据类型,本文取 |
| 是 | 凭据来源,本文取 |
| 是 | 要扮演的本账号 RAM 角色名称,须已配置信任 ack-agent-identity 的信任策略。 |
| 是 | |
| 否 | 签发的 STS 凭据有效期,默认 |
| 否 | 跨账号扮演的目标角色 ARN,格式 |
状态与排查
CredentialProvider 的运行状态记录于 status.conditions,可通过以下命令查看:
kubectl describe credentialprovider <name> -n <YOUR_NAMESPACE>RRSA 来源的 CredentialProvider 只要通过配置校验就会立即标记为 Available=True(Reason 为 ReconcileSucceeded),协调阶段不会校验 RAM 角色是否存在、信任策略是否正确、权限是否足够。因此,与 RAM 角色相关的错误不会体现在 CredentialProvider 的状态上,而是在实际签发 STS 凭据(调用 AssumeRoleWithOIDC)时才暴露。常见运行时错误及排查方向如下:
现象 | 排查方向 |
签发凭据报 | 核对 RAM 角色信任策略: |
访问资源报 |
|
访问资源报 |
|
并发创建大量 Sandbox 时偶发签发失败 |
|
出口注入与 OSS 挂载场景的完整分层排查手段,请分别参见为Agent Sandbox出口流量注入凭据与为Agent Sandbox挂载OSS存储。
使用限制
以下为本功能的硬性约束一览,细节描述保留于对应章节:
限制项 | 详见 |
STS 凭据有效期: | |
policy 只能收缩权限:最终 STS 权限为 RAM 角色权限与 | |
policy 语法不可混用: | |
|
常见问题
如何预估 AssumeRoleWithOIDC接口的峰值 QPS?
并发申领(通过 SandboxClaim CRD 或 Sandbox.create接口申领) Sandbox 实例时,AssumeRoleWithOIDC接口的峰值 QPS 预估公式为:峰值 QPS ≤ min(M, T) × P。
公式内的各项说明如下。
符号项 | 含义 |
M | 每秒并发申领的 Sandbox 实例数。 |
T | 每秒完成领用的 Sandbox 实例数。 |
P | 单个 Sandbox 实例声明的存储挂载点数量。 |
跨账号场景请参考该公式预估 AssumeRole接口的峰值 QPS。该预估公式仅供参考,请结合业务规模,以实际压测结果为准。下面是在提前准备 Sandbox 预热池后执行的压测结果示例,供参考(AssumeRoleWithOIDC接口的默认限流为 100/s)。
P | M |
|
2 | 25 | 50 |
2 | 70 | 100 |
2 | 100 | 150 |
2 | 120 | 200 |
3 | 17 | 50 |
3 | 34 | 100 |
3 | 63 | 150 |
3 | 80 | 200 |
6 | 9 | 50 |
6 | 17 | 100 |
6 | 25 | 150 |
6 | 34 | 200 |
如何查看AssumeRoleWithOIDC接口的调用情况?
可以通过如下几种方式查看AssumeRoleWithOIDC接口的调用情况。
登录操作审计控制台,查询事件名称为
AssumeRoleWithOIDC的操作事件。更多操作,请参见通过操作审计控制台查询事件。使用操作审计提供的自定义查询功能,查询事件名称为
AssumeRoleWithOIDC的操作事件。更多操作,请参见自定义查询事件。如需配置调用量事件告警,请参见事件告警概览。
CredentialProvider 已 Available,但 Sandbox 获取不到 STS 凭据?
RRSA 来源的 CredentialProviderAvailable 仅代表配置合法,不代表能成功扮演角色。请按以下方向排查:
核对 RAM 角色的信任策略:
oidc:iss与集群提供商 URL 完全一致,oidc:aud为sts.aliyuncs.com,oidc:sub为system:serviceaccount:ack-agent-identity:credential-provider,Principal.Federated为集群提供商 ARN。确认
roleName与 RAM 控制台中的角色名称一致,且该角色已授予所需的权限策略。若为并发创建大量 Sandbox 时偶发失败,前往配额中心申请
AssumeRoleWithOIDC接口配额。
获取到 STS 凭据,但访问云资源被拒绝?
最终生效权限是RAM 角色权限与 policy 的交集,任一层缺失都会导致拒绝:
确认 RAM 角色的权限策略覆盖了实际执行的操作与资源(如写操作需包含
oss:PutObject)。确认
CredentialProvider的policy声明的 Action/Resource 覆盖了实际执行的操作,且模板变量/函数渲染出的资源与实际访问路径一致。
Agent 获取凭据时被拒绝(无权限)?
确认已创建 AgentRole(action: GetResourceCredential、resource: CredentialProvider/<name>)及 AgentRoleBinding,且 AgentRoleBinding 的 agentName 与目标 AgentIdentity 名称一致,相关资源位于同一命名空间。