使用ECS实例RAM角色安全访问KMS

ECS实例RAM角色是RAM角色的一种,它让ECS实例扮演具有某些权限的角色。当您的自建应用部署在阿里云ECS服务器上时,可以使用ECS实例RAM角色访问KMS。本文介绍了如何使用ECS实例RAM角色访问KMS。

支持ECS实例RAM角色的SDK

  • 阿里云SDK:用于执行管控类操作。

  • 凭据SDK:包含凭据客户端、凭据JDBC客户端、RAM凭据插件,用于获取凭据值。

注意事项

  • ECS实例的网络类型为专有网络VPC。

  • 一个ECS实例只能授予一个RAM角色。

  • 若您的账户为RAM用户(子账号),请先联系阿里云账号(主账号)获取配置RAM角色的权限。具体操作,请参见授权RAM用户使用实例RAM角色

步骤一:创建RAM角色并授权

通过RAM控制台

  1. 创建可信实体为阿里云服务的RAM角色。

    1. 登录RAM控制台

    2. 在左侧导航栏,选择身份管理 > 角色

    3. 角色页面,单击创建角色,按照界面提示完成角色创建。注意以下参数,其他参数按需填写。

      • 角色名称:本文示例为EcsRamRoleTest。

      • 可信实体类型:选择阿里云服务

      • 角色类型:选择普通服务角色

      • 受信服务:选择云服务器

  2. 授予RAM角色访问KMS的权限。

    成功创建RAM角色后,该RAM角色没有任何权限,您需要为该RAM角色授权。

    1. 角色页面,单击目标RAM角色操作列的新增授权

    2. 新增授权页面,在系统策略上填写KMS系统策略名称(AliyunKMSFullAccess),然后单击确定

通过RAM OpenAPI

  1. 创建可信实体为阿里云服务的RAM角色。

    调用RAM的CreateRole - 创建角色接口,请求参数设置如下:

    • RoleName:填写RAM角色名称(本文示例为EcsRamRoleTest)。

    • AssumeRolePolicyDocument:填写如下策略内容,表示允许ECS扮演该角色。

      {
          "Statement": [
              {
                  "Action": "sts:AssumeRole", 
                  "Effect": "Allow", 
                  "Principal": {
                      "Service": [
                          "ecs.aliyuncs.com"
                      ]
                  }
              }
          ], 
          "Version": "1"
      }
  2. 授予RAM角色访问KMS的权限。

    调用RAM的AttachPolicyToRole - 为指定角色添加权限接口,为实例RAM角色(EcsRamRoleTest)添加AliyunKMSFullAccess系统权限。请求参数设置如下:

    • PolicyType:填写System,表示系统策略。

    • PolicyName:填写KMS系统策略名称(AliyunKMSFullAccess)。

    • RoleName:填写RAM角色名称(EcsRamRoleTest)。

步骤二:将RAM角色授予ECS实例

通过ECS控制台

说明

如果您还未购买ECS实例,请先购买ECS实例。具体操作,请参见自定义购买实例

  1. 登录ECS管理控制台

  2. 在左侧导航栏,选择实例与镜像 > 实例

  3. 在页面左侧顶部,选择ECS实例所在的资源组和地域。

  4. 定位到目标ECS实例,选择图标 > 实例设置 > 授予/收回RAM角色

  5. 在对话框中,选择创建好的RAM角色,单击确定完成授予。

通过ECS OpenAPI

步骤三:使用ECS实例RAM角色访问KMS

以使用Java语言,调用KMS ListKeys接口查询当前地域的所有密钥ID为例。更详细的SDK使用指导请参见SDK参考

阿里云SDK(V1.0)

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);

        // 设置RAM角色。本文示例使用"EcsRamRoleTest"。
        String roleName = "EcsRamRoleTest"; 

        // 设置ECS实例RAM角色的凭证Provider。
        AlibabaCloudCredentialsProvider provider = new InstanceProfileCredentialsProvider(roleName);

        IAcsClient client = new DefaultAcsClient(profile, provider);

        ListKeysRequest request = new ListKeysRequest();
      
        try {
            ListKeysResponse 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());
        }

    }
}

阿里云SDK(V2.0)

package com.aliyun.sample;

import com.aliyun.tea.*;

public class Sample {

    public static com.aliyun.kms20160120.Client createClient() throws Exception {
        com.aliyun.credentials.models.Config credentialConfig = new com.aliyun.credentials.models.Config();
        // 凭证类型
        credentialConfig.type = "ecs_ram_role";
        // 选填,该ECS实例角色名称,不填会自动获取,但是建议加上以减少请求次数
        credentialConfig.roleName = "<your-ecsRamRoleName>";
        com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client(credentialConfig);

        com.aliyun.teaopenapi.models.Config kmsClientConfig = new com.aliyun.teaopenapi.models.Config()
        //设置KMS endpoint,例如:kms.cn-hangzhou.aliyuncs.com
        .setEndpoint( "kms.cn-hangzhou.aliyuncs.com").
                setCredential(credentialClient);
        return new com.aliyun.kms20160120.Client(kmsClientConfig);

    }

