#javascript #node.js #aws-sdk
#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;
Любая помощь приветствуется!
Комментарии:
1. В чем ошибка?
Ответ №1:
Есть пара ошибок, которые вы допускаете, принимая роль и используя эти учетные данные для доступа к другим ресурсам.
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;
Прочитайте приведенную ниже документацию для получения дополнительных вариантов использования
Ответ №2:
Это типичная проблема синхронизации js asycn. Вы вызываете IIFE
, который является вашим (async () => {...})();
первым, тогда list_queues()
в стеке вызовов произойдет первым, потому что sts.assumeRole(...)
вызов асинхронный. Другое дело, поскольку вы уже используете async / await, тогда вам не нужно использовать .then()
, просто используйте await
напрямую, чтобы избежать обратного вызова neste.
Правильный способ:
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;