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