All Products
Search
Document Center

Container Service for Kubernetes:Use RRSA for pod-level access control

Last Updated:Jun 26, 2026

Assign each pod a dedicated RAM role with short-lived STS tokens instead of shared node credentials.

RRSA provides two key security properties:

  • Least privilege: Scope RAM permissions to a specific service account, so only pods using that account can access those resources. This eliminates the need for static AccessKey pairs.

  • Credential isolation: Pods cannot access credentials used by other pods on the same node. Without RRSA, all pods on a node share the permissions of the underlying Elastic Compute Service (ECS) instance role.

How RRSA works

Without RRSA, all pods on a node share the ECS instance role's permissions through instance metadata, posing a significant security risk.

RRSA solves this by binding a RAM role to a Kubernetes service account. When a pod starts, it receives an OpenID Connect (OIDC) token scoped to its service account, calls the AssumeRoleWithOIDC API, and receives a role-scoped STS token for cloud API access.

The authentication flow:

  1. Token injection: When a pod starts, ACK uses service account token volume projection to mount an OIDC token file scoped to the pod's service account.

  2. Assume role: The application calls the AssumeRoleWithOIDC API using this OIDC token.

  3. Receive STS credentials: Alibaba Cloud RAM verifies the OIDC token against the cluster's OIDC provider and returns role-scoped STS credentials.

  4. Access resources: The pod uses the short-lived STS credentials to access authorized Alibaba Cloud APIs.

OIDC tokens are short-lived. Read the token from the file on every authentication request — do not cache it. ACK renews tokens automatically before expiration.

When RRSA is enabled, ACK automatically:

  • Creates a dedicated OIDC issuer for the cluster.

  • Enables service account token volume projection for the cluster.

  • Creates a RAM identity provider (IdP) in your account, named ack-rrsa-<cluster_id>, configured for single sign-on (SSO) with the cluster's OIDC issuer.

Before you begin

Ensure the following before configuring RRSA:

  • Cluster version: ACK cluster (Basic, Pro, Serverless, or Edge) runs Kubernetes 1.22 or later.

  • Permissions: Administrative access to the ACK console and RAM console.

  • Token validity limit: After RRSA is enabled, newly created ServiceAccount tokens have a maximum validity of 12 hours.

Step 1: Enable RRSA for your cluster

Enable RRSA during cluster creation or after the cluster is running. For ACK Serverless clusters, enable RRSA after cluster creation from the cluster details page.

Enable during cluster creation

When creating an ACK managed cluster or ACK Edge cluster, go to the Cluster Configurations step, expand Advanced Options (Optional), and click Enable next to RRSA OIDC.

image

Enable for an existing cluster

  1. Log on to the ACK console. In the left navigation pane, click Clusters.

  2. Click the name of your cluster. In the left navigation pane, click Cluster Information.

  3. On the Basic Information tab, scroll to the Security and Auditing section and click Enable next to RRSA OIDC.

    image

  4. In the Enable RRSA dialog box, click Confirm. Wait for the cluster status to change from Updating to Running. RRSA is now enabled.

Get the OIDC provider URL and ARN

After RRSA is enabled, hover over the Enabled label next to RRSA OIDC in the Security and Auditing section. The URL and Alibaba Cloud Resource Name (ARN) of the OIDC provider are displayed.

image

Record both values for use when configuring RAM roles and application templates.

Step 2: Configure an application to use RRSA

The setup for a sample application has two parts:

  • Cluster-level setup (do once per cluster): Enable RRSA and install ack-pod-identity-webhook.

  • Per-application setup (repeat for each app): Create or use an existing RAM role, grant permissions, and deploy the application.

Sample configuration

Item

Value

Namespace

rrsa-demo

Service account

demo-sa

RAM role

demo-role-for-rrsa

Sample workflow

1. Install ack-pod-identity-webhook

ack-pod-identity-webhook automatically injects the OIDC token file path and RAM role ARN into pods as environment variables. Skip this step to configure pod templates manually. See Manually configure pod templates.

  1. In the ACK console, click the name of your cluster. In the left navigation pane, click Add-ons.

  2. On the Add-ons page, click the Security tab.

  3. Find ack-pod-identity-webhook and click Install.

  4. Confirm the information and click OK.

2. Create or configure a RAM role for the OIDC identity provider

Create a RAM role

Create a RAM role named demo-role-for-rrsa that trusts the cluster's OIDC identity provider (IdP). See Create a RAM role for an OIDC IdP.

Use the following parameter values:

Parameter

Value

Identity Provider Type

Select OIDC.

Identity Provider

Select the IdP named ack-rrsa-<cluster_id>, where <cluster_id> is your cluster ID.

Condition

  • oidc:iss: Keep the default value.

  • oidc:aud: Keep the default value.

  • oidc:sub: Manually add this condition.

    • Key: Select oidc:sub

    • Operator: Select StringEquals

    • Value: Enter system:serviceaccount:<namespace>:<serviceAccountName>, where <namespace> is the namespace of your application and <serviceAccountName> is the name of the service account. For the test application in this topic, enter system:serviceaccount:rrsa-demo:demo-sa.

Role Name

demo-role-for-rrsa

The oidc:sub condition scopes the trust to a specific service account in a specific namespace. Replace rrsa-demo and demo-sa with your actual namespace and service account name.

Configure an existing RAM role

To use an existing RAM role, update its trust policy to allow the service account to assume it. See Edit the trust policy of a RAM role.

Add a Statement entry with the following structure:

{
  "Action": "sts:AssumeRole",
  "Condition": {
    "StringEquals": {
      "oidc:aud": "sts.aliyuncs.com",
      "oidc:iss": "<oidc_issuer_url>",
      "oidc:sub": "system:serviceaccount:<namespace>:<service_account>"
    }
  },
  "Effect": "Allow",
  "Principal": {
    "Federated": [
      "<oidc_provider_arn>"
    ]
  }
}

Replace the placeholders:

Placeholder

Value

<oidc_issuer_url>

URL of the cluster's OIDC provider — see Get the OIDC provider URL and ARN

<oidc_provider_arn>

ARN of the cluster's OIDC provider — see Get the OIDC provider URL and ARN

<namespace>

Namespace of the application

<service_account>

Service account used by the application

To automate trust policy updates, use ack-ram-tool:

ack-ram-tool rrsa associate-role --cluster-id <cluster_id> \
    --namespace <namespace> --service-account <service_account> \
    --role-name <role_name> --create-role-if-not-exist

3. Grant permissions to the RAM role

Attach the AliyunCSReadOnlyAccess policy to demo-role-for-rrsa. See Grant permissions to a RAM role.

This grants the application read-only access to ACK cluster information.

4. Deploy your application

Create a file named demo.yaml with the following content. The namespace label pod-identity.alibabacloud.com/injection: 'on' and the service account annotation pod-identity.alibabacloud.com/role-name: demo-role-for-rrsa enable automatic injection by ack-pod-identity-webhook. See ack-pod-identity-webhook.

---
apiVersion: v1
kind: Namespace
metadata:
  name: rrsa-demo
  labels:
    pod-identity.alibabacloud.com/injection: 'on'

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: demo-sa
  namespace: rrsa-demo
  annotations:
    pod-identity.alibabacloud.com/role-name: demo-role-for-rrsa

---
apiVersion: v1
kind: Pod
metadata:
  name: demo
  namespace: rrsa-demo
spec:
  serviceAccountName: demo-sa
  containers:
    - image: registry.cn-hangzhou.aliyuncs.com/acs/ack-ram-tool:1.3.0
      args:
        - rrsa
        - demo
      name: demo
  restartPolicy: OnFailure

Deploy the application:

kubectl apply -f demo.yaml

5. Verify the injected configuration

Confirm that ack-pod-identity-webhook injected the required environment variables and volume mounts:

kubectl -n rrsa-demo get pod demo -o yaml

The expected output includes the following injected items:

Category

Item

Description

Environment variable

ALIBABA_CLOUD_ROLE_ARN

ARN of the RAM role to assume

ALIBABA_CLOUD_OIDC_PROVIDER_ARN

ARN of the OIDC identity provider

ALIBABA_CLOUD_OIDC_TOKEN_FILE

Path to the OIDC token file

ALIBABA_CLOUD_STS_ENDPOINT

STS VPC endpoint for the current region

ALIBABA_CLOUD_STS_REGION

Region identifier for the STS endpoint

ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED

Whether to access STS over the VPC internal endpoint

VolumeMount

rrsa-oidc-token

Mounts the OIDC token into the container

Volume

rrsa-oidc-token

Projected volume source for the OIDC token

A correctly injected pod spec looks like this:

apiVersion: v1
kind: Pod
metadata:
  name: demo
  namespace: rrsa-demo
spec:
  containers:
  - args:
    - rrsa
    - demo
    env:
    - name: ALIBABA_CLOUD_ROLE_ARN
      value: acs:ram::1***:role/demo-role-for-rrsa
    - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN
      value: acs:ram::1***:oidc-provider/ack-rrsa-c***
    - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE
      value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
    - name: ALIBABA_CLOUD_STS_ENDPOINT
      value: sts-vpc.cn-hangzhou.aliyuncs.com
    - name: ALIBABA_CLOUD_STS_REGION
      value: cn-hangzhou
    - name: ALIBABA_CLOUD_VPC_ENDPOINT_ENABLED
      value: "true"
    image: registry.cn-hangzhou.aliyuncs.com/acs/ack-ram-tool:1.3.0
    imagePullPolicy: Always
    name: demo
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-4bwdg
      readOnly: true
    - mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens
      name: rrsa-oidc-token
      readOnly: true
  restartPolicy: OnFailure
  serviceAccount: demo-sa
  serviceAccountName: demo-sa
  volumes:
  - name: kube-api-access-4bwdg
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
  - name: rrsa-oidc-token
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          audience: sts.aliyuncs.com
          expirationSeconds: 3600
          path: token

6. Check application logs

Print the application log:

kubectl -n rrsa-demo logs demo

A successful run lists the clusters in your Alibaba Cloud account:

cluster id: cf***, cluster name: foo*
cluster id: c8***, cluster name: bar*
cluster id: c4***, cluster name: foob*

Optional: To verify least-privilege enforcement, detach the AliyunCSReadOnlyAccess policy from the RAM role (see Remove permissions from a RAM role). Wait 30 seconds, then run the log command again. The application returns a 403 error similar to:

   StatusCode: 403
   Code: StatusForbidden
   Message: code: 403, STSToken policy Forbidden for action cs:DescribeClustersForRegion request id: E78A2E2D-***
   Data: {"accessDeniedDetail":{"AuthAction":"cs:DescribeClustersForRegion","AuthPrincipalDisplayName":"demo-role-for-rrsa:ack-ram-tool","AuthPrincipalOwnerId":"11***","AuthPrincipalType":"AssumedRoleUser","NoPermissionType":"ImplicitDeny","PolicyType":"ResourceGroupLevelIdentityBasedPolicy"},"code":"StatusForbidden","message":"STSToken policy Forbidden for action cs:DescribeClustersForRegion","requestId":"E78A2E2D-***","status":403,"statusCode":403}

This confirms that RRSA is enforcing permissions at the pod level.

Advanced: Manually configure pod templates

To skip ack-pod-identity-webhook, manually add the required environment variables and projected volume to the pod spec:

apiVersion: v1
kind: Pod
metadata:
  name: demo
  namespace: rrsa-demo
spec:
  containers:
  - args:
    - rrsa
    - demo
    env:
    - name: ALIBABA_CLOUD_ROLE_ARN
      value: <role_arn>
    - name: ALIBABA_CLOUD_OIDC_PROVIDER_ARN
      value: <oidc_provider_arn>
    - name: ALIBABA_CLOUD_OIDC_TOKEN_FILE
      value: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens/token
    image: registry.cn-hangzhou.aliyuncs.com/acs/ack-ram-tool:1.3.0
    imagePullPolicy: Always
    name: demo
    volumeMounts:
    - mountPath: /var/run/secrets/ack.alibabacloud.com/rrsa-tokens
      name: rrsa-oidc-token
      readOnly: true
  restartPolicy: OnFailure
  serviceAccount: demo-sa
  serviceAccountName: demo-sa
  volumes:
  - name: rrsa-oidc-token
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          audience: sts.aliyuncs.com
          expirationSeconds: 3600
          path: token

Replace the placeholder values:

Placeholder

Value

Where to find it

<role_arn>

ARN of the RAM role

Roles page in the RAM console

<oidc_provider_arn>

ARN of the OIDC provider

Security and Auditing section in the cluster details page. See Get the OIDC provider URL and ARN.

Important

Set audience to sts.aliyuncs.com. This is the OIDC provider's client ID, not the STS endpoint domain used by the SDK.

Set expirationSeconds to a value between 600 and 43200 (seconds). Values above 43200 are capped at 12 hours.

After redeployment, the application reads the OIDC token from ALIBABA_CLOUD_OIDC_TOKEN_FILE, exchanges it for an STS token via AssumeRoleWithOIDC, and calls cloud APIs with the STS token. See AssumeRoleWithOIDC.

SDK support

Alibaba Cloud SDK V2.0 supports RRSA OIDC token authentication. Any cloud service SDK built on V2.0 that supports STS tokens also supports RRSA.

Supported SDK versions and demos

Language

Minimum version

Demo

Go

Alibaba Cloud Credentials for Go 1.2.6

Go SDK demo

Java

Alibaba Cloud Credentials for Java 0.2.10

Java SDK demo

Python 3

Alibaba Cloud Credentials for Python 0.3.1

Python SDK demo

Node.js / TypeScript

