AWS Secret Storage

Working with any form of a secret in development such as usernames, connection strings, passwords, etc is always difficult. Simply finding a convenient and efficient way of storing them without putting them in source control can be a daunting task. While there are many ways of handling this such as dotNet secrets, Azure Key Vault, and Hashicorp Vault. I, however, decided to go with AWS’s secret manager.

Vault Comparison

VaultProsCons
.Net SecretsEasy and quick to setup
Built in with .NET Core
Not the best for production
Only works with .NET
Azure Key VaultHosted
Practically free
Difficult automated management
Rotation takes a bit of setup
VaultKey rotation
Very flexible
Difficult policy management
Difficult unseal management
Must be self-hosted
AWS Hosted
Works well with other AWS projects
Auto rotation
Still a fairly new service
$0.40 per secret

Keep in mind that this chart is fully personal opinion, I highly encourage everyone to do their research.

Due to AWS being the current host of choice and not wanted to host and administer a solution myself AWS was the winner.

Time to investigate

So my path working with AWS took me down the dark road of documentation and google searches. Being that it’s still fairly new, being released in April of 2018, there wasn’t really much code examples to look at. After spending a while trying to find something in .NET I was right where I started. Guess it’s time to dig into their API documentation.

One thing I do have to say about Amazon is that they do an amazing job with their documentation.

Working with Password Manager

One of the first things that we have to do is bring in the correct nuget package. The AWSSDK.SecretsManager nuget contains all the necessary parts to allow us to easily interact with the AWS Secret Manager.

Package-Install AWSSDK.SecretsManager

Once we have the appropriate nuget installed now it’s just a manager of authenticating with the appropriate credentials and interacting with the secret storage.

I will admit that I may be taking the lazy way out, but I’m sure that most individuals reading this care more about the actual code rather than me babbling on. As you can tell by the code below it is actually fairly easy to interface with the AWS Secret Manager.

Secret Manager Code

The example below is a implementation that you can quickly plug into your project and start working with.

internal class SecretManager
{
private readonly AWSCredentials _credentials;
private readonly AmazonSecretsManagerConfig _config;
private readonly AmazonSecretsManagerClient _client;
public SecretManager(AWSCredentials creds)
{
_credentials = creds;
_config = new AmazonSecretsManagerConfig { RegionEndpoint = RegionEndpoint.USEast2 };
_client = new AmazonSecretsManagerClient(_credentials,_config);
}
public IDictionary<string, string> GetSecrets(string secretName)
{
var secretjson = GetSecret(secretName);
return JsonConvert.DeserializeObject<Dictionary<string, string>>(secretjson);
}
public string UpdateSecret(string secretId, string secret, string description)
{
var request = new UpdateSecretRequest() {
SecretId = secretId,
SecretString = secret,
Description = description
};
var response = Task.Run(async () => await _client.UpdateSecretAsync(request)).Result;
return response?.VersionId;
}
public string UpdateSecret(string secretId, IDictionary<string,string> secret, string description)
{
var secretJson = JsonConvert.SerializeObject(secret);
return UpdateSecret(secretId, secretJson, description);
}
public string GetSecret(string secretName)
{
var request = new GetSecretValueRequest
{
SecretId = secretName
};
GetSecretValueResponse response = null;
response = Task.Run(async () => await _client.GetSecretValueAsync(request)).Result;
return response?.SecretString;
}
public string GetSecretId(string secretName)
{
var request = new GetSecretValueRequest
{
SecretId = secretName
};
GetSecretValueResponse response = null;
response = Task.Run(async () => await _client.GetSecretValueAsync(request)).Result;
return response?.VersionId;
}
public string StoreSecret(IDictionary<string, string> secret, string name, string description)
{
var secretjson = JsonConvert.SerializeObject(secret);
return StoreSecret(secretjson, name, description);
}
public string StoreSecret(string secret, string name, string description)
{
var request = new CreateSecretRequest(){Name = name, SecretString = secret, Description = description};
var response = Task.Run(async()=> await _client.CreateSecretAsync(request)).Result;
return response?.Name;
}
public DateTime? DeleteSecret(string secretId)
{
var request = new DeleteSecretRequest(){
SecretId = secretId, ForceDeleteWithoutRecovery = true
};
var response = Task.Run(async () => await _client.DeleteSecretAsync(request)).Result;
return response?.DeletionDate;
}
}
view raw AWSSecretManager.cs hosted with ❤ by GitHub

Usage

What good is an implementation without a good usage example?

var awsCredentials = new BasicAWSCredentials("someaccesskey", "somesecretkey");
var secretManager = new SecretManager(awsCredentials);
secretManager.StoreSecret("somesecretKey","mysecret","Just some test secret I wanted to try");


Categories: General, Programming

Tags: , , , ,

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: