Mocking AWS with LocalStack in .NET Core 3

Configuring an ASP.NET Core application to interact with AWS mocks

Shtanko Michael
4 min readFeb 4, 2020

Amazon Web Services offers a lot of products and cloud services. It is almost impossible to find an enterprise application developed without any AWS service. It can be virtual servers, scalable data storages, relational or NoSQL databases or a bunch of other services.

Any of the Amazon’s services requires configuration before use, at least for development and production stages. And if the number of services you use exceeds two, then it may take a long time. And you also have to pay for using Amazon’s services even during development and testing.

So what are we supposed to do about it? Right, let’s set up a free local environment that mocks all Amazon’s services!

What is LocalStack?

LocalStack is a framework by Atlassian needed to mock and test all Amazon’s services right on your local machine. It provides the same APIs and opportunities as the real AWS.

LocalStack infrastructure (source https://localstack.cloud)

Benefits of using LocalStack:

  • You can save money during development and testing
  • You can work offline!
  • More straightforward and convenient debugging. No one else can use your own services.
  • Very fast introduction of new Amazon services in the application
  • You still can use aws cli to easily control each of your services.
    All you need to do is add endpoint argument to any request.
    For example, to create an Amazon SQS queue:
aws sqs create-queue --queue-name MyQueue --endpoint http://localhost:4576

Installing LocalStack on your local machine

  • Install Python (<=3.7.x) including pip (python package manager)

I couldn’t install LocalStack via pip with the latest Python version 3.8.1 installed

  • Install Docker
  • Install LocalStack via pip
pip install localstack
  • Run to launch LocalStack’s servises using Docker by default
localstack start

You can also use custom docker-compose.yml file, more info here

Moreover you can avoid of using Docker and launch LocalStack in non-Docker mode using host argument, but it will require addition dependencies and may cause bugs :)

localstack start --host

Using LocalStack services within .NET Core 3 application

Let’s say, we need to build a simple file manager application using Amazon S3 as a file storage, Amazon CloudFront for caching and Amazon CloudWatch for logging.

First of all we need to configure our mock environment. We can do it using aws cli or any GUI client (for example, Commandeer). Personally I prefer console way.

  • Install aws cli tool
  • Configure local profile using your personal access and secret tokens. It can be fake tokens, you can easily use tokens like «ACCESS TOKEN» as an access token and «SECRET TOKEN» as a secret, respectively.
    Use us-east-1 as a default region and json as an output format
aws configure
  • Create S3 bucket dev-files and make it public by default
aws s3 mb s3://dev-files --endpoint http://localhost:4572aws s3api put-bucket-acl --bucket dev-files --acl public-read-write --endpoint http://localhost:4572

Because CloudFront is available only in pro version of LocalStack we just use S3 instead to emulate similar behaviour.

That’s it. We have configured our local AWS environment. Let’s use it in code!

Let’s configure our project to use mock services instead of real ones in Development stage. In my case it’s Amazon S3 client and Amazon CloudWatch client.

  • Install several nuget packages
dotnet add package AWSSDK.S3 --version 3.3.110.1
dotnet add package AWSSDK.CloudWatchLogs --version 3.3.101.78
dotnet add package AWSSDK.Extensions.NETCore.Setup --version 3.3.100.1
dotnet add package Serilog.AspNetCore --version 3.2.0
dotnet add package Serilog.Sinks.AwsCloudWatch --version 4.0.155

The last two packages are used because I prefer Serilog as the default library for logging

  • Now we can replace real Amazon services with LocalStack services in ConfigureServices method of Startup.cs

AppSettings here is a custom class describing appsettings.{ENV}.json. It is used to strongly typify project settings.

All we have left to do is configure Serilog in Configure method of Startup.cs

And don’t forget to call UseSerilog method in Program.cs

This is how appsettings.Development.json file looks like just in case

It’s time to check out our services! Just inject them into the constructor of any controller or somewhere else where you need it and use it.

This is the simplest example of using these services.

Let’s upload some file to our local S3 storage usign cURL

curl -F `file=@file.jpg' https://localhost:44312/file/upload

Now our GET-request should return something like this

If we call a download request using id of any of the previously uploaded files, we should get a presigned link that expires in one day from this moment

curl https://localhost:44312/file/download/{key}

After you copy the link and paste it into your browser, the file should be downloaded without browser’s preview.

And one more thing! To make sure our logger is working properly just use this command:

aws logs get-log-events --log-group-name dev-logs --log-stream-name YYYY-MM-DD --endpoint http://localhost:4586

where YYYY-MM-DD is today’s date according to our LogStreamNameProvider

You should see something like this. If so, then all of our services work perfectly!

That’s it! I hope this article was helpful for you. If you have any questions or suggestions, let me know in the comments. Thank you for reading!

PS: You can find my simple file manager implementation in GitHub by this link!

A simple file manager preview

--

--