Alibaba Cloud Credentials for TypeScript/Node.js 2.2.6

Node.js SDK demo

See the credentials documentation for each language — Method 6: Use the RAM role of an OIDC IdP.

Cloud-service-specific SDK demos

Some cloud service SDKs provide native OIDC token support:

Cloud service

SDK

Demo

Object Storage Service (OSS)

OSS Go SDK — Method 5: Use OIDCRoleARN

Go demo

OSS

OSS Java SDK — Configure access credentials

Java demo

OSS

OSS Python SDK — Use the role of an OIDC IdP

Python demo

Simple Log Service (SLS)

Simple Log Service SDK for Java

Java demo

Enable RRSA authentication for CLIs

Use ack-ram-tool to configure CLIs for RRSA OIDC token authentication from within a pod.

Alibaba Cloud CLI

Alibaba Cloud CLI v3.0.206 and later support RRSA. Set region_id to your target region.

Option A: Configuration file. Set mode to OIDC in ~/.aliyun/config.json:

{
  "current": "rrsa",
  "profiles": [
    {
      "name": "rrsa",
      "mode": "OIDC",
      "region_id": "cn-hangzhou",
      "ram_session_name": "test-rrsa"
    }
  ],
  "meta_path": ""
}

Option B: Direct command (no configuration file required):

aliyun sts GetCallerIdentity --region cn-hangzhou --role-session-name=test-rrsa

Expected output:

{
  "AccountId": "11380***",
  "Arn": "acs:ram::1138***:assumed-role/test-rrsa-***/test-rrsa",
  "IdentityType": "AssumedRoleUser",
  "PrincipalId": "33300***:test-rrsa",
  "RequestId": "20F78881-F47E-5771-90D6-***",
  "RoleId": "33300***"
}

See Credential types.

ossutil 2.0

ossutil V2.1.0 and later support RRSA. Replace region with your actual region.

Set mode to oidcRoleArn in ~/.ossutilconfig:

cat <<EOF > ~/.ossutilconfig
[default]
mode = oidcRoleArn
OIDCProviderArn = "${ALIBABA_CLOUD_OIDC_PROVIDER_ARN}"
OIDCTokenFilePath = "${ALIBABA_CLOUD_OIDC_TOKEN_FILE}"
roleArn = "${ALIBABA_CLOUD_ROLE_ARN}"
roleSessionName = test-rrsa
region = cn-hangzhou
EOF

See Examples in the ossutil 2.0 documentation.

Simple Log Service CLI

Simple Log Service CLI does not support OIDC configuration files. Use ack-ram-tool to inject credentials at runtime:

ack-ram-tool export-credentials -f environment-variables -- aliyunlog log list_project --region-endpoint=cn-hangzhou.log.aliyuncs.com

Terraform

Alibaba Cloud Provider V1.222.0 and later support assume_role_with_oidc. Set region to your target region.

Add assume_role_with_oidc to your provider configuration:

provider "alicloud" {
  assume_role_with_oidc {
    role_session_name = "terraform-with-rrsa-auth-example"
  }
  region = "cn-hangzhou"
}

See Terraform RRSA demo.

Troubleshooting

SDK errors

Error

Cause

Fix

AuthenticationFail.OIDCToken.Expired — "This JsonWebToken is expired."

The application cached the OIDC token and is using an expired copy.

Read the token from the file (ALIBABA_CLOUD_OIDC_TOKEN_FILE) each time you authenticate. Use an Alibaba Cloud SDK to handle this automatically. See SDK support.

Throttling.User — "Request was denied due to user flow control."

The application is calling AssumeRoleWithOIDC too frequently.

Reuse the STS token until it expires. Use an Alibaba Cloud SDK for automatic token management. See SDK support.

AuthenticationFail.OIDCToken.AudienceNotMatch — "Invalid audience."

The audience parameter in the pod spec is not set to sts.aliyuncs.com.

Set audience: sts.aliyuncs.com in the projected volume source of the pod spec.

AuthenticationFail.OIDCToken.IssuerConfigurationBroken / IssuerNotMatch / AuthenticationFail.NoPermission — "No such OIDC Provider registered."

RRSA is not enabled for the cluster.

See Step 1: Enable RRSA for your cluster. After enabling, recreate any pods that use RRSA.

EntityNotExist.Role — "The role not exists: acs:ram::..."

The RAM role assumed by the application does not exist.

Create the RAM role. See Create a RAM role for an OIDC IdP and Step 2: Create a RAM role for the OIDC identity provider.

AuthenticationFail.NoPermission — "There is no permission"

The RAM role's trust policy does not allow the service account to assume it.

Update the trust policy. See Configure an existing RAM role.

References