Calling one Lambda Function from another with the Lambda .NET SDK

Want to learn more about AWS Lambda and .NET? Check out my A Cloud Guru course on ASP.NET Web API and Lambda.

Download full source code.

Calling one Lambda function from another is something you’ll occasionally need to do. If you are using Lambda function URLs it is a simple HTTP request. But you can also use the AWS Lambda SDK to invoke the other function.

In this example, I have two functions, one called Catalog, and one called Inventory. The Catalog function calls the Inventory function and receives a response.

The two functions are very simple, but they are useful for demonstrating the technique.

1. Get the tools

Install the latest tooling, this lets you deploy and run Lambda functions.

dotnet tool install -g Amazon.Lambda.Tools

Install the latest Lambda function templates.

dotnet new --install Amazon.Lambda.Templates

Get the latest version of the AWS CLI, from here.

2. Create the functions

Create two functions, one called Catalog and one called Inventory.

Run the following commands -

dotnet new lambda.EmptyFunction --name Catalog
dotnet new lambda.EmptyFunction --name Inventory

3. Replace the code

Catalog function

Change to the directory Catalog/src/Catalog/. Add the AWS Lambda SDK to the project, the will let you call the Inventory function.

Run the following -

dotnet add package AWSSDK.Lambda

Open the Function.cs file and replace the code with the following -

 1using Amazon.Lambda;
 2using Amazon.Lambda.Core;
 3using Amazon.Lambda.Model;
 4using System.Text.Json;
 5
 6// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
 7[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
 8
 9namespace Catalog;
10
11public class Function
12{
13    public async Task<string> FunctionHandler(string catalogItemId, ILambdaContext context)
14    {
15        context.Logger.LogInformation($"Searching the catalog for an item with id: {catalogItemId}");
16
17        AmazonLambdaClient client = new AmazonLambdaClient();
18
19        var request = new InvokeRequest
20        {
21            FunctionName = "Inventory",
22            Payload = JsonSerializer.Serialize(catalogItemId) // note that we are serializing the catalogItemId to JSON, this is important.
23        };
24        var result = await client.InvokeAsync(request);
25        var item = JsonSerializer.Deserialize<Item>(result.Payload);
26
27        return $"Catalog function called the Inventory function which returned an item: {item.InventoryId}, {item.Name}, {item.Quantity}";
28    }
29}
30
31public class Item
32{
33    public string InventoryId { get; init; }
34    public string Name { get; init; }
35    public int Quantity { get; init; }
36} 
 
Pay attention to line 22 if the input to the function you are calling is a string, you need to serialize it.

Inventory function

Change to the directory Inventory/src/Inventory/.

Open the Function.cs file and replace the code with the following -

 1using Amazon.Lambda.Core;
 2
 3// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
 4[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
 5
 6namespace Inventory;
 7
 8public class Function
 9{
10    public Item FunctionHandler(string inventoryId, ILambdaContext context)
11    {
12        // Perform a search for the inventory item
13        context.Logger.LogInformation($"Searching for inventory item with id: {inventoryId}");
14        var item = new Item(){ InventoryId = "15a", Name = "Red Running Shoes", Quantity = 12};
15        return item;
16    }
17}
18
19public class Item
20{
21    public string InventoryId { get; init; }
22    public string Name { get; init; }
23    public int Quantity { get; init; }
24} 

4. Deploy the functions

From the Catalog/src/Catalog/ directory, run the following -

dotnet lambda deploy-function Catalog

You will be asked to select an IAM role, or create a new one, at the bottom of the list will be *** Create new IAM Role ***, type in the associated number.

You will be asked for a role name, enter CatalogRole.

After this you will be prompted to select the IAM Policy to attach to the role, choose AWSLambdaBasicExecutionRole, it is number 6 on my list.

After a few seconds, the function will be deployed.

Repeat the process for the Inventory/src/Inventory/ function, giving it a role name of InventoryRole.

5. Invoke the Catalog function

To invoke the Catalog function, run the following -

dotnet lambda invoke-function Catalog --payload '15a'

You will get an error saying that role the Catalog function is running as does not have permission to invoke the Inventory function -

"errorType": "AmazonLambdaException",
 "errorMessage": "User: arn:aws:sts::xxxxxxxxx:assumed-role/CatalogRole/Catalog is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:xxxxxxxx:function:Inventory because no identity-based policy allows the lambda:InvokeFunction action",
 "stackTrace": [

6. Grant the Catalog function permission to invoke the Inventory function

You need to grant the Catalog function permission to invoke the Inventory function, but to do this, you need the ARN of the Inventory function.

Run the following -

dotnet lambda  get-function-config Inventory

The ARN will be the second item in the table.

In the Catalog/src/Catalog directory, create a new directory called policies, and create a file there called InvokeInventoryFunction.json

Add the following to that file, replacing the “Resource” with the ARN you just got -

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action":[
                "lambda:InvokeFunction"
            ],
            "Resource": "arn:aws:lambda:us-east-1:xxxxxxx:function:Inventory"
        }
    ]
}

From the command line run the following -

aws iam put-role-policy --role-name CatalogRole --policy-name InvokeInventoryFunction --policy-document file://policies/InvokeInventoryFunction.json

7. Invoke the Catalog function again

It can take a while for permissions to be applied so I suggest redeploying the function first.

Run -

dotnet lambda deploy-function Catalog

Now invoke the function -

dotnet lambda invoke-function Catalog --payload '15a'

And you should get a response -

Payload:
"Catalog function called the Inventory function and returned and item: 15a, Red Running Shoes, 12"

That’s it!

Download full source code.

comments powered by Disqus

Related