I have a weird problem where I can't seem to go anywhere with. I have followed everything online (multiple tutorials etc) but can't get sts.assumeRole to work.
My set-up:
I have a bot running in Sub AWS account 1 where I need pricing information from the Main AWS account.
So, I created a role on the Main AWS account to have AWS ce:* access, below:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["ce:*"],
"Resource": ["*"]
}]
}
Trust Relationship
{
"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'
to confirm my understanding, you are trying to assume a role in one account from an ec2 instance in another account.
child
accountmain
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)Move the pricingAWS.getCostAndUsage()
line inside assume role callback. because the line is called before the credentials are updated :). You can also change everything to async/await as I showed below.
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();
hope this helps.