    public static void main(String[] args_) throws Exception {
        java.util.List<String> args = java.util.Arrays.asList(args_);
        com.aliyun.kms20160120.Client client = Sample.createClient();
        com.aliyun.kms20160120.models.ListKeysRequest listKeysRequest = new com.aliyun.kms20160120.models.ListKeysRequest();
        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
        try {
            client.listKeysWithOptions(listKeysRequest, runtime);
        } catch (TeaException error) {
            System.out.println(error.getMessage());
            com.aliyun.teautil.Common.assertAsString(error.message);
        } catch (Exception _error) {
            _error.printStackTrace();
        }        
    }
}

凭据客户端

更多详细信息,请参见凭据客户端

  1. 通过系统环境变量或配置文件secretsmanager.properties配置以下参数。

    参数

    参数值

    credentials_type

    固定取值ecs_ram_role。

    credentials_role_session_name

    RAM角色名称。

    cache_client_region_id

    格式为[{"regionId":"<your region id>"}],请将<your region id>替换为您真实的地域ID。

  2. 构建客户端获取凭据值。

    import com.aliyuncs.kms.secretsmanager.client.SecretCacheClient;
    import com.aliyuncs.kms.secretsmanager.client.SecretCacheClientBuilder;
    import com.aliyuncs.kms.secretsmanager.client.exception.CacheSecretException;
    import com.aliyuncs.kms.secretsmanager.client.model.SecretInfo;
    
    public class CacheClientEnvironmentSample {
    
        public static void main(String[] args) {
            try {
                //构建凭据客户端
                SecretCacheClient client = SecretCacheClientBuilder.newClient();
                //使用构建好的客户端获取凭据信息
                SecretInfo secretInfo = client.getSecretInfo("#secretName#");
                System.out.println(secretInfo);
            } catch (CacheSecretException e) {
                e.printStackTrace();
            }
        }
    }

凭据JDBC客户端

以通过JDBC方式连接MySQL数据库为例介绍。详细信息,请参见凭据JDBC客户端

  1. 在项目的运行代码中新增配置文件secretsmanager.properties

    ## 访问凭据类型
    credentials_type=ecs_ram_role
    ## ECS RAM Role名称
    credentials_role_name=#credentials_role_name#
    ## 关联的KMS服务地域
    cache_client_region_id=[{"regionId":"#regionId#"}]
    ## 用户自定义的刷新频率, 默认为6小时,最小值为5分钟,单位为毫秒
    refresh_secret_ttl=21600000
  2. 通过JDBC方式连接MySQL数据库。

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    
    public class SecretManagerJDBCSample {
        public static void main(String[] args) throws Exception {
            // 加载阿里云凭据管家JDBC Load the JDBC Driver com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver
            Class.forName("com.aliyun.kms.secretsmanager.MysqlSecretsManagerSimpleDriver");
            Connection connect = null;
            try {
                connect = DriverManager.getConnection("secrets-manager:mysql://<YOUR-MYSQL-IP>:<YOUR-MYSQL-PORT>/<YOUR-DATABASE-NAME>", "#your-mysql-secret-name#","");
            } catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }

RAM凭据插件

更多详细信息,请参见RAM凭据插件

  1. 在项目的运行代码中新增配置文件managed_credentials_providers.properties

    credentials_type=ecs_ram_role
    ## ECS RAM Role名称
    credentials_role_name=#credentials_role_name#
    ## 关联的KMS服务地域
    cache_client_region_id=[{"regionId":"#regionId#"}]
  2. 获得阿里云Java SDK客户端并调用云服务。

    以调用ECS DescribeInstanceStatus为例:

    运行以下示例代码时,请自行在pom.xml中添加云服务器aliyun-java-sdk-ecs依赖。

    import com.aliyuncs.IAcsClient;
    import com.aliyuncs.ecs.model.v20140526.DescribeInstanceStatusRequest;
    import com.aliyuncs.ecs.model.v20140526.DescribeInstanceStatusResponse;
    import com.aliyun.kms.secretsmanager.plugin.sdkcore.ProxyAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.exceptions.ServerException;
    
    public class AliyunSdkProviderSample {
        public static void main(String[]args) {
            String secretName="******";
            /*
              如果应用无法设置从classpath和可执行jar包中读取默认配置文件(managed_credentials_providers.properties),
              或需自定义配置文件名称时,可调用以下代码设置自定义配置文件,并按以下顺序读取:
              1."your-config-name"配置绝对路径+文件名称,即读取绝对路径下的文件
              2."your-config-name"仅配置文件名称,默认先读取classpath下的配置文件,再读取可执行jar包中的配置文件
            */
            //ConfigLoader.setConfigName("your-config-name");
            
            // 1. 获取ACSClient by aliyun-java-sdk-managed-credentials-provider
            IAcsClient client = null;
            try {
                client = new ProxyAcsClient("<the regionId of ECS>", secretName);
            } catch (ClientException e) {
                 e.printStackTrace();
             }
            // 2. 调用ECS的OpenAPI实现业务功能
            DescribeInstanceStatusRequest request = new DescribeInstanceStatusRequest();
            DescribeInstanceStatusResponse response;
            try {
                 response = client.getAcsResponse(request);
            } catch (ServerException e) {
                 e.printStackTrace();
             } catch (ClientException e) {
                 e.printStackTrace();
             }
            // 3. 通过下面方法关闭客户端来释放插件关联的资源 
            client.shutdown();
        }
    }

相关文档