Configure credential injection for Agent Sandbox egress traffic

Updated at:

Use the tokenTransformation rule in a SecurityProfile to automatically replace credentials when Sandbox egress traffic is forwarded through the egress gateway, so that applications can securely call external APIs by using placeholder credentials.

Overview

In AI Agent scenarios, code that runs in a Sandbox often comes from untrusted sources. Placing real API keys or Alibaba Cloud AccessKey pairs directly in the code risks credential leaks. Credential injection dynamically replaces credentials when the egress gateway forwards traffic. This provides the following security benefits:

  • Sandbox applications hold only placeholder credentials, such as FAKE_AK, and cannot directly call external services.

  • Real credentials are stored on the cluster side in a Kubernetes Secret or CredentialProvider and managed centrally by the platform.

  • The gateway automatically replaces credentials and recalculates signatures when forwarding requests. This process is transparent to Sandbox applications.

  • The AgentIdentity authorization mechanism provides fine-grained control over the credentials that each agent identity can use.

Credential injection supports the following two modes. Select a mode based on the type of the target service:

Mode

Scenario

Description

API key injection

Third-party LLM services, such as OpenAI and Qwen

Replaces the placeholder token in a request with a real API key.

Alibaba Cloud STS credential injection

Alibaba Cloud OpenAPI

Replaces the AccessKey ID, AccessKey secret, and Security Token Service (STS) token, and recalculates the request signature.

Alibaba Cloud STS credential injection mode requires HTTPS traffic control and does not support OSS V1 signatures or Simple Log Service (SLS) private signatures. Confirm that these conditions are met before you select this mode. For the complete list of constraints, see Limits.

How it works

The following diagram shows how egress requests are forwarded and how their credentials are replaced:

image
  1. Request initiation: A Sandbox application initiates an egress request with placeholder credentials. The traffic-proxy sidecar transparently intercepts the request and forwards it to the egress gateway.

  2. Policy evaluation: The egress gateway sends request metadata to the traffic-extension Service, which matches the SecurityProfile rules in the namespace.

  3. Credential retrieval: After a tokenTransformation rule is matched, traffic-extension retrieves real credentials through CredentialProvider.

  4. Credential replacement: traffic-extension replaces the placeholder credential in the request header. In Alibaba Cloud STS mode, it also recalculates the request signature based on the real AK/SK.

  5. Forwarding and response: The egress gateway forwards the request with the rewritten request header to the target service. The response returns to the Sandbox application along the original path.

Related resource objects

Credential injection uses the following five custom resources (CRs). You create them in order in the following procedures:

Resource object

Description

AgentIdentity

Defines an agent identity. A SandboxClaim references this identity through the security.agents.kruise.io/agent-name annotation to obtain credential injection capabilities.

CredentialProvider

Defines the real credential source. API key mode reads from a Kubernetes Secret, whereas Alibaba Cloud STS mode assumes a RAM role through RAM Roles for Service Accounts (RRSA) to obtain temporary credentials.

AgentRole

Defines authorization rules that specify which CredentialProvider an agent can obtain credentials from.

AgentRoleBinding

Binds an AgentRole to an AgentIdentity to grant the permissions defined in the AgentRole.

SecurityProfile

Defines tokenTransformation rules, which specify the domains to match, the target request header, and the credential source (a referenced CredentialProvider).

Prerequisites

  • Cluster version 1.30 or later.

  • On the cluster Add-ons page, verify the following add-on versions and configurations:

    • ack-agent-identity: version 0.2.0 or later.

    • ack-agent-sandbox-controller: version 0.5.16 or later, with identityProvider enabled in the configuration.

    • ack-sandbox-manager: version 0.6.4 or later, with enhancedTrafficManagement enabled in the configuration.

Configure credential injection

For either credential injection mode, first create an AgentIdentity CR to define an agent identity. Sandbox instances that you create later are associated with this identity to obtain credential injection capabilities.

