Invoke a Lambda across multiple AWS accounts

Aleksandr Melnichenko
6 min readOct 23, 2018

--

How to invoke a Lambda across multiple different AWS accounts and regions? How to invoke a Lambda from another Lambda? These are the questions to which you can quickly find answers in this post.

Sometimes you can have a Lambda script that you simply want to execute across multiple AWS accounts and regions without creating several copies of it in each AWS account manually or even using AWS Cloudformation StackSets.

Below you will find step-by-step instructions on how to execute a Lambda function across multiple different AWS accounts and regions, these steps include the following:

  • S3 bucket creation
  • IAM Roles and policies creation
  • SSM Parameter creation
  • Lambda Functions creation
  • Testing

Briefly, Lambda “invoke_master” will do the asynchronous invocation of another Lambda called “invoke_slave” and pass ARN of a remote IAM Role that exists in child(remote) AWS account. Lambda “invoke_slave” after being called will assume the IAM Role and complete a required job.

S3 bucket creation part

I. You need to create an S3 bucket where all Lambda outputs/results will be saved in the HTML format. In our example, each AWS account will have its own file. In order to create a bucket via AWS Management Console simply navigate to S3 and click on “Create Bucket”, choose bucket name and region and click on “Create” or alternatively you can also use following AWS CLI command:

aws s3 mb s3://your_s3_bucket_name_here --region us-east-1

IAM Roles and policies creation part

Summary of this part: we will create two IAM roles in the parent(main) AWS account (ex. id:123456789012) and one IAM Role in each of our child(remote) AWS accounts (ex. id:“111111111111” / id:“222222222222”).

II. First of all, let’s create an IAM Role in the parent(main) AWS account and call it “lambda_functions_invoker”. The role will be assigned to Lambda function called “invoke_master” which will be invoking our second Lambda called “invoke_slave” across multiple different AWS accounts.

Two following IAM policies must be attached to the “lambda_functions_invoker” IAM role:

  • AWS managed policy: AWSLambdaBasicExecutionRole
  • Managed policy: (please create it using JSON provided below)

The managed policy allows invoking other Lambda functions and allows to get a value of SSM parameter “rolearnlist”. You must modify line 15 and replace “123456789012” with Id of your parent(main) AWS account.

III. Secondly, we need to create one more IAM role in the parent(main) AWS account which will be attached to “invoke_slave” Lambda that will be invoked across multiple AWS accounts and contain a necessary job. Let’s call the role “lambda_basicexec_crossaccount”.

Two following IAM policies must be attached to the “lambda_basicexec_crossaccount” IAM role:

  • AWS managed policy: AWSLambdaBasicExecutionRole
  • Inline policy: (please create it using JSON provided below)

The inline policy allows STS assume role action, so Lambda can assume a remote IAM role and have access to the necessary resources in child(remote) AWS accounts. You must modify lines 14 and 19 and replace id:“111111111111” and id:“222222222222” with Ids of your child(remote) AWS accounts. In addition, policy allows to create a new object in your S3 bucket. Please don’t forget that “your_s3_bucket_name_here” in line 9 must be replaces by the name of the S3 bucket that was created earlier.

IV. Finally, we need to log in to our two AWS child(remote) accounts and create IAM role using the following name: “lambda-cross-account-access-role”. When you will be creating it, please select the type of trusted entity “Another AWS account” and provide account Id of your parent(main) AWS account (ex. 123456789012). The role must have those permissions that are required for your job to run. In our example, we will use AWS managed policy “AmazonEC2ReadOnlyAccess”, please make sure you attached it to the role.

SSM Parameter creation part

Summary of this part: we will create SSM Parameter in the parent(main) AWS account (ex. 123456789012) which will contain ARNs of all remote IAM roles.

V. In the parent(main) AWS account open Systems Manager, click on “Parameter Store” -> “Create Parameter” and use following parameter details for creation:

  • Name: “rolearnlist”,
  • Type: “StringList”,
  • Value: “arn:aws:iam::111111111111:role/lambda-cross-account-access-role,arn:aws:iam::222222222222:role/lambda-cross-account-access-role”

Please replace id:“111111111111” and id:“222222222222” with Ids of your child(remote) AWS accounts.

Lambda Functions creation part

Summary of this part: In the parent(main) AWS account (ex. 123456789012) we will create two Lambda functions called “invoke_master” and “invoke_slave”.

Now when IAM Roles and SSM parameter are ready it’s finally time to create our Lambda functions.

VI. Create python 3.6 Lambda function using “invoke_master” name and python code provided below. Please assign “lambda_functions_invoker” IAM role to this Lambda function.

Briefly, “invoke_master” Lambda gets the list of ARNs of remote IAM roles from the ssm parameter, loops through it and invokes multiple versions of “invoke_slave” Lambda with ARN passed as a payload.

VII. Create python 3.6 “invoke_slave” Lambda using the code below and attach IAM role “lambda_basicexec_crossaccount”.

Change timeout to 1 minute under Lambda’s Basic settings. In line 66 “your_s3_bucket_name_here” must be replaces by the name of your S3 bucket that was created earlier. Each invoked version of “invoke_slave” Lambda receives ARN of IAM role and initiates a new session by assuming that role. As a result, Lambda receives temp credentials ACCESS_KEY, SECRET_KEY, SESSION_TOKEN which all can be used for making further API calls in that specific AWS account where the IAM role is. Finally, the part which is between lines 48–69 can be replaced with any other python code which will do the job you need. In our example we are checking and making a report of all Elastic IPs that are not in use. The job runs across all AWS accounts and all existing AWS regions.

Testing part

VIII. Now, when everything is ready, we can do some testing:

  1. Log in to each of your AWS child(remote) accounts, navigate to “EC2” -> “Elastic IPs” and allocate new addresses but do not associate them to the EC2 instances.
  2. Go back to your parent(main) AWS account -> “Lambda” -> click on “invoke_master” -> “Test” -> as a test event pick any name and click on “Create” -> click “Test” again.
  3. Now you can open your S3 bucket where you should be able to find 2 objects with following names: “awsaccount-111111111111-EIPs.html” and “awsaccount-222222222222-EIPs.html” where “1…” and “2…” will be also replaces with Ids of your child(remote) AWS accounts.
S3 bucket objects created by Lambda “invoke_master” (example)
HTML pages content (example)

Conclusion

I hope that my instructions were clear enough and you did not have any problems setting everything up. I did not want to overcomplicate things that is why as an example I decided to use S3 bucket. At the same time, I can also recommend you to use DynamoDB as a destination point of your data. In this case, all your results coming from different AWS accounts and regions can be easily saved into DynamoDB tables and processed later in the way you need.

Using the described method I built a Cloud Dashboard for my team. In my case, the Dashboard is hosted in S3 bucket and is hidden behind the CloudFront with enabled authentication and WAF. Each specific job has it’s own “lambda_slave” Lambda function and DynamoDB table where all results are getting saved. As soon as all results are saved, one more “builder_lambda” gets triggered which requests content from all DynamoDB tables, builds HTML webpage, saves it to S3 bucket, and finally deletes all DynamoDB tables (optional) in order to decrease the monthly bill.

In case if you like this post or interested in knowing more about building your own Dashboard please clap so I can understand it. As soon as I will see the interest from people, I will be glad to write another post and share more details as well as examples of basic python scripts. Thank you for your time!

--

--