Deploying an ASP.NET Core Web API on AWS Lambda

So here we’ll look at deploying a Web API on Lambda & S3. First we’ll look at the guide Amazon provide, and then we will look at things in a bit more detail and tackle the questions left unanswered.

Essentially, this boils down to:

  1. Install the AWS Visual studio toolkit from https://aws.amazon.com/visualstudio/
  2. Create a new visual studio project, selecting the option ‘AWS Serverless Application (.NET Core)’*
  3. Select the ASP.NET Core Web API blueprint
  4. Write your code
  5. Right click the project and ‘Publish to AWS Lambda’

*You can convert an existing project also. I’ll do a follow-up on how this works soon.

So… all done, right? That was easy!

Well… not quite. What if your web API needs to communicate with RDS? What if it needs to talk to other external services & APIs? Can you still use Nlog and Swagger? How do you publish to separate staging and production environments?

All these answers and more can be found below.

But first, let’s go back to the beginning:

1) Creating the API

So, I create an ASP.NET Core Web API from the project menu, call it ‘AndyTestAPI’, and modify the controller to add my test methods.

The exact code isn’t important here (in a production environment for example, you’re more likely to use Entity Framework than direct SQL queries), but the point is I’ve added three methods — one for a simple GET request, one which checks connectivity to an external location (www.google.com) and one which performs a query on a database I set up in AWS RDS earlier.

Great! Now let’s build it and check it works

Aw crap. There’s always something…

Damn. So now I update my copy of visual studio, then I install the latest copy of the .NET Core SDK, and try again.

Success! Now I run the API and call my methods to check they work:

All good. Note that in order for the database connection to work whilst developing on my local machine, the security group on my AWS RDS instance has been set to allow access only from my specific IP address.

Lets publish to AWS lambda (right click on the project in Visual Studio) and run the queries again

You’ll need to set up an AWS user account in IAM with programmatic access. Mine is called ‘awsdev’.
Note the AWS Serverless URL. This is where you call your API

As expected, the RDS connection fails because the security group is currently blocking all incoming traffic from unrecognised sources.

2) Getting the Lambda Web API talking to RDS

Ideally, AWS resources that talk to each other should keep those communications within AWS, so what we will do to give lambda access to the RDS is as follows:

  1. Create a new security group in our VPC for our lamda-based API
  2. Assign our lambda API proxy function to this VPC and security group
  3. Add a rule in the RDS security group to allow access from requests originating in the lambda function’s security group
The security group on your lambda function can remain with the default rules

Note the slightly ominous warning about external access at the bottom here. We’ll come back to this shortly. After saving, scroll to the top of the page and you may see an error like the following:

To fix this, go to your IAM settings and add AWSLambdaVPCAccessExecutionRole policy to your proxy function’s role. It should now look as follows:

Now you can update your lambda VPC settings, followed by your RDS security group.

Note that we’ve added access for the id of the lambda security group we created earlier, not an IP address

Now we can run our tests again. Our database connectivity is now working, but our external access test gives us the following:

OH GOD! GOOGLE IS DOWN! Or…. wait, what was that warning about external access from our lambda function if we make it run in a VPC?

3) External connectivity from the VPC

So, we broke it. And we need to add NAT to fix it. We don’t want to screw around with everything else running in our VPC, so at this point I am going to create two (for availability) private subnets pointed at a NAT purely for our lambda function to run in. So off we go to AWS VPC settings…

First, we will make a NAT Gateway & EIP on one of our existing subnet(s)

Now we will create some new subnets to sit within our VPC. Assign these whatever IP range is suitable for your setup.

Now create a new route table in your VPC, and add the 0.0.0.0/0 route to it, pointing to your NAT Gateway created earlier.

Assign your private subnet(s) to the route you’ve just made

And finally, go back to your lambda proxy function and update the VPC subnets

Now we run the test functions again, and everything works! Hurrah! We now have an ASP.NET Core Web API deployed to AWS Lambda using S3, and it is able to both make external connections and query databases we’ve set up on RDS.

Continued…

In part 2 (coming soon), we cover using NLog, Swagger UI, and deploying to separate Staging & Production environments