通过 SecurityProfile 的 tokenTransformation 规则,在 Sandbox 出口流量经 Egress Gateway 转发时自动替换凭据,让应用以占位符凭据安全调用外部 API。
功能介绍
在 AI Agent 场景中,Sandbox 运行的代码通常来自不可信来源,直接放置真实 API Key 或云账号 AccessKey 存在凭据泄露风险。凭据注入功能通过出口网关在转发过程中动态替换凭据,实现以下安全目标:
Sandbox 应用仅持有占位符凭据(如
FAKE_AK),无法直接调用外部服务。真实凭据存储在集群侧(Kubernetes Secret 或 CredentialProvider),由平台统一管理。
网关在转发请求时自动替换凭据并重新计算签名,对 Sandbox 应用透明。
通过 AgentIdentity 授权机制,精细控制每个 Agent 身份可使用的凭据。
凭据注入支持以下两种模式,可根据目标服务类型选择:
模式 | 适用场景 | 说明 |
API Key 注入 | 第三方 LLM 服务(OpenAI、通义千问等) | 将请求中的占位符 Token 替换为真实 API Key。 |
阿里云 STS 凭据注入 | 调用阿里云 OpenAPI | 替换 AK/SK/STS 三元组并重新计算请求签名。 |
工作原理
下图展示出口流量凭据注入的完整请求转发与凭据替换流程:
请求发起:Sandbox 应用使用占位符凭据发起出口请求,被 traffic-proxy Sidecar 透明拦截后转发至 egress-gateway。
策略评估:Egress Gateway 将请求元信息发送至 traffic-extension 服务,匹配命名空间下的 SecurityProfile 规则。
凭据获取:命中 tokenTransformation 规则后,traffic-extension 通过 CredentialProvider 获取真实凭据。
凭据替换:traffic-extension 替换请求头中的占位符凭据;对阿里云 STS 模式,还会基于真实 AK/SK 重新计算请求签名。
转发响应:Egress Gateway 使用改写后的请求头转发至目标服务,响应原路返回 Sandbox 应用。
涉及的资源对象
凭据注入功能通过以下五种 CR(Custom Resource,自定义资源)协作实现,下文操作步骤将依次创建:
资源对象 | 说明 |
| 定义 Agent 身份标识。SandboxClaim 通过 Label 关联此身份,获得对应凭据注入能力。 |
| 定义真实凭据来源:API Key 模式从 Kubernetes Secret 读取,阿里云 STS 模式通过 RRSA 扮演 RAM 角色获取临时凭据。 |
| 定义权限规则,声明可获取哪个 CredentialProvider 的凭据。 |
| 将 AgentRole 绑定到指定 AgentIdentity,完成授权。 |
| 定义 tokenTransformation 规则,指定匹配的域名、目标请求头与凭据来源(引用 CredentialProvider)。 |
适用范围
集群版本 >= 1.30。
在集群组件管理页面,确认以下组件版本及配置:
ack-agent-identity:版本 >= 0.2.0。ack-agent-sandbox-controller:版本>= 0.5.16,且配置中已启用identityProvider。ack-sandbox-manager:版本 >= 0.6.4,且配置中已启用enhancedTrafficManagement。
配置凭据注入
无论使用哪种凭据注入模式,均需先创建 AgentIdentity CR 定义 Agent 身份标识,后续创建的 Sandbox 实例通过关联此身份获得凭据注入能力。
以下操作通过 kubectl 完成,执行前请确保已配置可访问目标 ACS 集群的 kubeconfig,具体操作请参见通过kubectl快速使用ACS。
将以下内容保存为
agent-identity.yaml,并执行kubectl apply -f agent-identity.yaml命令创建 AgentIdentity 资源。apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentIdentity metadata: name: my-agent # Agent 身份名称,后续配置中引用 namespace: <YOUR_NAMESPACE> spec: description: "示例 AI Agent 身份"完成通用步骤后,根据目标服务类型选择对应模式:
API Key 注入模式:适用于第三方 API 服务(如 LLM 服务)注入 API Key。
阿里云 STS 凭据注入模式:适用于 Sandbox 调用阿里云 OpenAPI,自动重新计算签名。
API Key 注入模式
以下为端到端操作流程,以
httpbin.org作为验证目标,实际使用时替换为目标域名。将以下内容保存为
llm-api-key-secret.yaml并执行kubectl apply -f命令,创建存储 API Key 的 Secret。apiVersion: v1 kind: Secret metadata: name: llm-api-key namespace: <YOUR_NAMESPACE> type: Opaque stringData: apiKey: "sk-xxxxxxxxxxxxxxxx" # 替换为真实 API Key将以下内容保存为
credential-provider-apikey.yaml并执行kubectl apply -f命令,创建 CredentialProvider 引用上述 Secret。apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: llm-api-key namespace: <YOUR_NAMESPACE> spec: type: APIKey apiKey: source: provider: Kubernetes kubernetes: secretRef: name: llm-api-key # 上一步所创建的 Secret 名称 keyName: apiKey # Secret 中包含 API Key 的字段名说明secretRef.name支持使用模板变量动态引用 Secret 名称,详见CredentialProvider 模板变量。将以下内容保存为
agent-role-apikey.yaml并执行kubectl apply -f命令,创建 AgentRole 和 AgentRoleBinding,授权 Agent 身份获取该CredentialProvider 凭据。apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentRole metadata: name: get-llm-key namespace: <YOUR_NAMESPACE> spec: rules: - effect: Allow action: "GetResourceCredential" resource: "CredentialProvider/llm-api-key" # 上一步所创建的 CredentialProvider 名称 --- apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentRoleBinding metadata: name: my-agent-get-llm-key namespace: <YOUR_NAMESPACE> spec: agentRoleRef: apiGroup: agentidentity.alibabacloud.com kind: AgentRole name: get-llm-key subjects: - authorizationType: "Agent" agentAuthorizationConfiguration: agentName: my-agent # 与 AgentIdentity name 一致将以下内容保存为
security-profile-apikey.yaml并执行kubectl apply -f命令,创建 SecurityProfile 配置 tokenTransformation 规则。以下示例表示当 Authorization 头以 Bearer 开头时,系统会按
valueTemplate将其自动替换为真实的 API Key({{ .Token }}为固定写法)。apiVersion: agents.kruise.io/v1alpha1 kind: SecurityProfile metadata: name: inject-llm-key namespace: <YOUR_NAMESPACE> spec: selector: matchLabels: security.agents.kruise.io/agent-name: my-agent # 与 AgentIdentity name 一致 rules: - name: inject-openai-key match: - domains: - "httpbin.org" # 验证示例,实际使用时替换为目标域名 actions: tokenTransformation: type: ApiKey credentialRef: kind: CredentialProvider name: llm-api-key apiKey: when: header: Authorization pattern: "^Bearer .+" targetHeader: Authorization valueTemplate: "Bearer {{ .Token }}"关键字段说明请参见tokenTransformation 字段说明。
将以下内容保存为
sandboxset-apikey.yaml并执行kubectl apply -f命令,创建 SandboxSet 并声明enhanced-traffic-policy模式以启用增强流量管理。apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet metadata: name: apikey-test namespace: <YOUR_NAMESPACE> spec: replicas: 2 runtimes: - name: csi - name: agent-runtime template: metadata: annotations: network.alibabacloud.com/network-policy-mode: enhanced-traffic-policy labels: alibabacloud.com/acs: "true" spec: automountServiceAccountToken: false containers: - name: sandbox image: registry-cn-hangzhou.ack.aliyuncs.com/acs/acs-ephemeraljob-tools-asi:v0.6 # 替换为实际业务镜像 resources: requests: cpu: "2" memory: 2Gi limits: cpu: "2" memory: 2Gi等待 Pod 就绪,确认 SandboxSet 中的 Sandbox 处于
Running状态:kubectl get sandbox -n <YOUR_NAMESPACE>预期输出:
NAME STATUS AGE CLAIMED apikey-test-xxxxx Running 60s false apikey-test-yyyyy Running 60s false将以下内容保存为
sandboxclaim-apikey.yaml并执行kubectl apply -f命令,通过 SandboxClaim 分配一个 Sandbox 并关联 Agent 身份。apiVersion: agents.kruise.io/v1alpha1 kind: SandboxClaim metadata: name: apikey-test-claim namespace: <YOUR_NAMESPACE> spec: templateName: apikey-test replicas: 1 claimTimeout: 5m ttlAfterCompleted: 15m labels: security.agents.kruise.io/agent-name: my-agent # 关联 AgentIdentity确认其中一个 Sandbox 的
CLAIMED状态变为true:kubectl get sandbox -n <YOUR_NAMESPACE>预期输出:
NAME STATUS AGE CLAIMED apikey-test-xxxxx Running 2m true apikey-test-yyyyy Running 2m false进入已 Claim 的 Sandbox Pod,使用占位符 Token 发起请求验证 API Key 注入效果。
CLAIMED_POD=$(kubectl get sandbox -n <YOUR_NAMESPACE> \ -l agents.kruise.io/sandbox-claimed=true,agents.kruise.io/sandbox-template=apikey-test \ -o jsonpath='{.items[0].metadata.name}') kubectl exec $CLAIMED_POD -n <YOUR_NAMESPACE> -c sandbox -- \ curl -s http://httpbin.org/headers -H "Authorization: Bearer fake-token"预期输出中
Authorization头已被替换为真实 API Key:{ "headers": { "Accept": "*/*", "Authorization": "Bearer sk-xxxxxxxxxxxxxxxx", "Host": "httpbin.org", "User-Agent": "curl/7.61.1", ... } }
阿里云 STS 凭据注入模式
系统透明替换请求中的 AK/SK/STS 三元组并重新计算请求签名,Sandbox 应用使用标准阿里云 SDK 和伪造凭据即可正常调用云服务。以下为端到端操作流程,以授予集群只读权限为例。
前提条件
集群已启用 RRSA(RAM Roles for Service Account)功能(阿里云 STS 模式必需),具体操作请参见通过RRSA配置ServiceAccount的RAM权限实现Pod权限隔离。
启用 HTTPS 流量管控(阿里云 SDK 默认采用 HTTPS),并在 ack-sandbox-manager 组件的
enhancedTrafficManagement.tlsTermination.includeHosts参数中配置*.aliyuncs.com或*。
操作步骤
说明本模式依赖 ack-agent-identity 组件访问 STS 服务的
AssumeRoleWithOIDC接口获取临时凭据。请根据实际业务的 Sandbox 实例规模,前往配额中心申请AssumeRoleWithOIDC接口的访问配额,避免因配额不足导致凭据注入失败。在 RAM 控制台创建 RAM(Resource Access Management,资源访问管理)角色(如
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" }为该 RAM 角色授予所需的权限策略(如
AliyunCSReadOnlyAccess)。将以下内容保存为
credential-provider-sts.yaml并执行 kubectl apply -f 命令,创建 CredentialProvider 引用上述 RAM 角色。policy字段定义最终颁发的 STS Token 的权限范围(必须是角色权限的子集)。apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: aliyun-cs-readonly namespace: <YOUR_NAMESPACE> spec: type: RAM ram: source: provider: RRSA rrsa: roleName: ack-agent-identity-sample-role policy: | { "Statement": [ { "Action": [ "cs:Describe*", "cs:Get*", "cs:List*" ], "Effect": "Allow", "Resource": ["*"] } ], "Version": "1" }policy支持模板变量按 Sandbox 实例动态调整权限,变量含义见CredentialProvider 模板变量。将以下内容保存为
agent-role-sts.yaml并执行 kubectl apply -f 命令,授权 Agent 身份获取该 CredentialProvider 凭据。apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentRole metadata: name: get-aliyun-sts namespace: <YOUR_NAMESPACE> spec: rules: - effect: Allow action: "GetResourceCredential" resource: "CredentialProvider/aliyun-cs-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: agentName: my-agent将以下内容保存为
security-profile-sts.yaml并执行 kubectl apply -f 命令,创建 SecurityProfile 配置 tokenTransformation 规则。apiVersion: agents.kruise.io/v1alpha1 kind: SecurityProfile metadata: name: aliyun-sts-injection namespace: <YOUR_NAMESPACE> spec: selector: matchLabels: security.agents.kruise.io/agent-name: my-agent rules: - name: inject-aliyun-sts match: - domains: - "*.aliyuncs.com" actions: tokenTransformation: type: AliyunSTS credentialRef: kind: CredentialProvider name: aliyun-cs-readonly关键字段说明请参见tokenTransformation 字段说明。
将以下内容保存为
sandboxset-sts.yaml并执行 kubectl apply -f 命令,创建 SandboxSet 并在环境变量中配置伪造的 AK/SK(Sandbox 内的阿里云 SDK 使用这些伪造凭据发起请求,网关在转发时替换为真实凭据)。apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet metadata: name: sts-test namespace: <YOUR_NAMESPACE> spec: replicas: 2 runtimes: - name: csi - name: agent-runtime template: metadata: annotations: network.alibabacloud.com/network-policy-mode: enhanced-traffic-policy labels: alibabacloud.com/acs: "true" spec: automountServiceAccountToken: false containers: - name: sandbox image: registry-cn-hangzhou.ack.aliyuncs.com/acs/acs-ephemeraljob-tools-asi:v0.6 # 替换为实际业务镜像 env: - name: ALIBABA_CLOUD_ACCESS_KEY_ID value: "FAKE_AK" # 伪造 AK,网关自动替换 - name: ALIBABA_CLOUD_ACCESS_KEY_SECRET value: "FAKE_SK" # 伪造 SK,网关自动替换 - name: ALIBABA_CLOUD_REGION value: "cn-hangzhou" # 替换为实际地域 resources: requests: cpu: "2" memory: 2Gi limits: cpu: "2" memory: 2Gi等待 Pod 就绪,确认 Sandbox 处于
Running状态:kubectl get sandbox -n <YOUR_NAMESPACE>预期输出:
NAME STATUS AGE CLAIMED sts-test-xxxxx Running 60s false sts-test-yyyyy Running 60s false将以下内容保存为
sandboxclaim-sts.yaml并执行 kubectl apply -f 命令,通过 SandboxClaim 分配一个 Sandbox 并关联 Agent 身份。apiVersion: agents.kruise.io/v1alpha1 kind: SandboxClaim metadata: name: sts-test-claim namespace: <YOUR_NAMESPACE> spec: templateName: sts-test replicas: 1 claimTimeout: 5m ttlAfterCompleted: 15m labels: security.agents.kruise.io/agent-name: my-agent # 关联 AgentIdentity确认其中一个 Sandbox 的
CLAIMED状态变为true,并检查 Token 签发状态:CLAIMED_POD=$(kubectl get sandbox -n <YOUR_NAMESPACE> \ -l agents.kruise.io/sandbox-claimed=true,agents.kruise.io/sandbox-template=sts-test \ -o jsonpath='{.items[0].metadata.name}') kubectl get sandbox $CLAIMED_POD -n <YOUR_NAMESPACE> -o yaml | grep token-status预期输出包含 Token 过期时间信息:
security.agents.kruise.io/token-status: '{"accessTokenExpiration":"2026-06-05T04:41:40Z"}'进入已 Claim 的 Sandbox Pod,安装阿里云 CLI 并使用伪造凭据验证 STS 凭据注入效果。
kubectl exec -it $CLAIMED_POD -n <YOUR_NAMESPACE> -c sandbox -- bash在 Sandbox 中执行:
# 1. 安装阿里云 CLI /bin/bash -c "$(curl -fsSL https://aliyuncli.alicdn.com/install.sh)" # 2. 配置伪造凭据 mkdir -p ~/.aliyun cat > ~/.aliyun/config.json << 'EOF' { "current": "default", "profiles": [{ "name": "default", "mode": "AK", "access_key_id": "FAKE_AK", "access_key_secret": "FAKE_SK", "region_id": "cn-hangzhou", "output_format": "json", "language": "en" }] } EOF # 3. 调用 CS API(已授权,预期成功) aliyun cs GET /api/v1/clusters预期返回正常的集群列表 JSON 响应,说明伪造凭据已被网关透明替换为通过 STS AssumeRole 获取的真实临时凭据。
tokenTransformation 字段说明
本节集中说明 tokenTransformation 规则的 CRD 字段、CredentialProvider 模板变量、阿里云 STS 模式支持的签名方式,供配置 SecurityProfile 时查阅。
CRD 字段
actions:
tokenTransformation:
disabled: false # 可选,临时禁用
failStrategy: Block # 可选,失败策略:Block(默认) / Allow
type: ApiKey | AliyunSTS # 必填,注入模式
credentialRef: # 必填,凭据来源
kind: CredentialProvider # CredentialProvider 或 Secret
name: <name> # 资源名称
namespace: <ns> # 可选,默认同 SecurityProfile 命名空间
# ApiKey 模式专用(type=ApiKey 时必填)
apiKey:
when: # 可选,注入前置条件
header: Authorization # 检查的请求头
pattern: "^Bearer .+" # RE2 正则
targetHeader: Authorization # 目标请求头,默认 Authorization
valueTemplate: "Bearer {{ .Token }}" # 值模板字段 | 说明 |
| 注入模式: |
| 设为 |
| 凭据获取或签名失败时的处理策略: |
| 凭据来源类型: |
| 引用的 CredentialProvider 或 Secret 名称。 |
| 注入前置条件:指定检查的请求头与 RE2 正则,匹配时才执行注入。 |
| 目标请求头(被替换的头),默认 |
| Go text/template 格式的值模板, |
CredentialProvider 模板变量
CredentialProvider 的 policy 与 secretRef.name 字段支持模板变量,引用 Sandbox 实例身份所关联的上下文信息,按 Sandbox 实例动态调整权限范围或引用不同 Secret。
模板变量 | 说明 |
| Sandbox 实例身份关联的 AgentIdentity CR 名称,通过 Label |
| Sandbox 实例身份关联的用户自定义 metadata 特定 Key 的值, |
以下示例通过 SandboxClaim 的 labels 传入 OSS bucket 与子路径,在 CredentialProvider policy 中按实例动态收敛 OSS 权限:
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: my-claim
namespace: <YOUR_NAMESPACE>
spec:
templateName: my-sandbox-set
replicas: 1
labels:
security.agents.kruise.io/agent-name: my-agent
# 以下 label 可在 policy 模板中通过 ${ack:agent-identity/metadata/KEY} 引用
security.agents.kruise.io/oss-bucket-name: my-bucket
security.agents.kruise.io/oss-subpath: user-data{
"Action": ["oss:Get*", "oss:List*"],
"Effect": "Allow",
"Resource": [
"acs:oss:*:*:${ack:agent-identity/metadata/oss-bucket-name}/${ack:agent-identity/metadata/oss-subpath}/*"
]
}阿里云 STS 模式支持的签名方式
系统自动检测请求使用的签名方式,无需手动指定;支持 Go、Java、Python、Node.js 等各语言阿里云 SDK 发出的标准签名请求。当请求不包含可识别的阿里云签名特征时,tokenTransformation 动作将被跳过,请求按正常流程放行或匹配后续规则。
签名版本 | 签名算法 | 典型 SDK 版本 | 识别特征 |
V3(ACS3-HMAC-SHA256) | HMAC-SHA256 | 阿里云 SDK 2.0 及以上(V2 SDK) |
|
V1 RPC(HMAC-SHA1) | HMAC-SHA1 | V1 SDK RPC 风格 | 查询参数包含 |
V1 ROA(HMAC-SHA1) | HMAC-SHA1 | V1 SDK ROA 风格 |
|
OSS V4(OSS4-HMAC-SHA256) | HMAC-SHA256 | OSS SDK V4 签名 |
|
使用限制
限制项 | 说明 |
阿里云 STS 模式必须启用 HTTPS 流量管控 | 阿里云 SDK 默认使用 HTTPS,需配置 TLS 终止才能拦截并改写请求。 |
阿里云 STS 模式不支持 OSS V1 签名 | 使用 OSS V1(旧版)签名的请求无法被识别和重签名。 |
阿里云 STS 模式不支持 SLS 私有签名 | SLS 服务使用非标准签名方式,当前不支持。 |
凭据替换仅作用于出口方向 | 仅对通过 egress-gateway 转发的请求生效。 |
单个规则仅支持一个 tokenTransformation | 如需对不同域名注入不同凭据,请创建多条规则。 |
API Key 模式 | 最大 1024 字符。 |
常见问题
凭据注入不生效,请求仍然使用原始凭据?
按以下步骤排查:
确认 Sandbox 已通过 SandboxClaim 关联正确的
security.agents.kruise.io/agent-name标签。确认 SecurityProfile 的
selector.matchLabels与 Sandbox Pod 标签匹配。确认 AgentRole 与 AgentRoleBinding 已正确授权访问对应的 CredentialProvider。
阿里云 STS 模式下,确认已启用 HTTPS 流量管控且
includeHosts包含目标域名(如*.aliyuncs.com)。查看 traffic-extension 组件日志,确认是否有错误输出。
kubectl logs -l app.kubernetes.io/name=traffic-extension -n sandbox-traffic-system
请求返回签名错误(SignatureDoesNotMatch)?
根据以下不同场景进行排查。
请求使用了不支持的签名方式(如 OSS V1、SLS 私有签名)。检查请求的
Authorization头格式是否在阿里云 STS 模式支持的签名方式列表中。配置了
type: ApiKey但目标是阿里云 API。ApiKey 模式仅做 header 替换,不会重新签名,应改用type: AliyunSTS。