All Products
Search
Document Center

Elastic Container Instance:Use an instance RAM role by calling API operations

Last Updated:Oct 11, 2023

You can assign an instance RAM role to an elastic container instance. Then you can access APIs of other Alibaba Cloud services based on Security Token Service (STS) credentials from applications deployed on the elastic container instance. This topic describes how to call API operations to create an instance RAM role, attach a permission policy to the RAM role, and then assign the RAM role to an elastic container instance.

Scenarios

Applications deployed on elastic container instances can access APIs of other Alibaba Cloud services such as Object Storage Service (OSS), Virtual Private Cloud (VPC), and ApsaraDB RDS by using an AccessKey pair of an Alibaba Cloud account or a RAM user. To conveniently call API operations, some users write AccessKey pairs to instances, such as writing AccessKey pairs to configuration files. This method may cause problems such as information leaks and complex maintenance. This method may also cause more permissions than necessary to be granted. Instance RAM roles can prevent such problems.

A RAM role is a virtual user that has specific permissions and can be assumed by elastic container instances. This allows the instances to obtain corresponding permissions. RAM roles eliminate the need to save AccessKey pairs in elastic container instances. If you want to modify permissions of the instances, you only need to modify the permissions of the RAM role that is assumed by the instances. This reduces the risk of AccessKey pair leaks. For more information about RAM roles, see RAM role overview.

Procedure

To use an instance RAM role by calling API operations, perform the following operations:

  1. Create an instance RAM role

    You can call the CreateRole operation to create an instance RAM role. In the request, you must set the trusted entity that assumes the RAM role to Elastic Container Instance and the trusted service to Elastic Compute Service (ECS).

  2. Attach a permission policy to the instance RAM role

    You can call the CreatePolicy operation to create a policy, and then call the AttachPolicyToRole operation to attach the policy to the instance RAM role.

  3. (Optional) Authorize a RAM user to use the instance RAM role

    Before you use a RAM user to create an elastic container instance and assign an instance RAM role to the instance, you must authorize the RAM user to use the instance RAM role.

  4. Assign the instance RAM role to an elastic container instance

    When you call the CreateContainerGroup operation to create an elastic container instance, you can use the RamRoleName parameter to assign the instance RAM role to the elastic container instance. This way, the instance obtains the permissions of the RAM role. Only one instance RAM role can be assigned to an elastic container instance.

  5. Obtain an STS token

    After you assign an instance RAM role to an elastic container instance, you must obtain an STS token by using the instance metadata if you want to access APIs of other Alibaba Cloud services from applications on the elastic container instance.

Create an instance RAM role

Call the CreateRole operation to create an instance RAM role. For information about the parameters, see CreateRole.

You can use the RoleName parameter to specify a role name. The ECIRamRoleTest role name is used in this example. Then, configure AssumeRolePolicyDocument based on the following code.

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

Attach a policy to the instance RAM role

  1. Call the CreatePolicy operation to create a custom policy.

    Configure the following parameters in the request:

    • PolicyName: the name of the policy. The ECIRamRoleTestPolicy name is used in this example.

    • PolicyDocument: the details about the policy.

      {
           "Statement": [
               {
               "Action": [
                   "oss:Get*",
                   "oss:List*"
               ],
               "Effect": "Allow",
               "Resource": "*"
               }
           ],
           "Version": "1"
       }

    For more information, see CreatePolicy.

  2. Call the AttachPolicyToRole operation to attach the policy to the RAM role.

    Configure the following parameters in the request:

    • PolicyName: the name of the policy. The ECIRamRoleTestPolicy name is used in this example.

    • PolicyType: the type of the policy. Set this parameter to Custom.

    • RoleName: the name of the RAM role. The ECIRamRoleTest name is used in this example.

    For more information, see AttachPolicyToRole.

Authorize a RAM user to use the instance RAM role

If you want a RAM user to use the instance RAM role, you must grant the ram:PassRole permission of the instance RAM role to the RAM user. If the RAM user does not have the ram:PassRole permission, the RAM user cannot exercise the permissions that are specified in role policies.

  1. Log on to the RAM console by using a RAM user that has administrative permissions or by using an Alibaba Cloud account.

  2. Authorize the RAM user to use the instance RAM role.

    To authorize the RAM user to use the instance RAM role, create the following custom policy and attach the policy to the RAM user. ECIRamRoleTest is the name of the instance RAM role. The ram:PassRole permission of the RAM role is to be granted to the RAM user. For more information, see Grant permissions to a RAM user.

    {
       "Statement": [
        {
          "Effect": "Allow",
          "Action": "ram:PassRole",
          "Resource": "acs:ram:*:*:role/ECIRamRoleTest" 
        }
      ],
      "Version": "1"
    }                

Assign the instance RAM role to an elastic container instance

