温馨提示:本文翻译自stackoverflow.com,查看原文请点击:node.js - NodeJS: aws-sdk sts.assumeRole is not working
amazon-web-services node.js aws-sdk-nodejs assume-role

node.js - NodeJS:aws-sdk sts.assumeRole无法正常工作

发布于 2020-03-27 16:16:40

我有一个奇怪的问题,我似乎无处可去。我已经在线上关注了所有内容(有多个教程等),但是无法使sts.assumeRole正常工作。

我的设置:

  • AWS主账户(用于计费,IAM等)
  • 次级AWS账户1(用于客户1)
  • 次级AWS账户2(用于客户2)
  • 等等

我有一个机器人在Sub AWS账户1运行,我需要从Main AWS账户获取价格信息

因此,我在主AWS账户上创建了一个角色,以具有以下AWS ce:*访问权限:

{
    "Version": "2012-10-17",
    "Statement": [{
            "Effect": "Allow",
            "Action": ["ce:*"],
            "Resource": ["*"]
        }]
}

信任关系

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com",
        "AWS": "arn:aws:iam::SubAWSaccount1-ID:role/instance-profile"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Now, this is the instance-profile attached to the EC2 instance running on the Sub AWS account 1:

"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "VisualEditor1",
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::mainAWSaccount-ID:role/botRole"
    }
  ]
}

Trust relationship

{
  "Version": "2012-10-17",
  "Statement": [
   {
    "Sid": "",
    "Effect": "Allow",
    "Principal": {
      "Service": "ec2.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
   }
  ]
}

Okay, that being out of the way, this is the code that is not working:

var AWS = require('aws-sdk');
var pricingAWS = new AWS.CostExplorer();

var getPricing = function(){

    var costParams = {
        TimePeriod: { Start: "2019-12-01 ", End: "2020-01-01"},
        Granularity: 'MONTHLY',
        Metrics: ['BlendedCost'],
        Filter: {      
            Dimensions: {
                Key: "LINKED_ACCOUNT",
                Values: ["Sub AWS account 2s ID"] //Main AWS account has access to many sub accounts info. So bot in running on Sub account 1, I need info from Sub account 1, 2, 3 etc and Role is on Main account
            }
        }
    };

    var roleToAssume = {
        RoleArn: 'arn:aws:iam::mainAWSaccount-ID:role/botRole',
        RoleSessionName: 'testTestTest',
        DurationSeconds: 900
    };

    var roleCreds = {};

    sts.assumeRole(roleToAssume, function(err, data) {
        if (err) {
            console.log(err);
        } else {
            roleCreds = {
                accessKeyId: data.Credentials.AccessKeyId,
                secretAccessKey: data.Credentials.SecretAccessKey,
                sessionToken: data.Credentials.SessionToken
            };

            pricingAWS.config.update({
                accessKeyId: roleCreds.AccessKeyId,
                secretAccessKey: roleCreds.SecretAccessKey,
                sessionToken: roleCreds.SessionToken
              });
        }
    });

    pricingAWS.getCostAndUsage(costParams, function (err, data) {
        if (err) {
            reject(err);
        }else{
            resolve(data);
        }
    });
};

getPricing();

What I get from the console.log(err)is:

User: arn:aws:sts::SubAWSAccount-1:assumed-role/slack-instance-profile/instanceID is not authorized to perform: ce:GetCostAndUsage on resource: arn:aws:ce:us-east-1:SubAWSAccount-1:/GetCostAndUsage'

查看更多

查看更多

提问者
Shayan Khan
被浏览
158
Arun K 2020-02-04 18:51

to confirm my understanding, you are trying to assume a role in one account from an ec2 instance in another account.

  1. create an IAM role in the child account
  2. allow the newly created role above to assume the role exists in the main account by attaching an IAM policy. Allow the child role to assume the main role via the main role's trust policy (you are doing this already)
  3. 在子ec2实例中运行的Nodejs代码中,担任父角色并阅读帐单报告(您已经在执行此操作)

代码修复

pricingAWS.getCostAndUsage()行移到承担角色回调中。因为该行是在更新凭据之前调用的:)。您还可以将所有内容更改为异步/等待,如下所示。

import AWS = require('aws-sdk');
var pricingAWS = new AWS.CostExplorer();
const sts = new AWS.STS()

var getPricing = async function () {

  var costParams = {
    TimePeriod: { Start: "2019-12-01 ", End: "2020-01-01" },
    Granularity: 'MONTHLY',
    Metrics: ['BlendedCost'],
    Filter: {
      Dimensions: {
        Key: "LINKED_ACCOUNT",
        Values: ["Sub AWS account 2s ID"] //Main AWS account has access to many sub accounts info. So bot in running on Sub account 1, I need info from Sub account 1, 2, 3 etc and Role is on Main account
      }
    }
  };

  var roleToAssume = {
    RoleArn: 'arn:aws:iam::mainAWSaccount-ID:role/botRole',
    RoleSessionName: 'testTestTest',
    DurationSeconds: 900
  };

  var roleCreds = {};


  try {

    const data = await sts.assumeRole(roleToAssume).promise();
    const roleCreds = {
      accessKeyId: data.Credentials.AccessKeyId,
      secretAccessKey: data.Credentials.SecretAccessKey,
      sessionToken: data.Credentials.SessionToken
    };

    pricingAWS.config.update({
      accessKeyId: roleCreds.accessKeyId,
      secretAccessKey: roleCreds.secretAccessKey,
      sessionToken: roleCreds.sessionToken
    });

    const costAndUsage = await pricingAWS.getCostAndUsage(costParams).promise()
    return costAndUsage
  } catch (err) {
    console.log('error: ', err);
    throw err;
  }

};

getPricing();

希望这可以帮助。