Creating async AutoMapper mappings

I’ve finally come to embrace AutoMapper after a long love-hate relationship over the years.  The basic use-case was always useful but there were always edge-cases where it fell down for me.  I’m usually thinking this was my fault as I was mis-using or misunderstanding.

In my current usage, I’ve come across the need to use async along side mapping data to a domain object. Mapping a domain object isn’t just for DB calls (though, these can be async as well). While you might want to do crazier things like an HTTP call for data to map, my use-case for this is simple: a Redis cache. The cache contains things from the DB and the API is rightfully async.

AutoMapper Type Converters

AutoMapper does provide a way to custom build a type: TypeConverters. However, the API is sync and it seems unlikely that async support will come to this or similar or any APIs in AutoMapper. The work of maintaining sync and async code paths is non-trivial and requiring async code paths for simple mappings does seem silly.

I wish there was a good way to do this but there doesn’t seem to be. Enter AsyncMapper!

Narochno.AsyncMapper

This is a library that sits on top of AutoMapper and aims to basically provide async versions of a Type Converter.

AsyncMapper first looks for it’s own interfaces for the requested mapping. If found, it uses that. If not found, it forwards to AutoMapper. Ideally, you’d still use AutoMapper inside AsyncMappings to do the grunt work of mapping as well.

My toy example should illustrate what I’m after.

The intent is this a just a small helper library for async operations but AutoMapper still is the primary way to map.

What next?

Look at Narochno.AsyncMapper and see how it looks and feels. There are a few things on the TODO but I wouldn’t grow more functionality into this. This library greatly assists my mapping organization that needs async.

 

 

Keeping secrets safe with ASP.NET Core and Credstash

Originally posted on Medium: https://medium.com/@adamhathcock/keeping-secrets-safe-with-asp-net-core-and-credstash-b6e268176791

I primarily use Amazon Web Services and .NET Core. Most .NET users tend to look to Azure by default because of Microsoft support. However, I strongly prefer AWS. All information here deals with .NET Core and AWS.

Secrets

Keeping secrets secure seems to be a pretty hard problem. The best thing with the biggest mindshare behind it seems to be Hashicorp Vault but it’s an application with more infrastructure to setup just to get it working.

I really hate having to run 3rd party applications in my own cloud applications. I only do it when I’m forced to. Basically, only when Amazon doesn’t have a matching service or the AWS service isn’t fit for purpose.

However, they do: the Key Management Service. I’m not going to get into detail about it but it’s not suitable by itself.

Fortunately, someone else already did some leg work to use KMS: enter Credstash

Credstash

You can read about Credstash on the github site but basically it’s a command line utility to add and retrieve secrets. It’s python based and perfectly good for doing the admin of secrets. However, I want to use it with my .NET Core applications.

Credstash uses KMS to protect keys and DynamoDB to store encrypted values.

Credstash vs Hashicorp Vault

Reference: Credstash

Vault is really neat and they do some cool things (dynamic secret generation, key-splitting to protect master keys, etc.), but there are still some reasons why you might pick credstash over vault:

  • Nothing to run. If you want to run vault, you need to run the secret storage backend (consul or some other datastore), you need to run the vault server itself, etc. With credstash, there’s nothing to run. all of the data and key storage is handled by AWS services
  • lower cost for a small number of secrets. If you just need to store a small handful of secrets, you can easilly fit the credstash DDB table in the free tier, and pay ~$1 per month for KMS. So you get good secret management for about a buck a month.
  • Simple operations. Similar to “nothing to run”, you dont need to worry about getting a quorum of admins together to unseal your master keys, dont need to worry about monitoring, runbooks for when the secret service goes down, etc. It does expose you to risk of AWS outages, but if you’re running on AWS, you have that anyway

That said, if you want to do master key splitting, are not running on AWS, care about things like dynamic secret generation, have a trust boundary that’s smaller than an instance, or want to use something other than AWS creds for AuthN/AuthZ, then vault may be a better choice for you.

Narochno.Credstash

I created an ASP.NET Core configuration compatible reader for Credstash. It’s fairly simple and so far is working well.
Find it on NuGet and use it like so:

AWSCredentials creds = new StoredProfileAWSCredentials();
if (!env.EnvironmentName.MatchesNoCase("alpha"))
{
    creds = new InstanceProfileAWSCredentials();
}
builder.AddCredstash(new CredstashConfigurationOptions()
{
    EncryptionContext = new Dictionary<string, string>()
    {
        {"environment", env.EnvironmentName}
    },
    Region = RegionEndpoint.EUWest1,
    Credentials = creds
});

There’s probably more there than you need but I need it.

For AWS Creds, I use locally stored creds in my profile for development. I call this environment alpha so don’t sweat that. On an instance, I want to use IAM profile based permissions. Usage of this is on the credstash page.

KMS has a concept of EncryptionContexts that are basically just key/value pairs that need to match in order for the decryption of secrets to be successful. I use the environment name as an extra value to segment secrets by.

Conclusion

I can finally have something secure without having values hardcoded in a repo somewhere. KMS has an audit trail and Credstash uses an immutable value system to version secrets so that old values are still there.

It’s cheap, easy to setup and works with C# now. Everything I need.

DistributedCache extensions for Data Protection in ASP.NET Core

Repo: https://github.com/Visibilityltd/Visibility.AspNetCore.DataProtection.DistributedCache

This contains two simple classes:

  • DistributedCache DataProtection Provider
  • DistributedCache PropertiesDataFormat

DataProtection Provider

When having a distributed and stateless ASP.NET Core web server, you need to have your Data Protection keys saved to a location to be shared among your servers.

The default providers that the ASP.NET Core team provides are here

I was just going to use Redis but the implementation is hard-coded to Redis. I’m already using the DistributedCache Redis provider, so why not just link in to that? I don’t need to configure two different things now.

Usage

services.AddDataProtection()
.PersistKeysToDistributedCache();

Boom, now if you’re using IDistributedCache you now persist your generated DataProtection keys there.

DistributedCache PropertiesDataFormat

Another issue is that the state on the URL can used for Authentication can be large. Why not use cache?

This is inspired and mostly copied from: https://github.com/IdentityServer/IdentityServer4/issues/407

Usage

Useful for any Authentication middleware. You need to hook it into the AuthenticationOptions for your protocol like so:

I’m using CAS Authentication

var dataProtectionProvider = app.ApplicationServices.GetRequiredService();
var distributedCache = app.ApplicationServices.GetRequiredService();

var dataProtector = dataProtectionProvider.CreateProtector(
typeof(CasAuthenticationMiddleware).FullName,
typeof(string).FullName, schemeName,
"v1");

//TODO: think of a better way to create
var dataFormat = new DistributedPropertiesDataFormat(distributedCache, dataProtector);

...

app.UseCasAuthentication(x =>
{
x.StateDataFormat = dataFormat;
...
};

OpenId and OAuth have StateDataFormat in their options. I’m sure others do too.