AWS STS 临时授权方案

官方文档:
https://docs.amazonaws.cn/IAM/latest/UserGuide/id_credentials_temp_request.html


描述一下这篇文章的背景:

1 背景

使用cognito 控制app接入:
APP 通过cognito服务的开发者授权验证方式接入到的cognito服务身份池。通过userid 作为开发人员标识换到cognito indentity pool 的唯一标识 indentityid。 而每一个通过验证的用户都可以用身份映射到一个AWS IAM Role(角色)。而角色可以分配一些策略。这些策略可以使用一些通配规则,拿到对应的indentityid。
比如分配到某身份上的S3访问策略(policy)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws-cn:s3:::test",
                "arn:aws-cn:s3:::test/users/${cognito-identity.amazonaws.com:sub}",
                "arn:aws-cn:s3:::test/users/${cognito-identity.amazonaws.com:sub}/*"
            ]
        }
    ]

该策略使用后即可访问 test S3存储桶下的 users 目录,且以身份池命名的文件夹的读取权限。
比如用5aa0d55246c14813a2313c18换到的indentityID为 cn-north-1:e1fb5311-asdfsad-sadfasdfa-ecfadb
如果仅仅使用S3这样看起来没有问题。 但近期引入了KVS 服务。而KVS的资源创建不允许有: 。所以这里就给权限访问带来了困扰。而且通配的情况也让授权访问不够灵活。

2 使用AWS STS颁发临时身份凭证

https://docs.amazonaws.cn/IAM/latest/UserGuide/id_credentials_temp_request.html
这是IAM的关于临时身份授权的文档。提供了几种方式如下:

AWS STS API 谁能调用 凭证生命周期(最小值 /最大值 / 默认值) MFA 支持¹ 会话策略支持² 对生成的临时凭证的限制
AssumeRole 具有现有临时安全凭证的 IAM 用户或 IAM 角色 15 分钟 | 最大会话持续时间设置³ | 1 小时 无法调用 GetFederationTokenGetSessionToken
AssumeRoleWithSAML 任何用户;发起人必须传递 SAML 身份验证响应,指示身份验证来自已知的身份提供商 15 分钟 | 最大会话持续时间设置³ | 1 小时 无法调用 GetFederationTokenGetSessionToken
AssumeRoleWithWebIdentity 任何用户;发起人必须传递 Web 身份令牌,指示身份验证来自已知的身份提供商 15 分钟 | 最大会话持续时间设置³ | 1 小时 无法调用 GetFederationTokenGetSessionToken
GetFederationToken IAM 用户或 AWS 账户根用户 IAM 用户:15 分钟 / 36 小时 / 12 小时
根用户:15 分钟 / 1 小时 / 1 小时
无法使用 AWS CLI 或 AWS API 调用 IAM 操作。
无法调用除 GetCallerIdentity 之外的 AWS STS 操作。⁴
允许通过 SSO 登录到控制台。⁵
GetSessionToken IAM 用户或 AWS 账户根用户 IAM 用户:15 分钟 / 36 小时 / 12 小时
根用户:15 分钟 / 1 小时 / 1 小时
除非请求附带了 MFA 信息,否则无法调用 IAM API 操作。
无法调用除 AssumeRoleGetCallerIdentity 之外的 AWS STS API 操作。
不允许通过 SSO 登录到控制台。⁶

提供了以上5中方式。
如果使用身份池的方式实质上应该是使用了AssumeRoleWithWebIdentity 该方式。
这里我们想要更灵活的授予访问权限这里就提供两种方式:

  • GetFederationToken—通过自定义身份代理进行联合
  • GetSessionToken—不受信任的环境中用户的临时凭证


针对应用场景,是想要给APP临时授权,所以选择的为GetFederationToken。

关于GetFederationToken的有效期:
GetFederationToken API 操作为联合身份用户返回一组临时安全凭证。该 API 不同于 AssumeRole其默认有效期大大增加 (12 小时而不是 1 小时)。此外,您还可以使用 DurationSeconds 参数指定临时安全凭证保持有效的持续时间。生成的凭证在指定的持续时间内有效,即,900 秒 (15 分钟) 到 129,600 秒 (36 小时) 之间。较长的有效期有助于减少对 AWS 的调用次数,因为您不需要频繁获取新凭证。

关于GetFederationToken的权限范围:
您在发出此请求时使用特定 IAM 用户的凭证。临时安全凭证的权限是由调用 GetFederationToken 时传递的会话策略决定的。生成的会话权限是 IAM 用户策略与您传递的会话策略的交集。使用会话策略授予的权限不能超过请求联合的 IAM 用户的基于身份的策略允许的权限。有关角色会话权限的更多信息,请参阅会话策略。


测试代码(nodejs)
代码通过STS GetFederationToken 获取credentials 并用该credentials初始化S3获取S3中数据。
实际使用中获取credentials 由服务端完成
使用credentials初始化S3获取S3中文件由APP完成

const AWS = require('aws-sdk');
const sts = new AWS.STS({
    accessKeyId: 'AKIAXXXXXXXXXXXXX',
    secretAccessKey: 'NeUXXXXXXXXXXXXXXXXXXXXXXXXXX',
    region: 'cn-northwest-1',
});

let str1 = {
  "Version": "2012-10-17",
  "Statement": [
      {
          "Sid": "VisualEditor0",
          "Effect": "Allow",
          "Action": "s3:GetObject",
          "Resource": [
              "arn:aws-cn:s3:::testbucket",
              "arn:aws-cn:s3:::testbucket/test/",
              "arn:aws-cn:s3:::testbucket/test/*"
          ]
      }
  ]
}

function getFederationToken(){
  return new Promise((resolve, reject) => {
    var params = {
      Policy:JSON.stringify(str1), //"{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Stmt1\",\"Effect\":\"Allow\",\"Action\":\"s3:ListAllMyBuckets\",\"Resource\":\"*\"}]}",
      Name: "test"  //假定角色会话的标识符。 userid
    };
    sts.getFederationToken(params, function (err, data) {
      if (err){
        console.log(err, err.stack); // an error occurred
        return reject(err);
      } 
      else{
        console.log(data);
        return resolve(data.Credentials);
      }
    });
  })
}

async function run(){
  const credentials = await getFederationToken();
  let s3 = new AWS.S3({ accessKeyId: credentials.AccessKeyId, secretAccessKey: credentials.SecretAccessKey, sessionToken: credentials.SessionToken, region:'cn-northwest-1'});
  console.log(credentials);
  let getParams = {
    Bucket: "testbucket", 
    Key: 'kedaya1.jfif'
  };
  s3.getObject(getParams, function(err, data) {
    if (err){
        console.error("get object error");
        console.error(err);
    }
    console.info('-------GET object------');
    console.info(data);
  });
}

run();

返回值

{
  AccessKeyId: 'ASXXXXXXXXXXXXXX',
  SecretAccessKey: 'qKFBNTXXXXXXXXXXXXX',
  SessionToken: 'IQoJb3XXXXXXXXXXXXX',
  Expiration: 2020-06-16T18:18:20.000Z
}

你可能感兴趣的:(cloud,aws,sts,临时授权)