All Products
Search
Document Center

Key Management Service:Access KMS from an ECS instance in a secure manner

Last Updated:Mar 31, 2026

Assign a RAM role to an ECS instance so that applications running on it can call Key Management Service (KMS) APIs using automatically rotated temporary credentials — no hardcoded AccessKey required.

How it works

Instead of embedding long-term AccessKey credentials in your application, you attach a Resource Access Management (RAM) role to the ECS instance. The instance retrieves short-lived credentials from the metadata service, and the SDK automatically refreshes them before expiry. Your application never needs to manage credential rotation.

The setup involves four steps:

  1. Create an instance RAM role and grant it KMS permissions.

  2. Attach the role to an ECS instance.

  3. (Optional) Retrieve a temporary credential to verify the setup.

  4. Call KMS from your application using the SDK.

Instance RAM roles are only supported on ECS instances in a virtual private cloud (VPC).

Prerequisites

Before you begin, ensure that you have:

  • An ECS instance in a VPC

  • Permissions to create RAM roles and call ECS APIs

  • The KMS SDK, Encryption SDK, or Secrets Manager Client installed in your application

Step 1: Create an instance RAM role and grant KMS permissions

1. Create the RAM role.

Call the CreateRole operation of RAM using OpenAPI Explorer with the following parameters:

ParameterValue
RoleNameEcsRamRoleTest
AssumeRolePolicyDocumentSee the policy document below

Use the following trust policy to allow an ECS instance to assume the role:

{
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "ecs.aliyuncs.com"
                ]
            }
        }
    ],
    "Version": "1"
}

2. Grant the role KMS permissions.

Call the AttachPolicyToRole operation of RAM using OpenAPI Explorer with the following parameters:

ParameterValue
PolicyTypeSystem
PolicyNameAliyunKMSFullAccess
RoleNameEcsRamRoleTest

Step 2: Attach the RAM role to an ECS instance

Choose one of the following methods based on whether you are working with an existing instance or creating a new one.

Attach to an existing instance

Call the AttachInstanceRamRole operation of ECS using OpenAPI Explorer with the following parameters:

ParameterValue
RegionIdID of the region where the ECS instance resides
RamRoleNameEcsRamRoleTest
InstanceIdsInstance ID in ["i-bXXXXXXXX"] format

Attach when creating a new instance

  1. Call the CreateInstance operation of ECS using OpenAPI Explorer with the following parameters:

    ParameterValue
    RegionIdcn-hangzhou (example)
    ImageIdcentos_7_03_64_40G_alibase_20170503.vhd (example)
    InstanceTypeecs.g6.large (example)
    VSwitchIdID of the vSwitch in your VPC — required, as instance RAM roles only work in VPCs
    RamRoleNameEcsRamRoleTest
  2. Set the instance password and start the instance.

  3. Enable internet access for the instance from the ECS console or via API.

For information about authorizing a RAM user to assume this role, see Use an instance RAM role by calling API operations.

Step 3: (Optional) Retrieve a temporary credential

Retrieve the temporary credential to verify the role is attached correctly. The credential contains a token and is automatically refreshed on a regular basis.

A successful response looks like this:

{
   "AccessKeyId": "STS.J8XXXXXXXXXX4",
   "AccessKeySecret": "9PjfXXXXXXXXXBf2XAW",
   "Expiration": "2017-06-09T09:17:19Z",
   "SecurityToken": "CAIXXXXXXXXXXXwmBkleCTkyI+",
   "LastUpdated": "2017-06-09T03:17:18Z",
   "Code": "Success"
}

Step 4: Call KMS from your application

All three examples below use InstanceProfileCredentialsProvider, which automatically fetches and refreshes temporary credentials from the instance metadata service — no manual credential management needed.

KMS SDK

package com.aliyuncs.kms.examples;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.AlibabaCloudCredentialsProvider;
import com.aliyuncs.auth.InstanceProfileCredentialsProvider;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.kms.model.v20160120.*;
import com.aliyuncs.profile.DefaultProfile;

