动态创建的 Agent Sandbox 实例需要持久化读写 OSS 存储时,为消除容器内留存长期密钥的安全隐患,可创建声明 Agent Identity 认证的 PV 卷并配合 SandboxClaim 挂载,利用临时凭据实现按需授权与 OSS 目录挂载。
背景信息
相比传统AccessKey方式将长期静态凭据挂载到Sandbox(所有Sandbox共享同一组AK/SK,权限无法收缩到实例维度),Agent Identity通过ack-agent-identity组件为每个Sandbox签发独立身份,动态获取短期STS(Security Token Service,安全令牌服务)临时凭据,实现Sandbox级别的精细化权限隔离,且Sandbox内不留存任何长期密钥。
Agent Identity采用两层权限模型:
第一层:RAM角色权限(最大权限边界)。在RAM控制台创建,覆盖所有Sandbox可能访问的Bucket范围,由管理员一次性配置。
第二层:CredentialProvider策略(实际生效权限)。在集群内通过
CredentialProviderCR(Custom Resource,自定义资源)定义,必须是第一层的子集,支持模板函数按每个Sandbox声明的Bucket和子路径动态收缩。
每个 Sandbox 最终获取的 STS 凭据权限,为 RAM 角色权限与 CredentialProvider 策略的交集。此外,该权限的生效范围仅限于该 Sandbox 声明的 Bucket 及其子路径。
适用范围
已完成Agent Sandbox的基础环境搭建。具体操作,请参见创建Agent Sandbox。
已在集群组件管理中安装或升级并配置以下组件:
ack-agent-identity≥ v0.4.0,并勾选agentTokenDelegation配置项。ack-agent-sandbox-controller≥ v0.5.22-release.1,并勾选identityProvider配置项。由于组件运行及配置沙箱时需要依赖 csi-agent、csi-plugin 以及 agent-runtime 镜像,建议提前配置好镜像缓存,避免扩容耗时。
ack-sandbox-manager≥ v0.6.8,并勾选identityProvider配置项。
已在集群集群信息页的基本信息页签中的安全与审计区域开启RRSA OIDC,并已记录供应商URL和供应商ARN,用于后续RAM角色信任策略配置。具体操作,请参考启用RRSA功能。
其他功能使用限制,可参考后文使用限制。
网络放行配置
Sandbox访问Credential Provider获取STS凭据、访问OSS Endpoint读写数据均需要显式放行。使用TrafficPolicy控制Pod层出入方向流量,使用安全组控制ECS网卡层流量,二者需同步配置。
步骤一:创建RAM角色并配置信任策略
Agent Identity组件依赖RRSA(RAM Roles for Service Account,服务账户角色)扮演RAM角色获取STS临时凭据。此处配置的RAM角色权限是最大权限边界,实际每个Sandbox获得的权限还会被步骤二的CredentialProvider策略进一步收缩。建议将此角色配置为覆盖所有Sandbox可能访问的Bucket范围。
在目标集群信息页的基本信息页签中的安全与审计区域开启RRSA OIDC。
将鼠标悬浮至RRSA OIDC右侧已开启上面,即可查看提供商的URL链接和ARN信息。

