關於應用程序中使用STS切換IAM角色

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章