The following operations use kubectl. Before you begin, make sure that kubeconfig is configured to access the target ACS cluster. For more information, see Use ACS with kubectl.

  1. Save the following content as agent-identity.yaml, and run kubectl apply -f agent-identity.yaml to create the AgentIdentity resource.

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: AgentIdentity
    metadata:
      name: my-agent         # Agent identity name referenced by subsequent configurations.
      namespace: <YOUR_NAMESPACE>
    spec:
      description: "Example AI Agent identity"
  2. After you create the AgentIdentity CR, select a credential injection mode based on the type of the target Service:

    • API key injection mode: injects an API key for third-party API services, such as LLM services.

    • Alibaba Cloud STS credential injection mode: applies when a Sandbox calls Alibaba Cloud OpenAPI. The request signature is recalculated automatically.

API key injection mode

The following end-to-end procedure uses httpbin.org as the verification target. In production, replace it with your target domain.

Procedure

  1. Save the following content as llm-api-key-secret.yaml, and run kubectl apply -f to create a Secret that stores the API key.

    apiVersion: v1
    kind: Secret
    metadata:
      name: llm-api-key
      namespace: <YOUR_NAMESPACE>
    type: Opaque
    stringData:
      apiKey: "sk-xxxxxxxxxxxxxxxx"   # Replace with the real API key.
  2. Save the following content as credential-provider-apikey.yaml, and run kubectl apply -f to create a CredentialProvider that references the preceding 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       # Name of the Secret created in the preceding step.
            keyName: apiKey           # Name of the field that contains the API key in the Secret.
    secretRef.name supports template variables that dynamically reference Secret names. For more information, see CredentialProvider template variables.

    In addition to API keys stored in Secrets, API keys stored in Key Management Service (KMS) can also be referenced. For more information, see Use API Key credentials stored in KMS Secrets Manager by configuring a CredentialProvider.

  3. Save the following content as agent-role-apikey.yaml, and run kubectl apply -f to create an AgentRole and an AgentRoleBinding that authorize the agent identity to retrieve credentials from this CredentialProvider.

    apiVersion: agentidentity.alibabacloud.com/v1alpha1
    kind: AgentRole
    metadata:
      name: get-llm-key
      namespace: <YOUR_NAMESPACE>
    spec:
      rules:
      - effect: Allow
        action: "GetResourceCredential"
        # Name of the CredentialProvider created in the preceding step.
        resource: "CredentialProvider/llm-api-key"
    ---
    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:
          # Must match the name of the AgentIdentity CR created earlier.
          agentName: my-agent
  4. Save the following content as security-profile-apikey.yaml, and run kubectl apply -f to create a SecurityProfile and configure the tokenTransformation rule.

    In the following example, if the Authorization header begins with Bearer, the system uses valueTemplate to automatically replace it with the real API key. {{ .Token }} is fixed syntax.

    apiVersion: agents.kruise.io/v1alpha1
    kind: SecurityProfile
    metadata:
      name: inject-llm-key
      namespace: <YOUR_NAMESPACE>
    spec:
      selector:
        matchLabels:
          inject-api-key: "true"
      rules:
      - name: inject-openai-key
        match:
        - domains:
          - "httpbin.org"           # Verification example. Replace with the target domain in actual use.
        actions:
          tokenTransformation:
            type: ApiKey
            credentialRef:
              kind: CredentialProvider
              name: llm-api-key
            apiKey:
              when:
                header: Authorization
                pattern: "^Bearer .+"
              targetHeader: Authorization
              valueTemplate: "Bearer {{ .Token }}"

    For descriptions of the key fields, see tokenTransformation field reference.

  5. Save the following content as sandboxset-apikey.yaml, and run kubectl apply -f to create a SandboxSet. Replace the sample container image with your workload image. The SandboxSet declares the enhanced-traffic-policy mode to enable enhanced traffic management.

    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   # Replace with the actual workload image.
            resources:
              requests:
                cpu: "2"
                memory: 2Gi
              limits:
                cpu: "2"
                memory: 2Gi

    Wait for the Pods to become ready. Confirm that the Sandboxes in the SandboxSet are in the Running state:

    kubectl get sandbox -n <YOUR_NAMESPACE>

    Expected output:

    NAME                STATUS    AGE    CLAIMED
    apikey-test-xxxxx   Running   60s    false
    apikey-test-yyyyy   Running   60s    false
  6. Save the following content as sandboxclaim-apikey.yaml, and run kubectl apply -f to create a SandboxClaim that allocates a Sandbox and associates an agent identity.

    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
      annotations:
        # Must match the name of the AgentIdentity CR created earlier.
        security.agents.kruise.io/agent-name: my-agent
      labels:
        inject-api-key: "true"

    Confirm that the CLAIMED state of one Sandbox changes to true:

    kubectl get sandbox -n <YOUR_NAMESPACE>

    Expected output:

    NAME                STATUS    AGE    CLAIMED
    apikey-test-xxxxx   Running   2m     true
    apikey-test-yyyyy   Running   2m     false
  7. Verification: Enter the claimed Sandbox Pod and use a placeholder token to send a request that verifies API key injection.

    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"

    In the expected output, the Authorization header has been replaced with the real API key:

    {
      "headers": {
        "Accept": "*/*",
        "Authorization": "Bearer sk-xxxxxxxxxxxxxxxx",
        "Host": "httpbin.org",
        "User-Agent": "curl/7.61.1",
        ...
      }
    }

