Mount OSS storage for an Agent Sandbox by using Agent Identity
To give dynamically created Agent Sandbox instances persistent read/write access to Object Storage Service (OSS), create a PersistentVolume (PV) with Agent Identity authentication and mount it through a SandboxClaim. Temporary Security Token Service (STS) credentials replace long-term keys, enabling sandbox-level permission isolation.
Background information
The traditional AccessKey approach mounts a single long-term key pair to all sandboxes. Permissions cannot be scoped to individual instances. Agent Identity uses the ack-agent-identity
add-on to assign each sandbox an independent identity instead. Each sandbox dynamically obtains short-lived STS credentials, enabling sandbox-level fine-grained permission isolation without storing any long-term credentials inside the sandbox.
Agent Identity uses a two-layer permission model:
-
Layer 1: Resource Access Management (RAM) role permissions (maximum permission boundary). Created in the RAM console, this layer covers the full range of buckets that all sandboxes may access. An administrator configures this layer once.
-
Layer 2: CredentialProvider policy (effective permissions). Defined in the cluster through a
CredentialProvidercustom resource (CR), this policy must be a subset of Layer 1. Template functions dynamically narrow the policy per sandbox based on the declared bucket and subpath.
The STS credentials that each sandbox ultimately obtains represent the intersection of the RAM role permissions and the CredentialProvider policy. The effective scope is further limited to the bucket and subpath declared by that sandbox.
Prerequisites
-
The basic environment for Agent Sandbox is set up. For more information, see Create an Agent Sandbox.
-
The following add-ons are installed or upgraded and configured on the cluster Add-ons page:
-
ack-agent-identityv0.4.0 or later, with the agentTokenDelegation option selected. -
ack-agent-sandbox-controllerv0.5.22-release.1 or later, with the identityProvider option selected.The add-on runtime and sandbox configuration depend on the csi-agent, csi-plugin, and agent-runtime images. Configure image caches in advance to avoid prolonged scale-out times.
-
ack-sandbox-managerv0.6.8 or later, with the identityProvider option selected.
-
-
RRSA OIDC is enabled in the Security and Auditing section on the Basic Information tab of the Cluster Information page. Record the provider URL and provider ARN for later use when configuring the RAM role trust policy. For more information, see Step 1: Enable RRSA for your cluster.
For other usage limits, see Usage limits later in this topic.
Network allowlist configuration
Sandboxes need network access to both the Credential Provider (for STS credentials) and the OSS endpoint (for data). Configure both a TrafficPolicy for pod-level traffic and a security group for Elastic Compute Service (ECS) network interface-level traffic.
Step 1: Create a RAM role and configure the trust policy
The Agent Identity add-on relies on RAM Roles for Service Accounts (RRSA) to assume a RAM role and obtain STS temporary credentials. The RAM role permissions configured in this step define the maximum permission boundary. The actual permissions that each sandbox obtains are further narrowed by the CredentialProvider policy in Step 2. Configure this role to cover the full range of buckets that all sandboxes may access.
-
On the Basic Information tab of the Cluster Information page, enable RRSA OIDC in the Security and Auditing section.
Hover over the Enabled status next to RRSA OIDC to view the provider URL and ARN.

