Question:
I have an AWS ElasticSearch Cluster in account “A”.
I’m trying to create a lambda (triggered from a DynamoDB Stream) in account “B” that will write to ES in account “A”.
I’m getting the following error:
1 2 3 4 |
{ "Message":"User: arn:aws:sts::AccountB:assumed-role/lambdaRole1/sourceTableToES is not authorized to perform: es:ESHttpPost on resource: beta-na-lifeguard" } |
I have tried putting the STS as well as the ROLE into the ES access policy (within account “A”) with no luck. Here is my policy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::AccountA:user/beta-elasticsearch-admin" }, "Action": "es:*", "Resource": "*" }, { "Effect": "Allow", "Principal": { "AWS": [ "arn:aws:iam::AccountA:user/beta-elasticsearch-readwrite", "arn:aws:iam::AccountA:role/beta-na-DynamoDBStreamLambdaElasticSearch", "arn:aws:sts::AccountB:assumed-role/lambdaRole1/sourceTableToES", "arn:aws:iam::AccountB:role/service-role/lambdaRole1" ] }, "Action": [ "es:ESHttpGet", "es:ESHttpPost", "es:ESHttpPut" ], "Resource": "*" } ] } |
Answer:
In my code above I was adding arn:aws:sts::AccountB:assumed-role/lambdaRole1/sourceTableToSNS
into the AccountA ES access list, that is wrong. Instead do the following:
I already had arn:aws:iam::AccountA:role/beta-na-DynamoDBStreamLambdaElasticSearch
in the ES access list, I needed to add a trust relationship (from the IAM role screen) for that role to be assumable by AccountB. I added this into the trust relationship:
1 2 3 4 5 6 7 8 |
{ "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::AccountB:root" }, "Action": "sts:AssumeRole" } |
Then, in my accountB lambda code, I needed to assume that role. Here is the relevent code from the lambda.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var AWS = require('aws-sdk'); var sts = new AWS.STS({ region: process.env.REGION }); var params = { RoleSessionName: "hello-cross-account-session", RoleArn: "arn:aws:iam::accountA:role/beta-na-DynamoDBStreamLambdaElasticSearch", DurationSeconds: 900 }; sts.assumeRole(params, function (err, data) { if (err) { console.log(err, err.stack); // an error occurred context.fail('failed to assume role ' + err); return; } log("assumed role successfully! %j", data) postToES(bulkUpdateCommand, context); }); |