安全凭证服务(STS)

STS即Secure Token Service 是一种安全凭证服务,可以使用STS来完成对于临时用户的访问授权。对于跨用户短期访问s3资源时,可以使用STS服务。这样就不需要透露主账号AK/SK,只需要生成一个短期访问凭证给需要的用户使用即可,避免主账号AK/SK泄露带来的安全风险。

初始化STS服务

String accessKey = "<your-access-key>";
String secretKey = "<your-secret-access-key>";
String endPoint = "<your-endpoint>";
BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
        AwsClientBuilder.EndpointConfiguration endpointConfiguration =
                new AwsClientBuilder.EndpointConfiguration(endPoint, Regions.DEFAULT_REGION.getName());
        return AWSSecurityTokenServiceClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withEndpointConfiguration(endpointConfiguration)
                .build();

获取临时token

private static final String DEFAULT_BUCKET = "<your-bucket-name>";
private static final String ROLE_SESSION_NAME = "<your-session-name>";
private static final String ARN = "arn:aws:iam:::role/xxxxxx";
private static final String POLICY = "{\"Version\":\"2012-10-17\"," + "\"Statement\":" + "{\"Effect\":\"Allow\","
		+ "\"Action\":[\"s3:*\"]," // 允许进行 S3 的所有操作。如果仅需要上传,这里可以设置为 PutObject
		+ "\"Resource\":[\"arn:aws:s3:::" + DEFAULT_BUCKET + "\",\"arn:aws:s3:::" + DEFAULT_BUCKET + "/*\"]"// 允许操作默认桶中的所有文件,可以修改此处来保证操作的文件
            + "}}";
			
public static void assumeRole() {
	try {
		AWSSecurityTokenService stsClient = buildSTSClient();
		AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest();
		assumeRoleRequest.setRoleArn(ARN);
		assumeRoleRequest.setPolicy(POLICY);
		assumeRoleRequest.setRoleSessionName(ROLE_SESSION_NAME);
		assumeRoleRequest.setDurationSeconds(60*60*2);      // 单位秒,有效时间,默认1小时,最长12小时

		System.out.println("policy=" + POLICY);
		AssumeRoleResult assumeRoleRes = stsClient.assumeRole(assumeRoleRequest);
		Credentials stsCredentials = assumeRoleRes.getCredentials();
		System.out.println("ak=" + stsCredentials.getAccessKeyId());
		System.out.println("sk=" + stsCredentials.getSecretAccessKey());
		System.out.println("token=" + stsCredentials.getSessionToken());
	} catch (Exception e) {
		e.printStackTrace();
	}
}

Policy设置例子

允许所有的操作
{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":["s3:*"],"Resource":["arn:aws:s3:::<your-bucket-name>","arn:aws:s3:::<your-bucket-name>/*"]}}

限制只能上传和下载
{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":["s3:PutObject","s3:GetObject"],"Resource":["arn:aws:s3:::<your-bucket-name>","arn:aws:s3:::<your-bucket-name>/*"]}}

使用分片上传
{"Version":"2012-10-17","Statement":{"Effect":"Allow","Action":["s3:PutObject","s3:AbortMultipartUpload","s3:ListBucketMultipartUploads","s3:ListMultipartUploadParts"],"Resource":["arn:aws:s3:::<your-bucket-name>","arn:aws:s3:::<your-bucket-name>/*"]}}

其他操作权限
上传权限:s3:PutObject
下载权限:s3:GetObject
删除权限:s3:DeleteObject
获取列表权限:s3:ListBucket

注意:
1.ListObjects 操作是由ListBucket权限控制的
2."Version:2012-10-17"是系统的policy格式的版本号,不能改成其他日期

更多操作权限可以参考:
https://awspolicygen.s3.amazonaws.com/policygen.html
参数 类型 描述
RoleArn String 角色的ARN,在控制台创建角色后可以查看
Policy String 角色的policy,需要是json格式,限制长度1~2048
RoleSessionName String 角色会话名称,此字段为用户自定义,限制长度2~64
DurationSeconds Integer 会话有效期时间,默认为3600s,范围15分钟至12小时

使用临时token

实现一个CredentialsProvider,支持更新ak/sk和token。

public class MyCredentialsProvider implements AWSCredentialsProvider {
    private AWSCredentials credentials;

    public MyCredentialsProvider(String ak, String sk, String token) {
        this.credentials = new BasicSessionCredentials(ak, sk, token);
    }

    public synchronized AWSCredentials getCredentials() {
        return credentials;
    }

    public synchronized void refresh() {
    }

    // 更新ak,sk,token
    public synchronized void updateCred(String ak, String sk, String token) {
        this.credentials = new BasicSessionCredentials(ak, sk, token);
    }
}

使用临时token

String secretKey = "<your-secret-access-key>";
String endPoint = "<your-endpoint>";
String sessionToken = "<your-session-token>";
MyCredentialsProvider credProvider = new MyCredentialsProvider(accessKey, secretKey, sessionToken);
ClientConfiguration clientConfiguration = new ClientConfiguration();
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(
		endPoint, Regions.DEFAULT_REGION.getName());
return AmazonS3ClientBuilder.standard()
		.withCredentials(credProvider)
		.withClientConfiguration(clientConfiguration)
		.withEndpointConfiguration(endpointConfiguration)
		.build();