Alibaba Cloud STS credential injection mode

The system transparently replaces the AccessKey ID, AccessKey secret, and STS token in a request and recalculates the request signature. A Sandbox application can use the standard Alibaba Cloud SDK and fake credentials to call cloud services. The following end-to-end procedure uses read-only access to clusters as an example.

Prerequisites

Procedure

Note

This mode relies on the ack-agent-identity add-on to call the AssumeRoleWithOIDC API of STS to obtain temporary credentials. Based on the number of Sandbox instances in your workloads, go to Quota Center to request a sufficient quota for the AssumeRoleWithOIDCAPI. This prevents credential injection failures caused by insufficient quota.

  1. Create a RAM role, such as ack-agent-identity-sample-role, in the RAM console.

  2. Configure the trust policy of the RAM role to authorize the ack-agent-identity add-on to assume the role through RRSA. Replace <oidc_issuer_url> and <oidc_provider_arn> in the following template with the RRSA OIDC information of the cluster. You can find this information in the RRSA OIDC section of the Basic Information page of the cluster.

    {
      "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"
    }
  3. Grant the RAM role the required access policy, such as AliyunCSReadOnlyAccess.

  4. Save the following content as credential-provider-sts.yaml, and run kubectl apply -f to create a CredentialProvider that references the preceding RAM role. The policy field defines the permission scope of the issued STS token and must be a subset of the role permissions.

    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 supports template variables that dynamically adjust permissions for each Sandbox instance. For variable definitions, see CredentialProvider template variables.

  5. Save the following content as agent-role-sts.yaml, and run kubectl apply -f to authorize the agent identity to retrieve credentials from the 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
  6. Save the following content as security-profile-sts.yaml, and run kubectl apply -f to create a SecurityProfile that configures a tokenTransformation rule.

    apiVersion: agents.kruise.io/v1alpha1
    kind: SecurityProfile
    metadata:
      name: aliyun-sts-injection
      namespace: <YOUR_NAMESPACE>
    spec:
      selector:
        matchLabels:
          inject-sts: "true"
      rules:
      - name: inject-aliyun-sts
        match:
        - domains:
          - "*.aliyuncs.com"
        actions:
          tokenTransformation:
            type: AliyunSTS
            credentialRef:
              kind: CredentialProvider
              name: aliyun-cs-readonly

    For descriptions of the key fields, see tokenTransformation field reference.

  7. Save the following content as sandboxset-sts.yaml, and run kubectl apply -f to create a SandboxSet. Set a fake AccessKey ID and AccessKey secret as environment variables. The Alibaba Cloud SDK in the Sandbox sends requests with these fake credentials, and the gateway replaces them with real credentials when it forwards the requests.

    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   # Replace with the actual workload image.
            env:
            - name: ALIBABA_CLOUD_ACCESS_KEY_ID
              value: "FAKE_AK"               # Fake AK. The gateway replaces it automatically.
            - name: ALIBABA_CLOUD_ACCESS_KEY_SECRET
              value: "FAKE_SK"               # Fake SK. The gateway replaces it automatically.
            - name: ALIBABA_CLOUD_REGION
              value: "cn-hangzhou"            # Replace with the actual region.
            resources:
              requests:
                cpu: "2"
                memory: 2Gi
              limits:
                cpu: "2"
                memory: 2Gi

    Wait for the Pods to become ready. Confirm that the Sandboxes are in the Running state:

    kubectl get sandbox -n <YOUR_NAMESPACE>

    Expected output:

    NAME              STATUS    AGE    CLAIMED
    sts-test-xxxxx    Running   60s    false
    sts-test-yyyyy    Running   60s    false
  8. Save the following content as sandboxclaim-sts.yaml, and run kubectl apply -f to create a SandboxClaim that allocates a Sandbox and associates an agent identity.

    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
      annotations:
        # Must match the name of the AgentIdentity CR created earlier.
        security.agents.kruise.io/agent-name: my-agent
      labels:
        inject-sts: "true"

    Confirm that the CLAIMED state of one Sandbox changes to true, and check the token issuance status:

    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

    The expected output contains the token expiration time:

    security.agents.kruise.io/token-status: '{"accessTokenExpiration":"2026-06-05T04:41:40Z"}'
  9. Verification: Enter the claimed Sandbox Pod, install the Alibaba Cloud CLI, and use fake credentials to verify STS credential injection.

    kubectl exec -it $CLAIMED_POD -n <YOUR_NAMESPACE> -c sandbox -- bash

    Run the following commands in the Sandbox:

    # 1. Install the Alibaba Cloud CLI.
    /bin/bash -c "$(curl -fsSL https://aliyuncli.alicdn.com/install.sh)"
    
    # 2. Configure fake credentials.
    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. Call the authorized CS API. The request is expected to succeed.
    aliyun cs GET /api/v1/clusters

    The command is expected to return a JSON list of clusters. This indicates that the gateway transparently replaced the fake credentials with real temporary credentials obtained through the STS AssumeRoleWithOIDC operation.

