FantasticFiasco / aws-signature-version-4

The buttoned-up and boring, but deeply analyzed, implementation of SigV4 in .NET
Apache License 2.0
77 stars 19 forks source link
amazon-web-services aws aws-signature aws-signature-v4 aws-signer aws-sigv4 hacktoberfest http request sign sigv4

AwsSignatureVersion4

CI/CD Codecov NuGet version SemVer NuGet downloads License

The buttoned-up and boring, but deeply analyzed, implementation of Signature Version 4 (SigV4) in .NET.

Package: AwsSignatureVersion4\ Platforms: .NET Standard 2.0, .NET 6

Table of contents

Introduction

This project is unique for me. It's my first that isn't a labor of love.

Having to sign requests in AWS I went through a series of emotions. My first was disappointment, directed at Amazon for not including a Signature Version 4 signer in their AWS SDK for .NET. The functionality is listed on Open Feature Requests for the AWS SDK for .NET but I haven't seen any actions towards an implementation yet.

My second emotion was being overwhelmed. The signing algorithm involved many more steps than I'd thought be possible, and I knew I'd have to spend a lot of time getting conformable with the algorithm.

So here we are, my attempt at implementing the Signature Version 4 algorithm in .NET. Please lets hope that AWS SDK soon releases this functionality so we can deprecate this piece of code...

Super simple to use

The best API is the one you already know. By extending both HttpClient and IHttpClientFactory we hope you'll get an easy integration.

Integration with HttpClient

This project extends the class HttpClient by providing additional overloads to DeleteAsync, GetAsync, GetStringAsync, PatchAsync, PostAsync, PutAsync, SendAsync, and the new synchronous addition to .NET 5 and onwards, Send. These overloads accept the following additional arguments.

These overloads are built to integrate with HttpClient, i.e. HttpClient.BaseAddress and HttpClient.DefaultRequestHeaders will be respected when sending the request.

The following example is demonstrating how one would send a GET /resources request to an IAM authenticated AWS API Gateway on host www.acme.com.

// Don't specify credentials in source code, this is for demo only! See next chapter for more
// information.
var credentials = new ImmutableCredentials("<access key id>", "<secret access key>", null);

var client = new HttpClient();
var response = await client.GetAsync(
  "https://www.acme.com/resources",
  regionName: "us-west-1",
  serviceName: "execute-api",
  credentials: credentials);

Please see the tests directory for other examples.

Integration with IHttpClientFactory

This project supports IHttpClientFactory by means of providing a custom HTTP message handler called AwsSignatureHandler. Once injected into the pipeline of the HTTP client factory it will sign your requests before sending them over the network.

AwsSignatureHandler takes an instance of AwsSignatureHandlerSettings as its only constructor argument, thus you will have to configure your dependency injection container to sufficiently resolve both these classes.

The following example is demonstrating how one would configure the ASP .NET Core service collection to acknowledge a HTTP client named my-client. For more information regarding configuration, please see Dependency injection in ASP.NET Core.

// Don't specify credentials in source code, this is for demo only! See next chapter for more
// information.
var credentials = new ImmutableCredentials("<access key id>", "<secret access key>", null);
services
  .AddTransient<AwsSignatureHandler>()
  .AddTransient(_ => new AwsSignatureHandlerSettings("us-west-1", "execute-api", credentials));

services
  .AddHttpClient("my-client")
  .AddHttpMessageHandler<AwsSignatureHandler>();

Please see the tests directory for other examples.

Credentials

We've come a long way, but let's back up a step. Credentials should not be specified in source code, so where do they come from?

It all starts with a principal, i.e. an entity identifying itself using authentication. In some situations the principal is a IAM user and in other situations it is an entity assuming a IAM role. Whatever your principal is, it has the capability of providing credentials.

How the credentials are provided depend on where you run your code. If you run your code in a ECS Task you get your credentials using ECSTaskCredentials. Other runtime will require other credential providers, all of them are listed in the namespace Amazon.Runtime.

The pledge

This project comes with a pledge, providing transparency on supported and unsupported scenarios.

Install via NuGet

If you want to include AwsSignatureVersion4 in your project, you can install it directly from NuGet.

To install AwsSignatureVersion4, run the following command in the Package Manager Console.

PM> Install-Package AwsSignatureVersion4

You can also install AwsSignatureVersion4 using the dotnet command line interface.

dotnet add package AwsSignatureVersion4

Credit

Thank you JetBrains for your important initiative to support the open source community with free licenses to your products.

JetBrains