In this blog post, we will discover how to run (invoke) a Lambda function in source account which in turn will execute Lambda function in another (destination) account. This concept is called cross account lambda execution and it does require cross account role (CAR). We will have ready to run CloudFormation script at the end but let’s understand the parts and pieces required to make them work!
CAR-Destination-IAMRole
Let’s create an IAM role in the destination account and specify the trust relationship to the source lambda function and an IAM policy to allow this role to invoke lambda function in the destination account.
Permission policy applied to the CAR-Destination-IAMRole, this policy allows the role to invoke the lambda function.
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:us-east-1:<<destination-account>>:function:CAR-Destination-Lambda" } }
Also, we need to configure Trust Relationship to the CAR-Destination-IAMRole. We are telling an IAM role from source account can assume the role in destination account.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<<source-account>>:role/source-lambda-iam-role", "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
Sample Lambda Function in destination account written in nodejs-
exports.handler = async (event) => { const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda in another account!'), }; return response; };
That’s all we need in the destination account.
Now, let’s create the components needed in the source account- a lambda function and IAM role associated to it.
source-lambda-iam-role
Permission policy to allow the source IAM role to assume the role from destination account
{ "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::<<destination-account>>:role/service-role/CAR-Destination-IAMRole", "Effect": "Allow" } ] }
Again, we would need to specify the Trust Relationship to the source iam role
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
Last thing you need is to create a lambda function in the source account
exports.handler = async (event) => { var aws = require('aws-sdk'); var sts = new aws.STS({ region: process.env.AWS_REGION }); var stsParams = { RoleArn: "arn:aws:iam::<<destination-account>>:role/service-role/CAR-Destination-IAMRole", DurationSeconds: 3600, RoleSessionName: "cross-account-lambda-session" }; const stsResults = await sts.assumeRole(stsParams).promise(); var lambda = new aws.Lambda({ region: process.env.AWS_REGION, accessKeyId: stsResults.Credentials.AccessKeyId, secretAccessKey:stsResults.Credentials.SecretAccessKey, sessionToken: stsResults.Credentials.SessionToken }); const result = await lambda.invoke({ FunctionName: "arn:aws:lambda:us-east-1:<<destination-account>>:function:CAR-Destination-Lambda", InvocationType: "RequestResponse", Payload: "{}" }).promise(); const response = { statusCode: 200, body: JSON.stringify(result) }; return response; };
Okay, we got our lambda function along with the execution IAM role in the source account. Last thing you need is a trigger to fire the lambda in source account. For the purpose of the demo, we will use aws cli with an account profile that has permission to invoke lambda in source account.
Bingo! We are able to execute a lambda is source account which in turn invokes a lambda in destination account.
As promised, let me share the CloudFormation scripts and you can download cloud-formation-source-account-former2.yml and cloud-formation-destination-account-former2.yaml from GitHub repo. Hope you learned how to use Cross Account Role! This example is using lambda resource but you can apply the concept to read/write data from/to S3 bucket across accounts.
For the purpose of learning, I used Former2 tool to script the CloudFormation from existing resources and modified it to support parameters. Former2 requires that you provide IAM key and secret. It’s okay to share them just for demo account but I would not use it for production. More info on Former2.