tokenTransformation field reference

Refer to this section when you configure a SecurityProfile. It describes the CRD fields of tokenTransformation rules, CredentialProvider template variables, and the signature methods supported in Alibaba Cloud STS mode.

CRD fields

actions:
  tokenTransformation:
    disabled: false              # Optional. Temporarily disable the rule.
    failStrategy: Block          # Optional. Failure strategy: Block (default) or Allow.
    type: ApiKey | AliyunSTS     # Required. Injection mode.

    credentialRef:               # Required. Credential source.
      kind: CredentialProvider   # CredentialProvider or Secret.
      name: <name>              # Resource name.
      namespace: <ns>           # Optional. Defaults to the SecurityProfile namespace.

    # Specific to ApiKey mode. Required when type is ApiKey.
    apiKey:
      when:                     # Optional. Injection precondition.
        header: Authorization   # Request header to check.
        pattern: "^Bearer .+"   # RE2 regular expression.
      targetHeader: Authorization  # Target request header. Defaults to Authorization.
      valueTemplate: "Bearer {{ .Token }}"  # Value template.

Field

Description

type

Injection mode: ApiKey or AliyunSTS.

disabled

Set to true to temporarily disable injection. The default is false.

failStrategy

The action to take when credential retrieval or signing fails: Block (default, blocks the request) or Allow (allows the original request).

credentialRef.kind

Credential source type: CredentialProvider or Secret. For AliyunSTS mode, CredentialProvider is recommended because it supports dynamic permission policies.

