如何等待AWS承担角色,然后进行模块定义

时间:2019-04-06 09:18:12

标签: javascript node.js aws-sdk

我正在尝试创建一个导出一些函数和变量的模块,但是在执行任何操作之前,它必须切换用户角色。这是我尝试过的代码。我希望先执行匿名异步功能,然后等待其完成的所有后续操作,否则其他请求将无权完成。

现在,我收到一个访问被拒绝错误,因为在listQueues完成之前调用了assumeRole

const AWS = require('aws-sdk');

AWS.config.update({region: 'eu-west-1'});
var sts = new AWS.STS();
var sqs;

(async () => {
  let role_promise = await sts.assumeRole({
    RoleArn: 'arn:aws:iam::xxxx:role/UserRole',
    RoleSessionName: 'NodeDeveloperRoleSession'
  }).promise().then(data => {
    console.log('Assumed role success :)');
    AWS.config.update({
      accessKeyId: data.Credentials.AccessKeyId,
      secretAccessKey: data.Credentials.SecretAccessKey,
      sessionToken: data.Credentials.SessionToken
    });
    sqs = new AWS.SQS({apiVersion: '2012-11-05'});
  }).catch(err => {
    console.log('Cannot assume role :(');
    console.log(err, err.stack);
  })
})();

async function list_queues() {
  let result = await sqs.listQueues({}).promise();
  return result.QueueUrls;
}

const result = list_queues();
exports.queues;

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:0)

在担任角色并使用该凭据访问其他资源时,您会犯几个错误。

const AWS = require('aws-sdk');

AWS.config.update({region: 'eu-west-1'});
var sts = new AWS.STS();
var sqs;

(async () => {
  let role_promise = await sts.assumeRole({
    RoleArn: 'arn:aws:iam::xxxx:role/UserRole',
    RoleSessionName: 'NodeDeveloperRoleSession'
  }).promise().then(data => {
    console.log('Assumed role success :)');

    /* here you are making AWS globally to use your assume role, 
       this will make subsequent call error prone, may or may not work
       depending on how you are making call 
   */

    AWS.config.update({
      accessKeyId: data.Credentials.AccessKeyId,
      secretAccessKey: data.Credentials.SecretAccessKey,
      sessionToken: data.Credentials.SessionToken
    });

    sqs = new AWS.SQS({apiVersion: '2012-11-05'});

  }).catch(err => {
    console.log('Cannot assume role :(');
    console.log(err, err.stack);
  })
})();

async function list_queues() {
  let result = await sqs.listQueues({}).promise();
  return result.QueueUrls;
}

const result = list_queues();
exports.queues;

这是我认为assume role并使用所需资源的更好方法:

const AWS = require('aws-sdk');

AWS.config.update({region: 'eu-west-1'});
var sts = new AWS.STS();
var sqs;

(async () => {
  let role_promise = await sts.assumeRole({
    RoleArn: 'arn:aws:iam::xxxx:role/UserRole',
    RoleSessionName: 'NodeDeveloperRoleSession'
  }).promise().then(data => {
    console.log('Assumed role success :)');

    /* 
      It will use your AWS assume role credential and will not set it globally,
      Which means you can access resources of multiple account in same function 
      likewise.
   */
    var creds = new AWS.Credentials({
        accessKeyId: data.Credentials.AccessKeyId,
        secretAccessKey: data.Credentials.SecretAccessKey,
        sessionToken: data.Credentials.SessionToken
    });

    /* now use creds to create object of the resources that you want to access from 
       that account */
   // Also, in this case using endpoint is advisable
   // I have set it to us-east-2, you can use any endpoint where your service is
    sqs = new AWS.SQS({apiVersion: '2012-11-05', credentials:  creds, endpoint: 'sqs.us-east-2.amazonaws.com'});

  }).catch(err => {
    console.log('Cannot assume role :(');
    console.log(err, err.stack);
  })
})();

async function list_queues() {
  let result = await sqs.listQueues({}).promise();
  return result.QueueUrls;
}

const result = list_queues();
exports.queues;

阅读以下文档以了解更多用例

More on Credential
AWS regions and endpoints

答案 1 :(得分:0)

这是一个典型的js asycn计时问题。您先调用IIFE,即(async () => {...})();,然后再调用栈中的list_queues(),因为sts.assumeRole(...)调用是异步的。另一件事是,因为您已经使用了异步/等待,所以不必使用.then(),只需直接使用await即可避免嵌套回调。

正确的方法:

const AWS = require('aws-sdk');

AWS.config.update({ region: 'eu-west-1' });
const sts = new AWS.STS();
let queues;

(async () => {
  try {
    const data = await sts.assumeRole({
      RoleArn: 'arn:aws:iam::xxxx:role/UserRole',
      RoleSessionName: 'NodeDeveloperRoleSession'
    }).promise();
    console.log('Assumed role success :)');
    AWS.config.update({  // or you can init your SQS with this Credential
      accessKeyId: data.Credentials.AccessKeyId,
      secretAccessKey: data.Credentials.SecretAccessKey,
      sessionToken: data.Credentials.SessionToken
    });
    const sqs = new AWS.SQS({ apiVersion: '2012-11-05' });
    const result = await sqs.listQueues({}).promise();
    queues = result.QueueUrls;
  } catch (err) {
    console.log('Cannot assume role :(');
    console.log(err, err.stack);
  }
})();

exports = queues;