When you call the CreateContainerGroup operation to create an elastic container instance, you can use the RamRoleName parameter to specify the RAM role. For more information, see CreateContainerGroup.

Note

Only one instance RAM role can be assigned to an elastic container instance. If an instance RAM role is assigned to an elastic container instance, an error message appears when you attempt to assign another instance RAM role to the instance.

Obtain an STS token

You can access the metadata URL in the pod to obtain STS tokens of the RAM role. STS tokens can be used to perform permissions and use resources of the RAM role. STS tokens are automatically and regularly updated.

curl http://100.100.100.200/latest/meta-data/ram/security-credentials/${your_ram_role_name}

Replace [role-name] in the preceding command with the actual RAM role name. If the RAM role name is ECIRamRoleTest, run the following command:

curl http://100.100.100.200/latest/meta-data/ram/security-credentials/ECIRamRoleTest

You can obtain the STS token in the command output. Example:

{
  "AccessKeyId" : "STS.******",
  "AccessKeySecret" : "******",
  "Expiration" : "2023-06-22T19:13:58Z",
  "SecurityToken" : "******",
  "LastUpdated" : "2023-06-22T13:13:58Z",
  "Code" : "Success"
}

Access Alibaba Cloud services based on the STS token

The following example shows how to use SDK for Go to access Alibaba Cloud services by using an STS token. In this example, you can access an OSS bucket by using the STS token that you obtained and view all listed objects in the bucket.

Note

This example is only used to demonstrate how to access Alibaba Cloud services by using STS tokens. In actual scenarios, write code based on your business requirements. For more information, see the SDK of the cloud service that you want to use.

package main

import (
	"encoding/json"
	"flag"
	"log"
	"os/exec"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

const (
	securityCredUrl = "http://100.100.100.200/latest/meta-data/ram/security-credentials/"
)

var (
	ossEndpoint   string
	ossBucketName string
)

func init() {
	flag.StringVar(&ossEndpoint, "endpoint", "oss-cn-hangzhou-internal.aliyuncs.com", "Please input oss endpoint, Recommended internal endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
	flag.StringVar(&ossBucketName, "bucket", "", "Please input oss bucket name")
}

type AssumedRoleUserCredentialsWithServiceIdentity struct {
	AccessKeyId     string `json:"AccessKeyId" xml:"AccessKeyId"`
	AccessKeySecret string `json:"AccessKeySecret" xml:"AccessKeySecret"`
	Expiration      string `json:"Expiration" xml:"Expiration"`
	SecurityToken   string `json:"SecurityToken" xml:"SecurityToken"`
	LastUpdated     string `json:"LastUpdated" xml:"LastUpdated"`
	Code            string `json:"Code" xml:"Code"`
}

func main() {
	flag.Parse()

	if ossEndpoint == "" {
		log.Fatal("Please input oss endpoint, eg: oss-cn-hangzhou-internal.aliyuncs.com")
	}
	if ossBucketName == "" {
		log.Fatal("Please input oss endpoint")
	}

	output, err := exec.Command("curl", securityCredUrl).Output()
	if err != nil {
		log.Fatalf("Failed to get ramrole name from metaserver: %s", err)
	}

	output, err = exec.Command("curl", securityCredUrl+string(output)).Output()
	if err != nil {
		log.Fatalf("Failed to get security credentials from metaserver: %s", err)
	}

	authServiceIdentity := new(AssumedRoleUserCredentialsWithServiceIdentity)
	if err := json.Unmarshal(output, authServiceIdentity); err != nil {
		log.Fatalf("Failed to Unmarshal to AssumedRoleUserCredentialsWithServiceIdentity: %s", err)
	}

	// Create an OSS client instance. If the OSS client is used in a production environment, you need to regularly update the OSS client to prevent the STS token from expiring and failure in access to Alibaba Cloud services.
	ossClient, err := oss.New(ossEndpoint, authServiceIdentity.AccessKeyId,
		authServiceIdentity.AccessKeySecret, oss.SecurityToken(authServiceIdentity.SecurityToken))
	if err != nil {
		log.Fatalf("Failed to new oss client: %s", err)
	}

	// Obtain a bucket.
	bucket, err := ossClient.Bucket(ossBucketName)
	if err != nil {
		log.Fatalf("Failed to get bucket %q: %s", ossBucketName, err)
	}

	// List objects in the bucket.
	marker := ""
	for {
		lsRes, err := bucket.ListObjects(oss.Marker(marker))
		if err != nil {
			log.Fatalf("Failed to list object from bucket %q: %s", ossBucketName, err)
		}
		// Display the listed objects. By default, a maximum of 100 objects are returned at a time. 
		for _, object := range lsRes.Objects {
			log.Println("Bucket: ", object.Key)
		}
		if lsRes.IsTruncated {
			marker = lsRes.NextMarker
		} else {
			break
		}
	}
}