1. 用过Aws的都知道,上面的各种服务都是有严格的权限控制的,即使是同一账号也会有不同的角色,类似于 IAM 用户。对于IAM角色可以参考:IAM角色。但是要注意,一次只有一组权限处于活动状态。在担任某个角色时,将临时放弃以前的用户或角色权限并使用为该角色分配的权限。
2. 假设现在有这样一个需求,我们的应用程序中使用了javav2的s3客户端,但部署的服务器上的默认角色并没有访问某个bucket的权限,那么这个时候就需要使用到STS assume role的功能临时生成一个token来访问资源了。
3. 关于assume role的python版本的代码Aws也有介绍。
4. 关于assume role的javav1的代码Aws也有介绍,这是api文档。
5. 遗憾的是,我们现在使用的是javav2的s3客户端,在Aws官网并找不到很详细的使用介绍。这个提供和检索 AWS 凭证可能会对于编码有所帮助,但是没有具体的例子。
6. 以下是对于javav2的S3切换role的总结。
1) 首先导入STS的依赖:
<dependency>
<artifactId>sts</artifactId>
<groupId>software.amazon.awssdk</groupId>
<version>${awsjavasdk.version}</version>
</dependency>
<dependency>
<artifactId>aws-core</artifactId>
<groupId>software.amazon.awssdk</groupId>
<version>${awsjavasdk.version}</version>
</dependency>
2) 假设我们的S3Util是这样的:
package com.bas.common.util;
import org.apache.commons.lang3.StringUtils;
import software.amazon.awssdk.auth.credentials.*;
import software.amazon.awssdk.core.pagination.sync.SdkIterable;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
import software.amazon.awssdk.services.sts.model.Credentials;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.*;
public class S3Util {
private S3Util(){}
public static S3Client builder(String regionStr) {
Region region = Region.US_EAST_1;//default region
if(StringUtils.isNotEmpty(regionStr)) {
region = Region.of(regionStr);
}
return S3Client.builder().region(region).build();
}
public static S3Client builder(Credentials credentials) {
Region region = Region.US_EAST_1;//default region
AwsSessionCredentials awsCreds = AwsSessionCredentials.create(
credentials.accessKeyId(),
credentials.secretAccessKey(),
credentials.sessionToken());
return S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(awsCreds)).region(region).build();
}
}
注: AwsSessionCredentials.create()的accessKeyId和secretAccessKey别弄反位置了。
3) 其实assume的用法很简单:
package com.bas.common.util;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.AssumeRoleRequest;
import software.amazon.awssdk.services.sts.model.AssumeRoleResponse;
import software.amazon.awssdk.services.sts.model.Credentials;
public class AssumeCredentials {
public static Credentials assumeRole(String regionKey, String roleArn, String sessionName) {
StsClient stsClient = StsClient.builder().region(Region.US_EAST_1).build();
AssumeRoleResponse roleResponse = stsClient.assumeRole(AssumeRoleRequest.builder().roleArn(roleArn).roleSessionName(sessionName)
// .externalId("Required") // 如果出现403,可能是iam role配置了值为"Required"的external id
.build());
return roleResponse.credentials();
}
}
注:如果stClient是us-east-1的,不能访问其他region的s3。
4) 初始化S3Client的方法:
public static void main(String[] args) {
S3Client s3 = S3Operations.builder(AssumeCredentials.assumeRole(s3Region, roleArn, sessionName));
}
其中,s3Region指的是S3 bucket的region,rolearn是那个bucket具有访问的role,sessionName可以任意起名。