public class RamRoleTest {
    public static void main(final String[] args) throws Exception {
        String regionId = "<region-id>";
        DefaultProfile profile = DefaultProfile.getProfile(regionId);

        // Name of the instance RAM role attached to this ECS instance
        String roleName = "<your-ecs-ram-role-name>"; // Enter EcsRamRoleTest.

        // The provider fetches and refreshes temporary credentials automatically
        AlibabaCloudCredentialsProvider provider = new InstanceProfileCredentialsProvider(roleName);

        IAcsClient client = new DefaultAcsClient(profile, provider);

        EncryptRequest request = new EncryptRequest();

        // Key alias or key ID used to encrypt the plaintext
        request.setKeyId("alias/Apollo/SalaryEncryptionKey");
        request.setPlaintext("Hello world");

        try {
            EncryptResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
    }
}

Encryption SDK

package com.aliyun.encryptionsdk.examples.credentials;

import com.aliyun.encryptionsdk.AliyunConfig;
import com.aliyun.encryptionsdk.AliyunCrypto;
import com.aliyun.encryptionsdk.exception.InvalidAlgorithmException;
import com.aliyun.encryptionsdk.exception.UnFoundDataKeyException;
import com.aliyun.encryptionsdk.model.CryptoResult;
import com.aliyun.encryptionsdk.provider.dataKey.DefaultDataKeyProvider;

import java.util.Collections;

import static org.junit.Assert.assertArrayEquals;

/**
 * Authenticate using an instance RAM role via the Encryption SDK.
 */
public class EcsRamRoleSample {
    private static final String PLAIN_TEXT = "this is test.";
    private static final String cmkArn = "acs:kms:RegionId:UserId:key/CmkId";
    private static final String ecRamRoleName = "EcsRamRoleTest";
    public static void main(String[] args) {
        AliyunConfig config = new AliyunConfig();
        // Configure the RAM role — credentials are fetched automatically
        config.withEcsRamRole(ecRamRoleName);

        AliyunCrypto crypto = new AliyunCrypto(config);

        DefaultDataKeyProvider defaultDataKeyProvider = new DefaultDataKeyProvider(cmkArn);
        try {
            CryptoResult<byte[]> encryptResult = crypto.encrypt(defaultDataKeyProvider, PLAIN_TEXT.getBytes(), Collections.singletonMap("sample", "Context"));
            CryptoResult<byte[]> decryptResult = crypto.decrypt(defaultDataKeyProvider, encryptResult.getResult());
            assertArrayEquals(decryptResult.getResult(), PLAIN_TEXT.getBytes());
        } catch (InvalidAlgorithmException | UnFoundDataKeyException e) {
            System.out.println("Failed.");
            System.out.println("Error message: " + e.getMessage());
        }
    }
}

Secrets Manager Client

package com.aliyuncs.kms.secretsmanager.examples;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.auth.InstanceProfileCredentialsProvider;
import com.aliyuncs.kms.secretsmanager.cacheclient.exception.CacheSecretException;
import com.aliyuncs.kms.secretsmanager.cacheclient.model.SecretInfo;
import com.aliyuncs.kms.secretsmanager.cacheclient.service.DefaultSecretManagerClientBuilder;

public class EcsSamples {

    public static void main(String[] args) throws CacheSecretException {
        String secretName = "<secret-name>";
        String roleName = "<your-ecs-ram-role-name>";
        String regionId = "<region-id>";
        SecretCacheClient client = SecretCacheClientBuilder.newCacheClientBuilder(
                DefaultSecretManagerClientBuilder.standard().withCredentialsProvider(new InstanceProfileCredentialsProvider(roleName)).withRegion(regionId)
                        .build()
        ).build();
        SecretInfo secretInfo = client.getSecretInfo(secretName);
        System.out.println("secretInfo:"+JSONObject.toJSONString(secretInfo));
    }
}

What's next