您在KMS托管RAM用户的AccessKey后,可以安装RAM凭据插件,在使用阿里云SDK时通过引用RAM凭据的名称,获取AccessKey完成API鉴权,无需关注AccessKey的具体信息或者是否被轮转。本文介绍RAM凭据插件的工作原理、安装和使用。
工作原理
RAM凭据插件根据凭据名称,从KMS获取RAM凭据值并缓存在应用程序的内存中。应用程序使用阿里云SDK时,通过RAM凭据插件本地缓存的AccessKey向云产品发起请求。
当由于凭据轮转等原因导致RAM凭据插件本地缓存的AccessKey失效时,RAM凭据插件将立即向KMS重新获取凭据并刷新本地缓存,并根据您设置的错误重试行为,通过最新获取的RAM凭据重试云产品调用请求。RAM凭据插件默认依据云产品调用响应错误码InvalidAccessKeyId和InvalidAccessKeyId.NotFound来判断AccessKey无效。
支持的阿里云SDK
KMS为下表中的阿里云SDK提供了RAM凭据插件。
Java SDK(仅支持Java 8及以上版本)
阿里云SDK名称 | RAM凭据插件模块名称 |
Python SDK
阿里云SDK名称 | RAM凭据插件模块名称 | 说明 |
无。 |
Go SDK
Go凭据插件遇到InvalidAccessKeyId错误时不会自动重试。自动轮转的凭据可依靠定时刷新机制(6小时)正常获取新凭据,如果需手动轮换凭据,请确保轮换窗口至少为 12小时,以避免因凭据失效导致任务中断。更多信息,请参见Go RAM 插件报错 InvalidAccessKeyId后,凭据失效如何解决?。
阿里云SDK名称 | RAM凭据插件模块名称 | 说明 |
无。 |
步骤一:创建访问凭证
场景一:通过共享网关获取凭据值
网络类型为公网或VPC网络。访问凭证支持ECS实例RAM角色、ClientKey。
ECS实例RAM角色
ECS RAM 角色是指为 ECS 实例授予的 RAM 角色,该 RAM 角色是一个受信服务为云服务器的普通服务角色。使用实例 RAM 角色可以实现在 ECS 实例内部无需配置 AccessKey 即可获取临时访问凭证(STS Token),从而调用 KMS 的 OpenAPI。
具体操作,请参见实例RAM角色。
登录RAM 控制台,创建可信实体为阿里云服务的 RAM 角色。
信任主体类型:选择云服务器。
信任主体名称:选择云服务器 ECS。
授予 RAM 角色访问 KMS 的权限。
方式一:设置基于身份的策略
单击 RAM 角色操作列的新增授权,直接绑定 KMS 内置系统权限策略到 RAM 角色。KMS 内置系统权限策略,请参见密钥管理服务系统权限策略参考。
说明同时支持自定义权限策略,具体操作请参见创建自定义权限策略。
方式二:设置基于资源的策略
KMS 支持基于资源的策略,即为单个密钥和凭据设置访问权限,用于控制哪些阿里云账号、RAM 用户、RAM 角色有权限来管理或使用 KMS 密钥、凭据。详细介绍,请参见密钥策略、凭据策略。
登录ECS 管理控制台,将 RAM 角色授予 ECS 实例。
ClientKey
登录密钥管理服务控制台,在顶部菜单栏选择地域后,在左侧导航栏单击。
创建网络规则(非必须)。
说明如果不需要基于来源 IP 限制访问,则不需要设置网络规则。但为了更高的安全性,通常建议合理设置。
单击网络规则页签,然后单击创建网络规则。
在创建网络规则面板,网络类型选择Public,填写允许访问的源IP地址后,单击确定。
创建权限策略。
单击权限策略,然后单击创建权限策略。
在创建权限策略面板,按照下方提示完成共享网关配置后,单击确定。
作用域:KMS共享网关
允许访问的资源:勾选需要访问的凭据
网络控制规则(非必须):勾选步骤二创建网络规则。
创建应用接入点 AAP。
单击应用接入页签,然后单击创建应用接入点。
在创建应用接入点面板,创建模式选择标准创建,然后按照下方提示完成各项配置。
配置项
说明
认证方式
选择 ClientKey
Client Key加密口令
设置 8~64 位包含数字、英文大小写、特殊字符
~!@#$%^&*?_-的字符串有效期
重要推荐设置为 1 年,以降低 ClientKey 被泄露的风险。请务必在到期前更换,以免无法正常访问 KMS。具体操作,请参见更换ClientKey。
权限策略
选择步骤三创建的权限策略。
单击确定,浏览器会自动下载ClientKey。ClientKey包含以下内容:
应用身份凭证内容(ClientKeyContent):文件名默认为
clientKey_****.json凭证口令(ClientKeyPassword):文件名默认为
clientKey_****_Password.txt。
场景二:通过专属网关获取凭据值(不推荐)
网络类型为KMS私有网络。访问凭证仅支持ClientKey。
ClientKey 支持快速创建和标准创建两种方式。关于 ClientKey 的详细介绍,请参见应用接入点概述、创建应用接入点。
方式一:快速创建
操作便捷高效,适用于快速测试和开发场景,该方式创建的访问凭证可以访问 KMS 实例的全部资源。
登录密钥管理服务控制台,在顶部菜单栏选择地域后,在左侧导航栏单击。
在应用接入页签,单击创建应用接入点,在创建应用接入点面板完成各项配置。
配置项
说明
创建模式
选择快速创建。
作用域(KMS实例)
选择应用要访问的KMS实例。
应用接入点名称
自定义应用接入点的名称。
认证方式
默认为ClientKey,不支持修改。
加密算法
选择用于加密 ClientKey 的加密算法。可选 TripleDES-CBC 或 RC2-CBC,默认为 RC2-CBC。
说明RC2-CBC 适用于大多数运行环境,推荐优先使用;若您的运行环境有更严格的算法要求而不支持 RC2-CBC,请选择 TripleDES-CBC
默认权限策略
默认为
key/*secret/*,不支持修改。即应用可以访问指定KMS实例中的所有密钥和凭据。单击确定,浏览器会自动下载ClientKey。ClientKey包含以下内容:
应用身份凭证内容(ClientKeyContent):文件名默认为
clientKey_****.json凭证口令(ClientKeyPassword):文件名默认为
clientKey_****_Password.txt。
方式二:标准创建
若希望对资源设置更精细化的访问权限,建议使用标准创建。
请参考创建应用接入点中的标准创建方式,创建用于访问专属网关的 ClientKey。关键配置说明如下:
配置网络规则时,网络类型选择Private。
配置权限规则作用域时,请选择对应的KMS 实例 ID。
创建完成后,浏览器会自动下载 ClientKey。ClientKey 包含以下内容:
应用身份凭证内容(ClientKeyContent):文件名默认为
clientKey_****.json凭证口令(ClientKeyPassword):文件名默认为
clientKey_****_Password.txt。
步骤二:通过配置文件设置RAM凭据插件运行参数
RAM凭据插件仅支持通过配置文件方式,配置运行参数。您需要在应用程序的运行目录中新增配置文件(managed_credentials_providers.properties),根据不同认证方式在配置文件中新增内容。
如果您的应用程序无法自动读取到managed_credentials_providers.properties文件,请参考代码示例,通过在代码中设置配置文件路径的方式读取。
ECS实例RAM角色
配置文件内容如下。
credentials_type=ecs_ram_role
## ECS RAM Role名称
credentials_role_name=#credentials_role_name#
## 关联的KMS服务地域
cache_client_region_id=[{"regionId":"#regionId#"}]ClientKey(共享网关)
通过KMS共享网关Endpoint获取凭据值,配置文件内容如下。
## 访问凭据类型。
credentials_type=client_key
## 读取client key的凭证口令:支持从环境变量或者文件读取。
## 凭证口令:在应用接入点AAP中创建Client Key时保存的凭证口令(ClientKeyPassword)。
client_key_password_from_env_variable=#your client key private key password environment variable name#
client_key_password_from_file_path=#your client key private key password file path#
# Client Key文件路径。
# Client Key文件:在应用接入点AAP中创建Client Key时下载的应用身份凭证内容(ClientKeyContent)。
# 下载后文件名默认为ClientKey_******.json。
client_key_private_key_path=#your client key private key file path#
## 关联的KMS服务地域。
cache_client_region_id=[{"regionId":"#regionId#"}]ClientKey(专属网关)
通过KMS专属网关Endpoint获取凭据值,配置文件内容如下。
方案一:配置ClientKey凭证口令(
clientKey_****_Password.txt)文件的路径,由SDK读取其中的内容。cache_client_dkms_config_info=[{"regionId":"<your dkms regionId>","endpoint":"<your dkms endpoint>","passwordFromFilePath":"< your password file path >","clientKeyFile":"<your Client Key file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]方案二:直接配置ClientKey凭证口令(ClientKeyPassword)内容
警告请先将凭证口令(ClientKeyPassword)即
clientKey_****_Password.txt中的内容,存放至自定义环境变量(如clientKeyPassword_content)中。cache_client_dkms_config_info=[{"regionId":"<your dkms regionId>","endpoint":"<your dkms endpoint>","passwordFromEnvVariable":"<YOUR_PASSWORD_ENV_VARIABLE>","clientKeyFile":"<your ClientKey file path>","ignoreSslCerts":false,"caFilePath":"<your CA certificate file path>"}]
步骤三:在云产品SDK中使用RAM凭据插件
Java
阿里云Java SDK(V2.0)
Java 9+ 兼容性说明
通过Maven的方式在项目中引入RAM凭据插件。
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-tea-openapi-sdk-managed-credentials-provider</artifactId> <version>[1.3.5,]</version> </dependency>说明建议您安装最新版本的插件,更多信息,请参见原始代码。
获得阿里云Java SDK客户端并调用云服务,以调用ECS DescribeInstances为例。
添加云服务器ecs20140526依赖。
<dependency> <groupId>com.aliyun</groupId> <artifactId>ecs20140526</artifactId> <version>7.1.0</version> </dependency>调用DescribeInstances接口。
import com.aliyun.ecs20140526.Client; import com.aliyun.ecs20140526.models.DescribeInstancesResponse; import com.aliyun.kms.secretsmanager.plugin.tea.openapi.ProxyClientCreator; import com.google.gson.Gson; public class AliyunTeaOpenApiProviderSample { public static void main(String[] args) throws Exception { // Step 1: 指定托管凭据的名称(在KMS中创建的凭据名称) String secretName = "your-secret-name"; /* 如果应用无法设置从classpath和可执行jar包中读取默认配置文件(managed_credentials_providers.properties), 或需自定义配置文件名称时,可调用以下代码设置自定义配置文件,并按以下顺序读取: 1."your-config-name"配置绝对路径+文件名称,即读取绝对路径下的文件 2."your-config-name"仅配置文件名称,默认先读取classpath下的配置文件,再读取可执行jar包中的配置文件 */ //ConfigLoader.setConfigName("your-config-name"); // Step 2: 配置 OpenAPI 客户端 com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); config.endpoint = "your-product-endpoint"; // 替换为实际的云产品 endpoint // Step 3: 创建客户端实例 Client client = ProxyClientCreator.createClient(config, Client.class, secretName); // Step 4: 调用云服务 API com.aliyun.ecs20140526.models.DescribeInstancesRequest request = new com.aliyun.ecs20140526.models.DescribeInstancesRequest(); request.setRegionId("cn-hangzhou"); // 设置地域ID DescribeInstancesResponse response = client.describeInstances(request); // Step 5: 打印结果 System.out.println(new Gson().toJson(response.getBody())); } }
阿里云Java SDK(V1.0)
通过Maven的方式在项目中引入RAM凭据插件。
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>[4.3.2,5.0.0]</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core-managed-credentials-provider</artifactId> <version>[1.3.1,]</version> </dependency>说明建议您安装最新版本的插件,更多信息,请参见原始代码。
获得阿里云Java SDK客户端并调用云服务。
以调用ECS DescribeInstanceStatus为例。
添加云服务器aliyun-java-sdk-ecs依赖。
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-ecs</artifactId> <version>5.11.20</version> </dependency>调用DescribeInstanceStatus接口。
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(); } }
在OSS SDK中使用
通过Maven的方式在项目中引入RAM凭据插件。
<dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-core</artifactId> <version>4.5.17</version> </dependency> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>[2.1.0,3.10.2]</version> <exclusions> <exclusion> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk-kms</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-sdk-oss-managed-credentials-provider</artifactId> <version>[1.3.1,]</version> </dependency>说明建议您安装最新版本的插件,更多信息,请参见原始代码。
获得OSS Java SDK客户端并调用云服务,以调用OSS listBuckets 为例:
import com.aliyun.kms.secretsmanager.plugin.oss.ProxyOSSClientBuilder; import com.aliyun.oss.OSS; import com.aliyun.oss.model.Bucket; import java.util.List; public class OssProviderSample { public static void main(String[] args) throws Exception { String secretName = "******"; String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; /* 如果应用无法设置从classpath和可执行jar包中读取默认配置文件(managed_credentials_providers.properties), 或需自定义配置文件名称时,可调用以下代码设置自定义配置文件,并按以下顺序读取: 1."your-config-name"配置绝对路径+文件名称,即读取绝对路径下的文件 2."your-config-name"仅配置文件名称,默认先读取classpath下的配置文件,再读取可执行jar包中的配置文件 */ //ConfigLoader.setConfigName("your-config-name"); // 获取Oss Client OSS ossClient = new ProxyOSSClientBuilder().build(endpoint, secretName); // 以下为业务方业务代码:调用阿里云OSS服务实现业务功能 List<Bucket> buckets = ossClient.listBuckets(); for (Bucket bucket : buckets) { if (bucket != null) { // ... } } // 通过下面方法关闭客户端来释放插件关联的资源 ossClient.shutdown(); } }
Python
阿里云Python SDK(V1.0)
执行pip命令以在项目中使用RAM凭据插件。
pip install aliyun-openapi-python-sdk-managed-credentials-provider说明请确保插件版本为0.1.0及以上版本,更多信息,请参见原始代码。
获得阿里云Python SDK客户端并调用云服务。
from aliyun_sdk_secretsmanager_sdk_core_plugin.proxy_acs_client import ProxyAcsClient region="cn-hangzhou" secretName="******" # 1. 获取ACSClient client = ProxyAcsClient(region_id=region, secret_name=secretName ) # 2. 业务方业务代码:使用client调用阿里云服务,无需代码改动。 ... # 3. 通过下面方法关闭客户端来释放插件关联的资源 client.shutdown()
OSS Python SDK
执行pip命令以在项目中使用RAM凭据插件。
pip install aliyun-oss-python-sdk-managed-credentials-provider说明请确保插件版本为0.1.0及以上版本,更多信息,请参见原始代码。
获得阿里云OSS Python SDK客户端并调用云服务。
from aliyun_sdk_secretsmanager_oss_plugin.proxy_bucket import ProxyBucket from itertools import islice endpoint = "******" secret_name ="******" bucket_name = "******" bucket = ProxyBucket(secret_name=secret_name, endpoint=endpoint, bucket_name=bucket_name) objects = bucket.list_objects() for b in islice(objects.object_list, 10): print(b.key) bucket.shutdown()
Go
阿里云Go SDK(V1.0)
安装阿里云Go SDK的RAM凭据插件。
重要建议安装最新版本的插件,更多信息,请参见原始代码。
Go语言下RAM凭据插件依赖的
alibaba-cloud-sdk-go版本需小于v1.63.0,请在插件的go.mod文件中检查并确认版本,以避免潜在的兼容性问题。
方式一:使用
go.mod管理您的依赖。在
go.mod文件中添加以下内容安装依赖包。require ( github.com/aliyun/aliyun-sdk-managed-credentials-providers-go/aliyun-sdk-managed-credentials-providers/alibaba-cloud-sdk-go-managed-credentials-provider vX.X.X )方式二:使用
go get命令获取远程代码包。go get -u github.com/aliyun/aliyun-sdk-mxanaged-credentials-providers-go/aliyun-sdk-managed-credentials-providers/alibaba-cloud-sdk-go-managed-credentials-provider
获得阿里云Go SDK的客户端并调用云服务。
以调用ECS DescribeInstances 为例:
package sample import ( "fmt" "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" sdkcoreprovider "github.com/aliyun/aliyun-sdk-managed-credentials-providers-go/aliyun-sdk-managed-credentials-providers/alibaba-cloud-sdk-go-managed-credentials-provider/sdk" ) func main() { secretName := "********" regionId := "cn-hangzhou" client, err := sdkcoreprovider.GetClient(&ecs.Client{}, regionId, secretName) if err != nil { fmt.Println(err) return } ecsClient := client.(*ecs.Client) request := ecs.CreateDescribeInstancesRequest() instancesResponse, err := ecsClient.DescribeInstances(request) if err != nil { fmt.Println(err) return } for _, instance := range instancesResponse.Instances.Instance { // do something with instance } }
OSS Go SDK
安装OSS Go SDK的RAM凭据插件。
重要建议安装最新版本的插件,更多信息,请参见原始代码。
Go语言下RAM凭据插件依赖的
alibaba-cloud-sdk-go版本需小于v1.63.0,请在插件的go.mod文件中检查并确认版本,以避免潜在的兼容性问题。
方式一:使用
go.mod管理您的依赖。在
go.mod文件中添加以下内容安装依赖包。require ( github.com/aliyun/aliyun-sdk-managed-credentials-providers-go/aliyun-sdk-managed-credentials-providers/aliyun-oss-go-sdk-managed-credentials-provider vX.X.X )方式二:使用
go get命令获取远程代码包。go get -u github.com/aliyun/aliyun-sdk-managed-credentials-providers-go/aliyun-sdk-managed-credentials-providers/aliyun-oss-go-sdk-managed-credentials-provider
获得阿里云OSS Go SDK客户端并调用云服务。
package sample import ( "fmt" ossprovider "aliyun-oss-go-sdk-managed-credentials-provider/sdk" ) func main() { secretName := "********" endpoint := "https://oss-cn-hangzhou.aliyuncs.com" // 获取Proxy Oss Client client, err := ossprovider.New(endpoint, secretName) if err != nil { fmt.Println(err) return } result, err := client.ListBuckets() if err != nil { fmt.Println(err) return } for _, bucket := range result.Buckets { //业务代码 } // 关闭客户端来释放插件关联的资源 client.Shutdown() }
常见问题
Go RAM 插件报错 InvalidAccessKeyId后,凭据失效如何解决?
问题原因:
Go 凭据插件在遇到
InvalidAccessKeyId错误时不会自动重试。手动轮转时若设置了较短的轮转窗口(比如10分钟)小于6小时,可能会遇到客户端AK失效但本地缓存还没来得及刷新的情况。
解决方案
等待系统自动刷新:自动轮转的凭据可依靠定时刷新机制( 时间间隔为6 小时))正常获取新凭据。
即时刷新:在遇到凭据失效时,捕捉异常并调用
sdk.RefreshSecretInfo(secretName)方法,手动刷新RAM凭据。定时刷新:设置一个定时任务,通过自定义的频率调用
sdk.RefreshSecretInfo(secretName)刷新RAM凭据,确保在凭据失效前就获得新的凭据。调整轮转窗口:针对RAM凭据手动轮转场景,建议轮转窗口大于12小时。