credentialRef.name

Name of the referenced CredentialProvider or Secret.

apiKey.when.header/apiKey.when.pattern

The injection precondition. Specifies the request header to check and an RE2 regular expression. Credentials are injected only when the header value matches the expression.

apiKey.targetHeader

Target request header to replace. The default is Authorization.

apiKey.valueTemplate

Value template in Go text/template format. {{ .Token }} represents the retrieved real credential. The maximum length is 1,024 characters.

CredentialProvider template variables

The policy and secretRef.name fields of CredentialProvider support template variables. These variables reference context associated with a Sandbox instance identity to dynamically adjust permission scopes or reference different Secrets for different Sandbox instances.

secretRef.name template variables

Template variables in secretRef.name

In addition to a fixed Secret name, secretRef.name can include ${ack:agent-identity/...} template variables. When retrieving credentials, the system renders the actual Secret name according to the identity context of the current request, so it can provide different credentials for different identities. For example, llm-api-key-${ack:agent-identity/agent-name} resolves to llm-api-key-my-agent according to the Agent name.

The following template variables are supported:

Template variable

Description

${ack:agent-identity/agent-name}

The name of the AgentIdentity associated with the current Agent identity.

${ack:agent-identity/metadata/<key>}

The value of the specified key in custom metadata written when the identity token is issued. Replace <key> with the actual key name.

If a template variable cannot be resolved in the current request context, the credential retrieval request fails with an explicit error message instead of silently returning an empty value. For example, resolution fails when the referenced metadata key does not exist.

The following example shows how to dynamically reference different Secrets by tenant. API Keys for different tenants are stored in Secrets named llm-api-key-<tenant identifier>. When retrieving credentials, the CredentialProvider resolves the corresponding Secret name through ${ack:agent-identity/metadata/tenant-id}.

The metadata value comes from custom metadata written when the identity token is issued. Annotation values can be passed in Agent Sandbox scenarios through the SandboxClaim annotation security.agents.kruise.io/<key>. The part after the prefix is the metadata key:

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: my-claim
  namespace: <YOUR_NAMESPACE>
spec:
  templateName: my-sandbox-set
  replicas: 1
  annotations:
    # After removing the prefix, the following value can be referenced in the template through ${ack:agent-identity/metadata/tenant-id}
    security.agents.kruise.io/tenant-id: acme
    security.agents.kruise.io/agent-name: my-agent

The corresponding CredentialProvider is as follows:

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-${ack:agent-identity/metadata/tenant-id}'   # Resolves to llm-api-key-acme
        keyName: apiKey

With this configuration, when tenant-id in the request identity metadata is acme, secretRef.name resolves to llm-api-key-acme and reads the Secret dedicated to that tenant.

policy template variables

The policy supports embedded ${ack:agent-identity/...} template variables. The system replaces these with actual values from the current request identity context at credential issuance time, enabling different permissions for different identities. The supported variables are:

Template variable

Description

${ack:agent-identity/agent-name}

The AgentIdentity name associated with the current agent identity.

${ack:agent-identity/metadata/<key>}

The value of a specified key in the custom metadata written during identity token issuance. Replace <key> with the actual key name.

The following example demonstrates dynamically scoping permissions by tenant. Different tenants' data is stored in subdirectories named after the tenant identifier under the OSS bucket. The policy uses ${ack:agent-identity/metadata/tenant-id} to resolve the corresponding resource path at credential issuance time.

policy: |
  {
    "Statement": [
      {
        "Action": ["oss:GetObject", "oss:PutObject"],
        "Effect": "Allow",
        "Resource": [
          "acs:oss:*:*:my-bucket/${ack:agent-identity/metadata/tenant-id}/*"
        ]
      }
    ],
    "Version": "1"
  }

The metadata values come from custom metadata written during identity token issuance. In the Agent Sandbox scenario, you can pass them through the security.agents.kruise.io/<key> annotation on the SandboxClaim (the annotation without the prefix becomes the metadata key):

apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
  name: my-claim
  namespace: <YOUR_NAMESPACE>
spec:
  templateName: my-sandbox-set
  replicas: 1
  annotations:
    # The following annotation (without the prefix) can be referenced in templates through ${ack:agent-identity/metadata/tenant-id}
    security.agents.kruise.io/tenant-id: acme
  labels:
    security.agents.kruise.io/agent-name: my-agent

With this configuration, when the requesting identity's metadata tenant-id is acme, the resource path in the policy resolves to acs:oss:*:*:my-bucket/acme/*, restricting that tenant to access only its own subdirectory.

Note

If a template variable cannot be resolved in the current request context (for example, the referenced metadata key does not exist), the credential issuance request fails with an explicit error message rather than silently returning an empty value or relaxing permissions.

Supported signature methods in Alibaba Cloud STS mode

The system automatically detects the signature method of each request. You do not need to specify it. It supports standard signed requests from Alibaba Cloud SDKs in Go, Java, Python, Node.js, and other languages. If a request does not include a recognizable Alibaba Cloud signature, the tokenTransformation action is skipped and the request proceeds normally or matches subsequent rules.

Signature version

Signature algorithm

Typical SDK version

Identifying feature

V3 (ACS3-HMAC-SHA256)

HMAC-SHA256

Alibaba Cloud SDK 2.0 and later (V2 SDK)

The Authorization header begins with ACS3-HMAC-SHA256

V1 RPC (HMAC-SHA1)

HMAC-SHA1

V1 SDK RPC style

Query parameters include Signature, SignatureMethod=HMAC-SHA1, and AccessKeyId

V1 ROA (HMAC-SHA1)

HMAC-SHA1

V1 SDK ROA style

The Authorization header begins with acs and includes :

OSS V4 (OSS4-HMAC-SHA256)

HMAC-SHA256

OSS SDK V4 signature

The Authorization header begins with OSS4-HMAC-SHA256

Limits

The following table describes the limits of credential injection.

Limit

Description

Alibaba Cloud STS mode requires HTTPS traffic control

Alibaba Cloud SDKs use HTTPS by default. TLS termination is required to intercept and rewrite these requests.

Alibaba Cloud STS mode does not support OSS V1 signatures

Requests that use the legacy OSS V1 signature cannot be recognized or re-signed.

Alibaba Cloud STS mode does not support SLS private signatures

Simple Log Service (SLS) uses a non-standard signature method and is not supported.

Credential replacement applies only to egress traffic

Credentials are replaced only in requests that are forwarded through the egress gateway.

Each rule supports only one tokenTransformation action

Create multiple rules when different credentials must be injected for different domains.

valueTemplate has a maximum length in API key mode

The maximum length is 1,024 characters.

FAQ

What do I do if credential injection does not take effect and requests still use the original credentials?

Troubleshoot the issue by following these steps:

  1. Confirm that the Sandbox is associated with the correct security.agents.kruise.io/agent-name annotation in the SandboxClaim.

  2. Confirm that selector.matchLabels in SecurityProfile matches the Sandbox Pod labels.

  3. Confirm that AgentRole and AgentRoleBinding correctly authorize access to the corresponding CredentialProvider.

  4. In Alibaba Cloud STS mode, confirm that HTTPS traffic control is enabled and includeHosts includes the target domain, such as *.aliyuncs.com.

  5. Check the traffic-extension logs for errors.

    kubectl logs -l app.kubernetes.io/name=traffic-extension -n sandbox-traffic-system

A request returns a signature error (SignatureDoesNotMatch)?

The error may have one of the following causes:

  • The request uses an unsupported signature method, such as OSS V1 or an SLS private signature. Check whether the Authorization header format matches one of the signature methods described in Supported signature methods in Alibaba Cloud STS mode.

  • type: ApiKey is configured, but the target is an Alibaba Cloud API. ApiKey mode only replaces the header and does not recalculate the signature. Use type: AliyunSTS instead.

References