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可以任意起名。