您在使用阿里云产品的SDK时,如果引入匹配此SDK的托管凭据插件,则可以通过托管RAM凭据的名称使用RAM用户的AccessKey,而无需关心AccessKey是什么,或者它是否被轮换。

工作原理

应用程序使用托管凭据插件后,只需要引用托管RAM凭据(RAM用户的AccessKey)的凭据名称。插件将根据凭据名称从凭据管家获取凭据的值(AccessKey)并缓存在应用程序的内存中。插件也会以指定的间隔(可配置)从凭据管家重新获取凭据的值并刷新本地的缓存。

应用程序使用阿里云SDK时,将通过插件缓存的AccessKey对云产品发起请求。

在某些情况下,缓存的RAM凭据不再有效,这通常发生在管理员在凭据管家中人工轮转凭据,以响应安全事件时。使用无效RAM凭据调用阿里云服务通常会导致应用程序产生异常。如果异常中包含的错误代码为InvalidAccessKeyId.NotFoundInvalidAccessKeyId,则托管凭据插件将立即刷新缓存的RAM凭据并重试失败的请求。

如果使用过期AccessKey调用某些云服务API返回的错误代码和上述所列错误码不同,应用开发人员可以修改默认的错误重试行为。更多信息,请参见示例二:修改默认过期处理程序

支持插件的阿里云SDK

阿里云提供了多种不同的SDK,针对不同SDK的托管凭据插件需要分别开发。下表列出了可以使用托管凭据插件的阿里云SDK。

阿里云SDK名称 支持插件的SDK版本 对应SDK的托管凭据插件
阿里云Java SDK 4.3.2~4.5.17 阿里云Java SDK托管凭据插件
OSS Java SDK 2.1.0~3.10.2 OSS Java SDK托管凭据插件
消息队列商业版TCP协议Java SDK 1.8.5.Final~1.8.7.4.Final 消息队列商业版TCP协议Java SDK托管凭据插件

安装托管凭据插件

针对阿里云的各类Java SDK的托管凭据插件,您可以访问多种阿里云SDK的托管凭据插件开源代码仓库了解更多安装信息。更多信息,请参见多种阿里云SDK的托管凭据插件开源代码仓库

您可以通过Maven的方式在项目中按需引入阿里云SDK托管凭据Java插件。以下以OSS插件导入为例,为您介绍需要添加的依赖信息。

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-sdk-oss-managed-credentials-provider</artifactId>
    <version>x.x.x</version>
</dependency>
说明 多种阿里云SDK的托管凭据插件具体版本,请参见aliyun-sdk-managed-credentials-providers-java release

示例一:在阿里云SDK中使用托管RAM凭据

  1. 为云服务的SDK配置托管凭据插件。

    您可以通过配置文件(managed_credentials_providers.properties)指定从凭据管家获取托管凭据的方式,以配置应用接入点的Client Key为例进行介绍。关于如何创建Client Key,请参见为AAP绑定Client Key

    ## 配置访问方式。
    credentials_type=client_key
    
    ## 读取Client Key的解密密码:支持从环境变量或者文件读取。
    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_private_key_path=#your client key private key file path#
    
    ## 配置关联的KMS地域。
    cache_client_region_id=[{"regionId":"#regionId#"}]
  2. 使用托管RAM凭据访问云服务。
    • 方法一:编码方式(以托管RAM凭据访问OSS为例)
      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 OssPluginSample {
      
          public static void main(String[] args) throws Exception {
              String secretName = "******";
              String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
      
              // 获取OSS客户端。
              OSS ossClient = new ProxyOSSClientBuilder().build(endpoint, secretName);
      
              List<Bucket> buckets = ossClient.listBuckets();
              for (Bucket bucket : buckets) {
                  if (bucket != null) {
                      // do something with bucket
                  }
              }
      
              // 通过以下方法关闭客户端来释放插件关联的资源。
               ossClient.shutdown();
          }
      }
    • 方法二:Spring Bean方式(以快速集成OSS SDK为例)
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd">
          <bean name="proxyOSSClientBuilder" class="com.aliyun.kms.secretsmanager.plugin.oss.ProxyOSSClientBuilder" scope="singleton" />
      </beans>

示例二:修改默认过期处理程序

托管凭据插件默认实现AKExpireHandler的接口调用,用来判断对云服务的调用是否使用了无效的凭据。使用无效凭据时,插件将重新从凭据管家获取最新的凭据,然后重试SDK对云服务的调用过程。

AKExpireHandler的接口定义如下:

package com.aliyun.kms.secretsmanager.plugin.common;

public interface AKExpireHandler<TException> {

  /**
   * 判断异常是否由AccessKey过期引起。
   *
   * @param e
   * @return
   */
  boolean judgeAKExpire(TException e);
}

您可以重新实现AKExpireHandler的接口调用,判断云服务返回的错误码是否由使用无效AccessKey引起,示例如下:

import com.aliyun.kms.secretsmanager.plugin.sdkcore.ProxyAcsClient;
import com.aliyun.kms.secretsmanager.plugin.common.AKExpireHandler;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;

import java.util.HashSet;
import java.util.Set;

public class SdkRetrySample {

  public static void main(String[]args) throws Exception{
    String region="cn-hangzhou";
    String secretName="******";

    // 获取阿里云SDK客户端,并对特定的错误码进行重新获取凭据。
    IAcsClient client = new ProxyAcsClient(
        region, secretName, new CustomHandler());

    // 业务代码。
    invoke(client,region);

    // 通过以下方法关闭客户端来释放插件关联的资源。 
    client.shutdown();
  }
}

class CustomHandler implements AKExpireHandler<ClientException> {
  private Set<String> errorCodeSet;

  public CustomerHandler() {
      errorCodeSet = new HashSet<String>();
      // 自行添加错误码,触发客户端重新从凭据管家获取托管的RAM凭据。
      errorCodeSet.add("InvalidAccessKeyId.NotFound");
      errorCodeSet.add("InvalidAccessKeyId");
  }

  @Override
  public boolean judgeAKExpire(ClientException e) {
      return errorCodeSet.contains(e.getErrCode());
  }

}