-
Go to the RAM console - Create Role page, select Principal Type as IdP Type, and replace
<oidc_issuer_url>with the provider URL and<oidc_provider_arn>with the provider ARN in the following template:ImportantIn large-scale scenarios, to avoid frequent STS token rotation, change the Max Session Duration on the Roles details page to 1 hour or more after the role is created.
If the current RAM user does not have the permissions to create roles or policies, ask the Alibaba Cloud account administrator to grant the
AliyunRAMFullAccesspermission or similar permissions to the current user. For more information, see Grant permissions to a RAM user.{ "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" }The value
ack-agent-identity:credential-providerin theoidc:subfield is the ServiceAccount used by theack-agent-identityadd-on and cannot be customized. -
Create a custom permission policy for the RAM role. Select a read-only or read/write policy based on business requirements, replace
<YOUR-BUCKET-NAME>with the actual bucket name, and use wildcards or list multiple resources to cover multiple buckets.Read-only policy
{ "Statement": [ { "Action": [ "oss:GetObject", "oss:ListObjects" ], "Effect": "Allow", "Resource": [ "acs:oss:*:*:<YOUR-BUCKET-NAME>", "acs:oss:*:*:<YOUR-BUCKET-NAME>/*" ] } ], "Version": "1" }Read/write policy
{ "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" } -
Go to the RAM console - Roles page. In the Actions column of the RAM role list, click Attach Policy for the target role to attach the permission policy created in the previous step to the RAM role.
Step 2: Create Agent Identity CRs
Create four CRs (AgentIdentity, CredentialProvider, AgentRole, and AgentRoleBinding) to complete the authorization binding between sandbox identities and credentials.
-
Save the following YAML as
agent-identity.yamlto define the agent identity:apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: AgentIdentity metadata: name: my-storage-agent # Agent identity name namespace: <YOUR-NAMESPACE> spec: description: "Agent identity for OSS storage mounting" -
Save the following YAML as
credential-provider.yamlto define the STS credential permission scope for each sandbox. The CredentialProvider policy must be a subset of the RAM role permissions in Step 1. Permissions that exceed the RAM role scope do not take effect. Create multiple CredentialProviders as permission templates to match different use cases. The following examples provide read-only and read/write templates.Replace
<YOUR-RAM-ROLE-NAME>with the RAM role name created in Step 1:Read-only CredentialProvider
apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: oss-ro # Read-only 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" }ListObjectsis a bucket-level operation. Use theoss:Prefixcondition to restrict listing to objects under the specified subpath. Otherwise, the sandbox can list the entire bucket contents.Read/write CredentialProvider
apiVersion: agentidentity.alibabacloud.com/v1alpha1 kind: CredentialProvider metadata: name: oss-rw # Read/write 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" }The template functions used in the CredentialProvider policy are automatically populated by the sandbox-controller based on the mount configuration of each sandbox instance. For more information, see CredentialProvider policy template functions in this topic.
-
Save the following YAML as
agent-role.yaml. Use an AgentRole to reference all storage-related CredentialProviders, and bind the role to the agent identity through an AgentRoleBinding: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" # Reference the read-only CredentialProvider - effect: Allow action: "GetResourceCredential" resource: "CredentialProvider/oss-rw" # Reference the read/write 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 # Must match the AgentIdentity name -
Apply all the preceding YAML files in sequence:
kubectl apply -f agent-identity.yaml kubectl apply -f credential-provider.yaml kubectl apply -f agent-role.yaml
Step 3: Configure the SandboxSet and create a PV
Enable Container Storage Interface (CSI) and agent-runtime capabilities in the SandboxSet, and create a PersistentVolume object that declares authType: agent-identity.
-
Save the following YAML as
sandboxset.yaml(note thatdnsPolicymust be set toClusterFirst), and runkubectl apply -f sandboxset.yamlto apply it:apiVersion: agents.kruise.io/v1alpha1 kind: SandboxSet metadata: name: code-interpreter-ossfs-agent-identity namespace: default spec: replicas: 3 runtimes: - name: csi # Enable CSI mount capability - name: agent-runtime # Inject envd and other environment management tools 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 # Must be set to 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: 30Enable the
network.alibabacloud.com/wait-clusterip-readyannotation to ensure that the sandbox can correctly resolve Credential Provider and storage service addresses when performing dynamic storage mounting. -
Save the following YAML as
oss-pv.yaml, replace the bucket name, region, and endpoint with actual values, and runkubectl apply -f oss-pv.yamlto create the resource.In Agent Identity mode, the PV does not require
nodePublishSecretRef, and no Secret needs to be created.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 # Fixed value. Declares Agent Identity authentication. bucket: <YOUR-BUCKET-NAME> # Replace with the actual bucket name. url: https://oss-cn-hangzhou-internal.aliyuncs.com # Replace with the actual endpoint. HTTPS internal endpoint recommended. path: / otherOpts: "-o sigv4 -o region=cn-hangzhou -o umask=022 -o allow_other" # Use signature version 4. Replace region as needed. volumeHandle: oss-pv-sandbox-system # Must match the PV name. persistentVolumeReclaimPolicy: Retain storageClassName: test volumeMode: FilesystemImportantThe
volumeAttributesof a PV cannot be modified after creation. To change the authentication method, delete and recreate the PV. This operation causes OSS access failures for sandboxes that have not been upgraded. Proceed with caution.The following table describes key fields:
Parameter
Description
authTypeSet to
agent-identityto use Agent Identity authentication.bucketThe name of the OSS bucket to mount.
urlThe OSS access endpoint. Internal network format:
https://oss-{region}-internal.aliyuncs.com. HTTPS endpoints are recommended.otherOptsossfs mount options. When using signature version 4, include
-o sigv4and-o region=<YOUR-REGION>.pathThe mount point path relative to the bucket root directory. Default value:
/.
Step 4: Mount the storage volume
When specifying mount configurations for a sandbox, use attributes.credentialProviderName to specify the CredentialProvider and security.agents.kruise.io/agent-name to associate the AgentIdentity created in Step 2. ACS supports the following two methods to trigger mounting:
Mount through E2B SDK
Use the e2b.agents.kruise.io/csi-volume-config parameter to specify mount configurations in JSON array format. The security.agents.kruise.io/agent-name value must exactly match the AgentIdentity name:
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}")
Mount through SandboxClaim
Declare the mount volume list in the spec.dynamicVolumesMount field of the SandboxClaim. The security.agents.kruise.io/agent-name value must exactly match the AgentIdentity name. The following example demonstrates a mixed-permission mount with two read-only subdirectories and one read/write subdirectory:
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: code-interpreter-claim
namespace: default
spec:
templateName: code-interpreter-ossfs-agent-identity # Name of the associated SandboxSet
replicas: 1
claimTimeout: 5m
ttlAfterCompleted: 15m
annotations:
# Must exactly match the AgentIdentity name
security.agents.kruise.io/agent-name: my-storage-agent
dynamicVolumesMount:
# Company-wide read-only subdirectory 1
- pvName: oss-pv-sandbox-system
mountPath: "/office-skill-readonly"
subPath: "office-skill-readonly"
readOnly: true
attributes:
credentialProviderName: "oss-ro"
# Company-wide read-only subdirectory 2
- pvName: oss-pv-sandbox-system
mountPath: "/bu-office-skill-sub"
subPath: "bu-office-skill-sub-readonly"
readOnly: true
attributes:
credentialProviderName: "oss-ro"
# Per-user read/write subdirectory
- pvName: oss-pv-sandbox-system
mountPath: "/user-owner-dir-rw"
subPath: "user-a-owner-dir-rw"
attributes:
credentialProviderName: "oss-rw"
The following table describes mount fields:
|
Field |
Type |
Description |
|
|
String |
The name of the PersistentVolume object. |
|
|
String |
The directory path for mounting into the container. Must be an empty directory. |
|
|
String |
The subdirectory name (relative path) in the remote storage. Optional. |
|
|
Boolean |
Specifies whether to mount in read-only mode. Optional. Default value: |
|
|
String |
The name of the CredentialProvider to use for this mount point. Required in Agent Identity mode. |
Step 5: Verify the mount result
-
After the sandbox is created, its
statuschanges toRunning, which indicates that the claim and mount process is complete. Query the allocated sandboxes:kubectl get sandbox -n default -l agents.kruise.io/claim-name=code-interpreter-claimExpected output:
NAME STATUS AGE CLAIMED code-interpreter-ossfs-agent-identity-6vh94 Running 22h true -
Replace
<POD_NAME>with the pod name of the allocated sandbox, and enter the container to verify that the mount directory can list and read/write files: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"If
lslists files in the OSS bucket subdirectory and write operations are denied (the Mount through E2B SDK example configures read-only permissions), the Agent Identity-authenticated OSS storage volume mount is working correctly.
Usage limits
-
Runtime storage mounting is supported through E2B-based
CreateAPI calls, the hibernation/wakeup feature, and in-place image upgrades. -
Sandboxes must use
dnsPolicy: ClusterFirstto resolve the Credential Provider service domain name. -
When configuring network policies or traffic policies, make sure to allow outbound traffic to the OSS endpoint, CoreDNS, and the Credential Provider service.
-
In concurrent single-file write scenarios, the overwrite-upload behavior of OSS may cause data overwriting. Ensure data consistency at the application level.
-
When the
readdiroperation is performed on a large number of files for the first time, ossfs loads all metadata at once, which may cause the process to run out of memory (OOM). Mount a bucket subdirectory instead of the root directory. -
For large-scale deployments, request a quota increase for the
AssumeRoleWithOIDCAPI in the Quota Center to prevent credential acquisition failures. -
CSI dynamic mounting relies on privileged containers and host path (
hostPath: /var/run/csi) permissions, which break the standard container security boundary. Follow these best practices: enable dynamic mounting only when required, use read-only mounting by default for shared storage volumes, use TrafficPolicy and security groups for compensating controls, and use HTTPS endpoints for all OSS mounts.
CredentialProvider policy template functions
The policy field of CredentialProvider supports the following dedicated template functions. The sandbox-controller automatically populates these functions based on the mount configuration of each sandbox instance. This eliminates the need to create a separate CredentialProvider for each subpath.
|
Template function |
Description |
|
|
Automatically populates Example output:
|
|
|
Automatically populates Example output:
|
|
|
Automatically populates Example output:
|
FAQ
Agent Identity-based OSS mounting operates in three layers: the sandbox accesses CredentialProvider over the network, CredentialProvider issues an STS token, and the STS token is used to access OSS. Each layer has distinct symptoms and troubleshooting methods. Troubleshoot layer by layer in the following order.
Common troubleshooting commands
# Check the token issuance status
kubectl get pod <POD_NAME> -n <namespace> -o jsonpath='{.metadata.annotations.security\.agents\.kruise\.io/token-status}'
# Check csi-agent-sidecar logs to locate specific ossfs errors
kubectl -n <namespace> logs <POD_NAME> -c csi-agent-sidecar
# Verify connectivity to CredentialProvider from inside the sandbox
telnet credential-provider.ack-agent-identity.svc 8443
Layer 1: Sandbox cannot access CredentialProvider (network unreachable)
Symptom
The csi-agent-sidecar or ossfs logs show network access timeout, DNS resolution failure, or connection refused errors. A typical error message is as follows:
"ossfs exited with error" err="signal: terminated"
The sandbox is in Running status but the mount directory is not created, or the mount times out.
Troubleshooting steps
-
Run
telnet credential-provider.ack-agent-identity.svc 8443from inside the sandbox. Based on the result, locate the issue:-
could not resolve host: DNS resolution issue. Go to step 2. -
Connection refusedorConnection timed out: Outbound traffic is blocked. Go to step 3. -
Connected to ...: The network layer is functioning correctly. Proceed to Layer 2 troubleshooting.
-
-
Troubleshoot DNS resolution:
-
Check the SandboxSet definition:
spec.template.spec.dnsPolicymust beClusterFirst, andspec.template.metadata.annotationsmust containnetwork.alibabacloud.com/wait-clusterip-ready: "*". -
Check the CoreDNS status:
kubectl -n kube-system get pod -l k8s-app=kube-dns. -
Refer to the Network allowlist configuration section to verify that the TrafficPolicy allows traffic to
kube-system/kube-dnsand the security group allows outbound TCP/UDP port 53.
-
-
Troubleshoot outbound traffic:
-
Refer to the Network allowlist configuration section to verify that the TrafficPolicy allows outbound traffic to
ack-agent-identity/credential-provider. -
Verify that the security group allows outbound TCP/8443 traffic to the managed component CIDR block.
-
Layer 2: CredentialProvider fails to issue a token
Symptom
The sandbox can access the CredentialProvider service, but the service returns errors or is not running correctly. The csi-agent-sidecar logs show token acquisition failures:
Security Token refresh failed
Troubleshooting steps
-
Refer to the add-on configuration section to verify the versions and configuration options of the
ack-agent-identity,ack-agent-sandbox-controller, andack-sandbox-manageradd-ons. -
Check whether the pod carries the
token-statusannotation:kubectl get pod <POD_NAME> -n <namespace> -o jsonpath='{.metadata.annotations.security\.agents\.kruise\.io/token-status}'-
No output: The
security.agents.kruise.io/agent-nameannotation was not passed when the sandbox was created, or the annotation was not propagated to the pod. Verify that themetadata.annotationsfield of the SandboxClaim or themetadataparameter in the E2B SDKSandbox.createcall containssecurity.agents.kruise.io/agent-name. -
Output with abnormal status: The
agent-namevalue does not match theAgentIdentityresource in the cluster (case-sensitive). Verify that both names are identical.
-
-
If the logs show
AssumeRoleWithOIDC-related errors, go to the RAM console and verify:-
The
oidc:issvalue in the trust policy of the target role exactly matches the provider URL of the cluster. -
The
oidc:subvalue issystem:serviceaccount:ack-agent-identity:credential-provider. This value cannot be customized. -
The
oidc:audvalue issts.aliyuncs.com. -
The
Principal.Federatedvalue is the provider ARN of the cluster.
For detailed configuration instructions, see Step 1: Create a RAM role and configure the trust policy.
-
-
If intermittent failures occur when a large number of sandboxes are created concurrently, go to the Quota Center to request a quota increase for the
AssumeRoleWithOIDCAPI.
Layer 3: Access to OSS is denied when using the STS token
Symptom
The sandbox is in Running status and the token is issued successfully, but reading or writing files in the mount directory is denied. The csi-agent-sidecar logs show the following error:
Invalid Credentials(host=xxxx message=xxx.)
Common error messages include:
-
You have no right to access...: The RAM role referenced by the CredentialProvider does not have sufficient permissions, and the final token lacks the required access permissions for the target bucket or object. -
Access denied by authorizer's policy: The CredentialProvider policy rendering issue causes the final effective policy to not include the required Action/Resource for the request.
Troubleshooting steps
Insufficient RAM role permissions:
-
Go to the RAM console, find the RAM role created in Step 1, and verify that the permission policy includes both bucket-level and object-level resources:
"Resource": [ "acs:oss:*:*:<YOUR-BUCKET-NAME>", "acs:oss:*:*:<YOUR-BUCKET-NAME>/*" ] -
Verify that the
Actionin the permission policy covers the operations actually performed by the sandbox. For example, write operations requireoss:PutObject, delete operations requireoss:DeleteObject, and list operations requireoss:ListObjects. For complete policy examples, see Step 1: Create a RAM role and configure the trust policy. -
Verify that the RAM role permission policy is successfully attached to the target role through Add Permissions.
CredentialProvider policy rendering issue:
-
Verify that the
Actionvalues declared in the CredentialProviderpolicycover the operations actually performed by the sandbox. The intersection of the CredentialProvider and RAM role policies constitutes the final effective permissions. Missing permissions in either layer results in a deny. -
If a write operation on a read-only mount is denied, change the
credentialProviderNamein the mount configuration to a read/write template (such asoss-rw), and removereadOnly: true. -
Verify that the CredentialProvider
policyuses template functions correctly:-
Object-level operations (such as
GetObjectandPutObject) must use{{ build_policy_oss_resource() }}in theResourcefield. -
Bucket-level operations (such as
ListObjects) must use{{ build_policy_oss_resource(limit_sub_path=false) }}in theResourcefield, with theoss:Prefixcondition to restrict the subpath prefix.
For detailed descriptions of template functions, see CredentialProvider policy template functions.
-
-
Verify that the
subPathdeclared in the SandboxClaim or E2B SDK matches the intended access path. Template functions automatically populateResourcevalues based on thebucketandsubPathdeclared by each sandbox instance. An incorrect declaration causes the final policy to not match the actual access path.