AWS Lambda makes it easy to build highly available serverless applications quickly. However, setting up resources in multiple regions makes it difficult to manage the applications since cross region access is limited by design in AWS for security and performance reasons. Fortunately, AWS makes it easy to access resources across regions in your intend to do so.
In this example. I’ll show you how to invoke a Lambda in one region from a Lambda in another region.
Lambda that invokes the other Lambda: SourceLambda in Oregon (us-west-2)
Lambda that is invoked: TargetLambda in N.Virginia (us-east-1)
Contents
Target Lambda
Let us create and test the target Lambda function first. Open AWS Console, switch to the target region from the Regions dropdown at the top right. In this example, N.Virginia (us-east-1) is the target Region. Go to Lambda console from the search box and click the Create function button. Give it a name and click the Create button. Enter the following code:
import json from datetime import datetime def lambda_handler(event, context): print(event) print("TargetLambda invoked at: {datetime}".format(datetime=datetime.now())) return { 'statusCode': 200, 'body': json.dumps('Hello from TargetLambda!') }
The code prints some statements for debugging and verification to a CloudWatch log group and then returns a message to the caller.
Click the Deploy button. A banner message appears confirming that the changes have been deployed. Click the Test tab and create a test event with the default input parameters provided. Execute the function and check the CloudWatch log group pertaining to the function. You should see entries similar to this:
Once you verify that the Lambda has executed successfully and you see the logs in CloudWatch, move on to creating the source Lambda function.
Source Lambda
In the AWS console, change the Region to the source region. In this example, Oregon (us-west-2) is the source Region. Search Lambda in search box and go the Lambda console. Click Create function button, provide a name for the function and click Create. Replace the function code with the code below:
import json import boto3 from datetime import datetime def lambda_handler(event, context): lambda_useast1 = boto3.client('lambda', region_name='us-east-1') function_name = "arn:aws:lambda:us-east-1:000000000000:function:TargetLambda" payload = json.dumps('{"Message":"Hello from SourceLambda", "Timestamp":"' + str(datetime.now()) +'"}') response = lambda_useast1.invoke( FunctionName = function_name, Payload = payload ) response_payload = response['Payload'].read() response_arr = json.loads(response_payload) return response_arr['body']
Click the Deploy button. A banner message appears confirming that the changes have been deployed.
This code invokes the target function by specifying its ARN in the invoke method call, passes a static message to the invoked function and then returns the response returned by the called function. The code uses the boto3 library to access the AWS resources, in this case, the Lambda. The line that does the trick is
lambda_useast1 = boto3.client('lambda', region_name='us-east-1')
The region_name
parameter specifies the region where the target function is located. If you remove this parameter from the invoke function call, you’ll encounter this error:
An error occurred (ResourceNotFoundException) when calling the Invoke operation: Functions from 'us-east-1' are not reachable in this region ('us-west-2')
Permissions
At this stage, if you try to execute the function, you’ll see this error:
An error occurred (AccessDeniedException) when calling the Invoke operation: User: arn:aws:sts::000000000000:assumed-role/SourceLambda-role-p4ql5a89/SourceLambda is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:000000000000:function:TargetLambda because no identity-based policy allows the lambda:InvokeFunction action
This is because the source Lambda function does not have the required permissions to invoke the target Lambda function. The permissions must be granted manually. In the source Lambda function, click Configuration tab and click the Permissions tab in the left tab bar.
As shown above, a Role has been automatically created and associated with the Lambda function. Click the Role name link to edit the permission policy. Under Permission policies, expand the policy and click Edit.
It displays the auto-generated policy with one entry for writing to the log group. Replace the policy with the policy below. Replace 000000000000
with your AWS Account Number which can be found when you click your name at the top right of the screen (next to Regions dropdown). Make sure you specify the correct source and target regions as well.
Click Review policy and then click Save changes.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "lambda:InvokeFunction", "logs:CreateLogGroup" ], "Resource": [ "arn:aws:logs:us-west-2:000000000000:*", "arn:aws:lambda:us-east-1:000000000000:function:TargetLambda" ] }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:us-west-2:000000000000:log-group:/aws/lambda/SourceLambda:*" } ] }
We are done. Now run the source Lambda function by clicking the Test button. You should see the message "Hello from TargetLambda!"
returned by the target function, which ensures that the invocation was successful.
Verify the Target Lambda function CloudWatch log group to ensure that the target function was indeed invoked successfully. You should see the "Hello from SourceLambda"
message that was sent by the source function.
Summary
There might be some practical reasons for having resources in specific regions and have your resources across multiple regions. Cross Lambda function invocation makes it easy to access resources in one region from resources in other regions.
thanks – very clear and just what I was looking for 🙂
You’re welcome. I’m happy that you liked the article and found it useful.