使用IAM角色而不是秘密和访问密钥下载和上传文件

时间:2020-04-27 10:29:43

标签: spring amazon-web-services spring-boot amazon-s3 amazon-iam

我正在使用AmazonS3客户端下载文件:

export default (props) => (
  <table className="table">
    <thead className="table-head">
      <tr>
        <th onClick={props.changeSortAscDesc}>ID <small>{props.sortAscDesc}</small></th>  
        <th>TITLE</th>
        <th>CREATED_AT</th>
        <th>UPDATED_AT</th>
      </tr>
    </thead>
    <tbody className="table-body">
       {props.dataAttribute.map(item => (
        <tr key={item.id}>
          <td>{item.id}</td>
          <td>{item.title}</td>
          <td>{item.created_at}</td>
          <td>{item.updated_at}</td>
        </tr>
      ))}
    </tbody>
  </table>
);

我的属性配置如下:

@Value("${cloud.aws.assumeRoleARN}")
private String assumeRoleARN;

@Bean
public AmazonS3Client generateS3Client() {
    AWSCredentialsProvider awsCredentialsProvider = roleCredentialsProvider();
    AmazonS3Client client = new AmazonS3Client(awsCredentialsProvider);
    return client;
}


@Bean
@Primary
public AWSCredentialsProvider roleCredentialsProvider() {
    String roleSessionName = "PP-Session-" + Thread.currentThread().getId();

    AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest();
    assumeRoleRequest.setRoleArn(assumeRoleARN);
    assumeRoleRequest.setExternalId("123");
    assumeRoleRequest.setRoleSessionName(roleSessionName);

    AWSSecurityTokenServiceClient stsClient = new AWSSecurityTokenServiceClient();
    stsClient.setRegion(Region.getRegion(Regions.EU_CENTRAL_1));

    STSAssumeRoleSessionCredentialsProvider.Builder builder = new  STSAssumeRoleSessionCredentialsProvider.Builder(assumeRoleARN,roleSessionName);

    STSAssumeRoleSessionCredentialsProvider stsAssumeRoleSessionCredentialsProvider = builder.withStsClient(stsClient).build();
    return stsAssumeRoleSessionCredentialsProvider;


}

该角色的信任实体定义为:

app.awsServices.bucketName=${S3_BUCKET_NAME}
cloud.aws.assumeRoleARN = arn:aws:iam::365991658844:role/external_id_role
cloud.aws.stack.auto=false
cloud.aws.region.static=eu-central-1

但是我反复得到:

    {
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::365991658844:user/test"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "123"
        }
      }
    }
  ]
}

1 个答案:

答案 0 :(得分:0)

您在这里遇到几个问题。

首先,您正在使用帐户的根凭据运行此程序。由于您为AWSSecurityTokenServiceClient使用了无参数构造函数,因此这意味着您要在环境变量或$HOME/.aws/credentials(或$HOME/.aws/config)中提供这些凭据。

这通常是一个不好的做法,因此第一步应该是为自己创建一个新用户。您将需要为此用户创建访问密钥,并更改当前使用这些密钥的任何配置。并且,您应该删除root用户的访问密钥(以及使用非常长的随机密码和多因素身份验证)。

您还可以使用“测试”用户担任该角色(假设其为sts:AssumeRole权限)。但是,在信任策略中指定单个用户会限制您的灵活性:您必须使用该用户的凭据承担角色。这意味着,如果您在EC2或Lambda上运行,则需要在配置中提供该用户的凭据,这与Amazon的best practices不符。

一种更好的方法来信任整个AWS帐户,然后对可以承担该角色的那些用户/组/角色使用显式访问策略。该信任策略如下所示(请注意,此信任策略中的“ root”不是 表示可以由帐户的root用户接受):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

您可以根据需要添加外部ID的条件。但是,在执行此操作之前,应先询问是否为appropriate to your situation。如果您不从不相关的帐户承担此角色,则没有理由使用外部ID。

接下来,每个可以担当此角色的用户/组/角色必须具有如下策略:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": [
        "arn:aws:iam::123456789012:role/ExampleRole"
      ]
    }
  ]
}

请注意,对于所有这些示例,123456789012帐号应替换为您正在使用的实际帐号。