访问RAM控制台-创建角色页面,选择信任主体类型为身份提供商类型,替换以下模板中的
<oidc_issuer_url>为提供商 URL,<oidc_provider_arn>为提供商 ARN:重要在大规模应用场景下,为避免STS Token反复轮转,建议在角色创建完成后,在角色详情页更改最大会话时间,调整至1小时以上。
若当前RAM用户没有创建角色或策略的相关权限,请联系阿里云账号管理员为当前用户授予
AliyunRAMFullAccess等相关权限。详细操作,请参考为RAM用户新增授权。{ "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" }oidc:sub中的ack-agent-identity:credential-provider是ack-agent-identity组件使用的ServiceAccount,不支持自定义。为该RAM角色创建自定义权限策略。根据业务需求选择只读或读写策略,将
<YOUR-BUCKET-NAME>替换为实际的Bucket名称,如需覆盖多个Bucket可使用通配符或列举多个Resource。只读策略
{ "Statement": [ { "Action": [ "oss:GetObject", "oss:ListObjects" ], "Effect": "Allow", "Resource": [ "acs:oss:*:*:<YOUR-BUCKET-NAME>", "acs:oss:*:*:<YOUR-BUCKET-NAME>/*" ] } ], "Version": "1" }读写策略
{ "Statement": [ { "Action": [ "oss:GetObject", "oss:PutObject", "oss:DeleteObject", "oss:AbortMultipartUpload", "oss:ListMultipartUploads", "oss:ListObjects" ], "Effect": "Allow", "Resource": [ "acs:oss:*:*:<YOUR-BUCKET-NAME>", "acs:oss:*:*:<YOUR-BUCKET-NAME>/*" ] } ], "Version": "1" }访问RAM控制台-角色页面,在RAM角色列表的操作列,单击目标角色对应的新增授权,将上一步创建的权限策略授权给该RAM角色。
步骤二:创建Agent Identity相关CR
创建AgentIdentity、CredentialProvider、AgentRole、AgentRoleBinding四种CR,完成Sandbox身份与凭据的授权绑定。
将以下YAML保存为
agent-identity.yaml,定义Agent身份标识:apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentIdentity metadata: name: my-storage-agent # Agent身份名称 namespace: <YOUR-NAMESPACE> spec: description: "用于OSS存储挂载的Agent身份"将以下YAML保存为
credential-provider.yaml,定义每个Sandbox实际获得的STS凭据权限范围。CredentialProvider的策略必须是步骤一RAM角色权限的子集,超出部分不会生效。可按业务场景创建多个CredentialProvider作为不同的权限模板,本文提供只读和读写两种通用模板。将
<YOUR-RAM-ROLE-NAME>替换为步骤一创建的RAM角色名称:只读CredentialProvider
apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: oss-ro # 只读场景的CredentialProvider namespace: <YOUR-NAMESPACE> spec: type: RAM ram: source: provider: RRSA rrsa: roleName: <YOUR-RAM-ROLE-NAME> tokenValidity: 1h policy: | { "Statement": [ { "Action": [ "oss:GetObject" ], "Effect": "Allow", "Resource": {{ build_policy_oss_resource() }} }, { "Action": [ "oss:ListObjects" ], "Effect": "Allow", "Resource": {{ build_policy_oss_resource(limit_sub_path=false) }}, "Condition": { "StringLike": { "oss:Prefix": {{ build_policy_oss_prefix_condition() }} } } } ], "Version": "1" }ListObjects是Bucket级别的操作,需通过oss:PrefixCondition限制只能列举指定子路径下的对象,否则Sandbox可列举整个Bucket的内容。读写CredentialProvider
apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: oss-rw # 读写场景的CredentialProvider namespace: <YOUR-NAMESPACE> spec: type: RAM ram: source: provider: RRSA rrsa: roleName: <YOUR-RAM-ROLE-NAME> tokenValidity: 1h policy: | { "Statement": [ { "Action": [ "oss:GetObject", "oss:PutObject", "oss:DeleteObject", "oss:AbortMultipartUpload", "oss:ListMultipartUploads" ], "Effect": "Allow", "Resource": {{ build_policy_oss_resource() }} }, { "Action": [ "oss:ListObjects" ], "Effect": "Allow", "Resource": {{ build_policy_oss_resource(limit_sub_path=false) }}, "Condition": { "StringLike": { "oss:Prefix": {{ build_policy_oss_prefix_condition() }} } } } ], "Version": "1" }CredentialProvider策略中使用的模板函数由sandbox-controller根据每个Sandbox实例的挂载配置自动填充,详细说明请参见本文CredentialProvider策略模板函数说明。
将以下YAML保存为
agent-role.yaml,通过AgentRole引用所有存储相关的CredentialProvider,并通过AgentRoleBinding将角色绑定到Agent身份:apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentRole metadata: name: oss-storage-role namespace: <YOUR-NAMESPACE> spec: rules: - effect: Allow action: "GetResourceCredential" resource: "CredentialProvider/oss-ro" # 引用只读CredentialProvider - effect: Allow action: "GetResourceCredential" resource: "CredentialProvider/oss-rw" # 引用读写CredentialProvider --- apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentRoleBinding metadata: name: my-agent-oss-binding namespace: <YOUR-NAMESPACE> spec: agentRoleRef: apiGroup: agentidentity.alibabacloud.com kind: AgentRole name: oss-storage-role subjects: - authorizationType: "Agent" agentAuthorizationConfiguration: agentName: my-storage-agent # 与AgentIdentity name一致依次应用以上所有YAML文件:
kubectl apply -f agent-identity.yaml kubectl apply -f credential-provider.yaml kubectl apply -f agent-role.yaml
步骤三:配置SandboxSet和创建PV
在SandboxSet中启用CSI和agent-runtime能力,并创建声明authType: agent-identity的PersistentVolume对象。
将以下YAML保存为
sandboxset.yaml(注意dnsPolicy必须为ClusterFirst),执行kubectl apply -f sandboxset.yaml进行应用:apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet metadata: name: code-interpreter-ossfs-agent-identity namespace: default spec: replicas: 3 runtimes: - name: csi # 启用CSI挂载能力 - name: agent-runtime # 注入envd等环境管理工具 template: metadata: annotations: network.alibabacloud.com/wait-clusterip-ready: "*" labels: alibabacloud.com/acs: "true" alibabacloud.com/compute-class: agent-sandbox alibabacloud.com/compute-qos: default spec: automountServiceAccountToken: false dnsPolicy: ClusterFirst # 必须为ClusterFirst containers: - image: registry-cn-hangzhou-vpc.ack.aliyuncs.com/acs/code-interpreter:v1.6 imagePullPolicy: IfNotPresent name: sandbox resources: requests: cpu: "1" memory: 1Gi limits: cpu: "1" memory: 1Gi terminationGracePeriodSeconds: 30建议启用
network.alibabacloud.com/wait-clusterip-ready注解,确保Sandbox执行动态存储挂载时能够准确解析到Credential Provider和存储服务端的地址。将以下YAML保存为
oss-pv.yaml,替换Bucket名称、Region和Endpoint为实际值,执行kubectl apply -f oss-pv.yaml创建资源。Agent Identity方式下PV无需
nodePublishSecretRef,也无需创建Secret。apiVersion: v1 kind: PersistentVolume metadata: labels: alicloud-pvname: oss-pv-sandbox-system name: oss-pv-sandbox-system spec: accessModes: - ReadWriteMany capacity: storage: 50Gi csi: driver: ossplugin.csi.alibabacloud.com volumeAttributes: authType: agent-identity # 固定值,声明使用Agent Identity认证 bucket: <YOUR-BUCKET-NAME> # 替换为实际Bucket名称 url: https://oss-cn-hangzhou-internal.aliyuncs.com # 替换为实际Endpoint,建议使用HTTPS内网端点 path: / otherOpts: "-o sigv4 -o region=cn-hangzhou -o umask=022 -o allow_other" # 使用签名版本4,region按实际替换 volumeHandle: oss-pv-sandbox-system # 必须与PV的名称一致。 persistentVolumeReclaimPolicy: Retain volumeMode: Filesystem重要PV的
volumeAttributes创建后不可修改。如需变更鉴权方式,需删除并重建PV。此操作会导致未升级的Sandbox OSS访问失败,请谨慎操作。关键字段说明如下:
参数
说明
authType固定为
agent-identity,表示使用Agent Identity认证。bucket待挂载的OSS Bucket名称。
urlOSS访问域名(Endpoint)。内网格式:
https://oss-{region}-internal.aliyuncs.com,建议使用HTTPS端点。otherOptsossfs挂载选项。使用签名版本4时须包含
-o sigv4和-o region=<YOUR-REGION>。path挂载点相对于Bucket根目录的路径,默认为
/。
步骤四:挂载存储卷
在Sandbox上指定挂载配置时,需通过attributes.credentialProviderName指定使用的CredentialProvider,并通过security.agents.kruise.io/agent-name关联步骤二创建的AgentIdentity。ACS支持以下两种触发挂载的方式:
通过E2B SDK挂载
使用e2b.agents.kruise.io/csi-volume-config参数以JSON数组格式指定挂载配置。注意:security.agents.kruise.io/agent-name配置必须与AgentIdentity名称完全一致:
import json
from e2b_code_interpreter import Sandbox
sbx = Sandbox.create(
template="code-interpreter-ossfs-agent-identity",
timeout=600,
metadata={
"e2b.agents.kruise.io/csi-volume-config": json.dumps([
{
"pvName": "oss-pv-sandbox-system",
"mountPath": "/data-oss",
"subPath": "user-a-data",
"attributes": {
"credentialProviderName": "oss-ro"
}
}
]),
"security.agents.kruise.io/agent-name": "my-storage-agent"
}
)
print(f"sandbox id: {sbx.sandbox_id}")通过SandboxClaim挂载
在SandboxClaim的spec.dynamicVolumesMount字段声明挂载卷列表。注意:security.agents.kruise.io/agent-name配置必须与AgentIdentity名称完全一致。以下示例演示2个只读子目录和1个读写子目录的混合权限挂载:
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: code-interpreter-claim
namespace: default
spec:
templateName: code-interpreter-ossfs-agent-identity # 关联的SandboxSet名称
replicas: 1
claimTimeout: 5m
ttlAfterCompleted: 15m
annotations:
# 必须与AgentIdentity名称完全一致
security.agents.kruise.io/agent-name: my-storage-agent
dynamicVolumesMount:
# 公司只读子目录1
- pvName: oss-pv-sandbox-system
mountPath: "/office-skill-readonly"
subPath: "office-skill-readonly"
readOnly: true
attributes:
credentialProviderName: "oss-ro"
# 公司只读子目录2
- pvName: oss-pv-sandbox-system
mountPath: "/bu-office-skill-sub"
subPath: "bu-office-skill-sub-readonly"
readOnly: true
attributes:
credentialProviderName: "oss-ro"
# 每个用户独立的读写子目录
- pvName: oss-pv-sandbox-system
mountPath: "/user-owner-dir-rw"
subPath: "user-a-owner-dir-rw"
attributes:
credentialProviderName: "oss-rw"挂载字段说明如下:
字段 | 类型 | 说明 |
| String | PersistentVolume对象名称。 |
| String | 挂载到容器内的目录路径,必须为一个空目录。 |
| String | 远端存储的子目录名(相对路径),可选。 |
| Boolean | 是否以只读方式挂载,可选,默认为 |
| String | 指定该挂载点使用的CredentialProvider名称。Agent Identity方式下必填。 |
步骤五:验证挂载结果
Sandbox创建成功后,
status变为Running即表示Claim与挂载流程已完成。查询已分配出的Sandbox:kubectl get sandbox -n default -l agents.kruise.io/claim-name=code-interpreter-claim预期输出:
NAME STATUS AGE CLAIMED code-interpreter-ossfs-agent-identity-6vh94 Running 22h true替换
<POD_NAME>为已分配Sandbox对应的Pod名称,进入容器验证挂载目录可正常列举文件:kubectl exec -it <POD_NAME> -- ls /data-oss kubectl exec -it <POD_NAME> -- sh -c "echo 'hello agent identity' > /data-oss/test.txt && cat /data-oss/test.txt"若
ls可正常列出OSS Bucket子目录下的文件,且无法写入文件(上一步通过E2B SDK挂载仅配置只读权限),即表示Agent Identity认证的OSS存储卷挂载生效。
使用限制
支持基于E2B的
Create接口、休眠或唤醒功能以及原地升级镜像后的运行时存储挂载。Sandbox需使用
dnsPolicy: ClusterFirst以便解析Credential Provider服务域名。在配置网络策略或流量策略时,请务必放行访问OSS Endpoint、CoreDNS及Credential Provider服务的出方向流量。
对于单文件并发写场景,OSS的"覆盖上传"特性可能导致数据覆盖,需在应用层保障数据一致性。
初次对大量文件执行
readdir操作时,ossfs会一次性加载全部元信息,可能导致进程OOM(Out Of Memory,内存溢出)。建议挂载Bucket子目录而非根目录。请根据Sandbox实例规模,前往配额中心申请
AssumeRoleWithOIDC接口的访问配额,避免因配额不足导致凭据获取失败。CSI(Container Storage Interface,容器存储接口)动态挂载依赖特权容器和宿主机路径(
hostPath: /var/run/csi)权限,会打破标准容器安全边界。请遵循以下最佳实践:仅在确需动态挂载时启用,共享存储卷默认使用只读挂载,配合TrafficPolicy和安全组做补偿控制,OSS挂载统一使用HTTPS Endpoint。
非root用户挂载配置(mTLS增强模式)
在安全要求更高的场景中,业务容器支持以非root用户身份运行进程,同时通过mTLS(mutual TLS,双向TLS认证)加强Sandbox Manager与Runtime之间的通信安全。mTLS模式下,CSI Socket不再暴露给业务容器,IdToken等配置信息也被从业务容器内移除,进一步收窄攻击面。
组件版本要求
mTLS增强模式需要以下组件版本:
ack-agent-sandbox-controller≥ v0.6.4-release.1ack-sandbox-manager≥ v0.6.10ack-agent-identity≥ v0.4.2
组件配置
在
ack-agent-sandbox-controller组件配置中,勾选identityProvider和enableRuntimeTLS配置项,表示开启基于mTLS的访问方式,加强安全访问链路。在
ack-sandbox-manager组件配置中,打开Whether to enable mTLS authentication for manager<->runtime communication.开关。
非root场景使用限制
以非root用户身份在业务容器中运行进程时,存储挂载存在以下额外限制:
限制一:挂载目录必须为当前用户可写
当业务容器内进程由非root用户拉起时,所配置的按需挂载目录必须是该非root用户具有写权限的目录。例如,若以UID 1000运行,该用户可写/workspace目录,则挂载点必须设置在/workspace目录下,否则挂载将失败。
限制二:OSS存储需调整挂载点文件系统权限
非root用户场景下,需要调整OSS挂载点文件系统权限,使非root用户具有OSS存量数据的文件系统权限。例如,通过将umask参数设置为000,可将文件系统权限设置为777。也可按需调整为其他权限,完整的挂载点权限配置说明请参见挂载点权限配置。建议单独创建一个PersistentVolume对象,避免与其他PV冲突。
PV配置示例如下:
apiVersion: v1
kind: PersistentVolume
metadata:
labels:
alicloud-pvname: oss-pv-sandbox-system
name: oss-pv-sandbox-system
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 50Gi
csi:
driver: ossplugin.csi.alibabacloud.com
volumeAttributes:
authType: agent-identity # 固定值,声明使用Agent Identity认证
bucket: <YOUR-BUCKET-NAME> # 替换为实际Bucket名称
url: https://oss-cn-hangzhou-internal.aliyuncs.com # 替换为实际Endpoint,建议使用HTTPS内网端点
path: /
otherOpts: "-o sigv4 -o region=cn-hangzhou -o umask=000 -o allow_other" # umask设置为000
volumeHandle: oss-pv-sandbox-system # 必须与PV的名称一致
persistentVolumeReclaimPolicy: Retain
storageClassName: test
volumeMode: Filesystem设置umask=000后,挂载目录的文件权限将对所有用户开放。整体的OSS挂载权限控制仍然基于Agent Identity能力,通过CredentialProvider策略将挂载点锁定在用户所配置的子目录范围内。
CredentialProvider策略模板函数说明
CredentialProvider的policy字段支持以下专用模板函数,由sandbox-controller根据每个Sandbox实例的挂载配置自动填充,无需为每个子路径单独创建CredentialProvider。
模板函数 | 说明 |
| 按Sandbox实例的挂载配置自动填充限制到子路径维度的 示例结果: |
| 按Sandbox实例的挂载配置自动填充限制到Bucket维度的 示例结果: |
| 按Sandbox实例的挂载配置自动填充限制到子路径前缀维度的 示例结果: |
常见问题
Agent Identity 挂载 OSS 的完整链路可以拆解为三层:Sandbox 通过网络访问 CredentialProvider → CredentialProvider 签发 STS Token → 使用 Token 访问 OSS。三层问题的定位方式和排查手段各不相同,可按以下顺序逐层排查。
通用排查命令
# 查看 token 签发状态
kubectl get pod <POD_NAME> -n <namespace> -o jsonpath='{.metadata.annotations.security\.agents\.kruise\.io/token-status}'
# 查看 csi-agent-sidecar 日志,定位 ossfs 具体报错
kubectl -n <namespace> logs <POD_NAME> -c csi-agent-sidecar
# 在 Sandbox 内验证与 CredentialProvider 的连通性
telnet credential-provider.ack-agent-identity.svc 8443挂载异常时如何开启调试日志?
如果发现挂载异常,可通过临时开启ossfs调试日志定位问题。执行kubectl edit pv <PV_NAME>,在spec字段下追加以下mountOptions配置,然后重新创建Sandbox:
spec:
mountOptions:
- dbglevel=debug
- curldbg开启后,csi-agent-sidecar容器日志会全量输出,便于排查问题。问题恢复后,再次编辑PV删除上述调试选项,避免生产环境产生过多日志。
第一层:Sandbox 无法访问 CredentialProvider(网络不通)
现象
csi-agent-sidecar 或 ossfs 日志中出现网络访问超时、DNS 解析失败或连接被拒绝,典型报错如下:
"ossfs exited with error" err="signal: terminated"Sandbox 已 Running 但挂载目录未生成,或挂载超时失败。
排查步骤
在 Sandbox 内执行
telnet credential-provider.ack-agent-identity.svc 8443,根据返回结果定位问题:报
could not resolve host:DNS 解析问题,进入步骤 2。报
Connection refused或Connection timed out:网络出方向被拦截,进入步骤 3。返回
Connected to ...:网络层正常,跳转至第二层排查。
排查 DNS 解析:
检查 SandboxSet 定义:
spec.template.spec.dnsPolicy必须为ClusterFirst,且spec.template.metadata.annotations包含network.alibabacloud.com/wait-clusterip-ready: "*"。检查 CoreDNS 状态:
kubectl -n kube-system get pod -l k8s-app=kube-dns。参考网络放行配置章节,确认 TrafficPolicy 已放行
kube-system/kube-dns,安全组出方向已放行 TCP/UDP 53。
排查网络出方向:
参考网络放行配置章节,确认 TrafficPolicy 已放行到
ack-agent-identity/credential-provider的出方向流量。确认安全组出方向已放行 TCP/8443 到集群托管组件网段。
第二层:CredentialProvider 服务签发 Token 失败
现象
Sandbox 已能访问 CredentialProvider 服务,但服务本身返回错误或未正常运行。csi-agent-sidecar 日志中出现 Token 获取失败报错:
Security Token refresh failed排查步骤
参考组件配置章节,确认
ack-agent-identity、ack-agent-sandbox-controller及ack-sandbox-manager组件版本和配置勾选情况。检查 Pod 是否携带
token-statusannotation:kubectl get pod <POD_NAME> -n <namespace> -o jsonpath='{.metadata.annotations.security\.agents\.kruise\.io/token-status}'无输出:Sandbox 创建时未传入
security.agents.kruise.io/agent-name,或该 annotation 未透传到 Pod。请核对 SandboxClaim 的spec.annotations或 E2B SDKSandbox.create的metadata参数中是否包含security.agents.kruise.io/agent-name。有输出但状态异常:传入的
agent-name与集群内AgentIdentity资源不匹配(区分大小写),请核对两者名称完全一致。
若日志出现
AssumeRoleWithOIDC相关错误,前往 RAM 控制台核对:目标角色信任策略中
oidc:iss与集群提供商 URL 完全一致。oidc:sub为system:serviceaccount:ack-agent-identity:credential-provider,不支持自定义。oidc:aud为sts.aliyuncs.com。Principal.Federated为集群提供商 ARN。
详细配置方法请参见步骤一:创建RAM角色并配置信任策略。
若并发创建大量 Sandbox 时出现偶发失败,请前往配额中心申请
AssumeRoleWithOIDC接口的访问配额。
第三层:使用 STS Token 访问 OSS 被拒绝
现象
Sandbox 已 Running,token 签发正常,但读写挂载目录中的文件时被拒绝,csi-agent-sidecar 日志出现以下报错:
Invalid Credentials(host=xxxx message=xxx.)常见报错信息如下:
You have no right to access...:CredentialProvider 引用的 RAM 角色本身权限不足,最终 Token 缺少目标 Bucket 或对象的访问权限。Access denied by authorizer's policy:CredentialProvider Policy 渲染问题,最终生效的 Policy 未包含请求操作所需的 Action/Resource。
排查步骤
RAM 角色权限不足:
前往 RAM 控制台,找到步骤一创建的 RAM 角色,核对其权限策略是否同时包含 Bucket 级和 Object 级资源:
"Resource": [ "acs:oss:*:*:<YOUR-BUCKET-NAME>", "acs:oss:*:*:<YOUR-BUCKET-NAME>/*" ]确认权限策略的
Action覆盖 Sandbox 实际执行的操作。例如写入操作需要包含oss:PutObject,删除操作需要包含oss:DeleteObject,列举操作需要包含oss:ListObjects。完整策略示例请参见步骤一:创建RAM角色并配置信任策略。确认 RAM 角色权限策略已通过新增授权成功绑定到目标角色。
CredentialProvider Policy 渲染问题:
核对 CredentialProvider 的
policy中声明的Action是否覆盖 Sandbox 实际执行的操作。CredentialProvider 与 RAM 角色策略的交集才是最终生效权限,任一层缺失都会导致拒绝。若为只读挂载执行写入报错,将挂载配置中的
credentialProviderName改为读写模板(如oss-rw),并去掉readOnly: true。确认 CredentialProvider 的
policy中正确使用了模板函数:对象级操作(如
GetObject、PutObject)的Resource应使用{{ build_policy_oss_resource() }}。Bucket 级操作(如
ListObjects)的Resource应使用{{ build_policy_oss_resource(limit_sub_path=false) }},并通过oss:PrefixCondition 限制子路径前缀。
模板函数的详细说明请参见CredentialProvider策略模板函数说明。
确认 SandboxClaim 或 E2B SDK 声明的
subPath与预期访问路径一致。模板函数会根据每个 Sandbox 实例声明的bucket和subPath自动填充Resource,声明错误会导致最终 Policy 与实际访问路径不匹配。