In one of my previous articles I wrote about how to Publish to SNS Topic Subscribed by a Cross-Account SQS Queue. In big organisations, where the infrastructure is organised per multiple AWS accounts, you might find often to do cross-account actions. This article will be about how to do Cross-Account Lambda Invocation.
AWS Lambda – server-less computing platform, that lets you run code without provisioning or managing any server infrastructure. The main advantage of using a Lambda is that you only pay for the compute time that you consume. If your code is not running, you don’t pay anything. The code is uploaded to the Lambda which can be triggered any time directly, via AWS services or from web or mobile apps.

First will start by creating in the second account the following resources:
- a lambda function (AWS::Lambda::Function)
- a lambda permission (AWS::Lambda::Permission) for setting the cross-account action
- a role for the lambda (AWS::IAM::Role)
CloudFormation Parameters – Account 2
[
{
"ParameterKey": "LambdaName",
"ParameterValue": "my-awesome-lambda"
},
{
"ParameterKey": "InvokerRoleArn",
"ParameterValue": "arn:aws:iam::<ACCOUNT-2-NUMBER>:role/role-name"
}
]
CloudFormation Template – Account 2
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Cross account invoking of a lambda",
"Parameters": {
"LambdaName": {
"Description": "The name of the lambda function",
"Type": "String"
},
"InvokerRoleArn": {
"Description": "The role arn of the service that invokes the lambda",
"Type": "String"
}
},
"Resources": {
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Description": "Simple Lambda Example",
"FunctionName": { "Ref": "LambdaName" },
"Code": {
"ZipFile": {
"Fn::Join": [
"",
[
"exports.handler = (event, context, callback) => {",
"callback(null, 'Hello World!');",
"};"
]
]
}
},
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [ "FunctionRole", "Arn" ]
},
"Runtime": "nodejs8.10",
"Timeout": "15"
},
"DependsOn": [ "FunctionRole" ]
},
"Permission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::Sub": "${LambdaFunction.Arn}"
},
"Principal": { "Ref": "InvokerRoleArn" }
}
},
"FunctionRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": [ "sts:AssumeRole" ],
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
}
}
]
}
}
}
}
}
The output of the stack creation should like something like this:

And in the first account we will create:
- a managed policy (AWS::IAM::ManagedPolicy) that will be attached to a role, which allows the action lambda:InvokeFunction to be executed for a provided lambda ARN.
CloudFormation Parameters – Account 1
[
{
"ParameterKey": "CrossAccountLambdaArn",
"ParameterValue": "arn:aws:lambda:eu-west-1:<ACCOUNT-1-NUMBER>:function:my-awesome-lambda"
},
{
"ParameterKey": "Roles",
"ParameterValue": [ "role-1", "role-2" ]
}
]
CloudFormation Template – Account 1
{
"AWSTemplateFormatVersion":"2010-09-09",
"Description":"Provides rules for the cluster to interact with other AWS resources",
"Parameters": {
"CrossAccountLambdaArn": {
"Description": "The name of the lambda function",
"Type": "String"
},
"Roles": {
"Description": "The list of roles that the policy will be attached to",
"Type": "List<String>"
}
},
"Resources":{
"readWrite":{
"Type":"AWS::IAM::ManagedPolicy",
"Properties":{
"Description":"Provides access to invoke lambda from a different account",
"ManagedPolicyName": "cross-account-lambda-invoke-policy",
"Roles": { "Ref" : "Roles" },
"PolicyDocument":{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"lambda:InvokeFunction"
],
"Resource": { "Ref": "CrossAccountLambdaArn"},
"Effect": "Allow"
}
]
}
}
}
}
}

GitHub Repository: https://github.com/sebastianvirlan/aws-cross-account-lambda-invocation
Leave a Reply