Introduction
I was working on my project to store the secrets in the application.json. But when I saw AWS Secrets Manager, it looked secure and easy to implement in my system.
- This will help to store secrets like connection string paths at secure location.
- The values are always encrypted so it is not possible to access those without authorization
- You don't need to deploy application in case of values modified.
- Very easy to change values.
- Implementation is easy and very fast.
This article will help you to implement the basic prototype where you can access the secrets from Secrets Manager for your project. The code will explain to you in a step by step manner what and how we can achieve this.
This article uses .NET Core 2.2 to implement the functionality.
Secure Secrets Storage Management
- AWS Secrets Manager encrypts secrets at rest using encryption keys that you own and store in AWS Key Management Service (KMS).
- When you retrieve a secret, Secrets Manager decrypts the secret and transmits it securely over TLS to your local environment.
- By default, Secrets Manager does not write or cache the secret to persistent storage. And you can control access to the secret using fine-grained AWS Identity and Access Management (IAM) policies.
Audit and Monitor Secrets Usage
- The secrets changed or modified are version controlled.
- You can track which secret changed and when it is modifed.
- We can set a cloud watch logging for secrets whcih will give detail information of the versioning of the secrets.
Automatic Secrets Rotation
- With AWS Secrets Manager, you can rotate secrets on a schedule or on demand by using the Secrets Manager console, AWS SDK
- You can also extend this functionality to rotate other secrets by modifying sample Lambda functions. For example, you can rotate OAuth refresh tokens used to authorize applications or passwords used for MySQL databases hosted on premises.
- All this can be done with the Secrets Manager API provided by AWS.
Using the Code
I created a micro service which will just do one thing to retrieve the data from the AWS and give the secrets in string format. This service contains the complete implementation of requesting the data from Amazon Secrets manager and return in json format
Prerequisites of the Project
AWSSD.Core
by Amazon Webservice AWSSDK.SecretsManager
by Amazon Seb Services Microsoft.AspNetCore.App
Microsoft.NETCore.App
Swashbuckle.AspNetCore
(This is for swagger)
First for our Core API, we need input via Rest endpoint API. As we are creating this as an API, you can send the details and the secrets. In order to do that, let's create a Model where it can be used to do that.
public class SecretsDetail
{
public string Region { get; set; }
public string SecretName { get; set; }
public string AccessKeyID { get; set; }
public string SecretKey { get; set; }
public string VersionStage { get; set; }
public string ServiceURL { get; set; }
}
Once our model is ready, we can use that model in the controller where it will pass to the GetSecretManager
class. When we have all the details for AWS communication, we are good to build objects. In the below code block, we are using AmazaonSecretsManagerConfig
to build the endpoint info for the Secrets Manager.
The AmazonSecretManagerClient
will take parameters like AccessID SecretKey
and config
. If you are in the network or working on EC2 instance, then you don't need to provide the config. You can just pass the secretName
and access id and secretKey
. But outside the Amazon's Network, you need all the details which we are using below:
string secretName = secretsDetail.SecretName;
string region = secretsDetail.Region;
string secret = "";
MemoryStream memoryStream = new MemoryStream();
AmazonSecretsManagerConfig amazonSecretsManagerConfig = new AmazonSecretsManagerConfig();
amazonSecretsManagerConfig.ServiceURL = secretsDetail.ServiceURL;
IAmazonSecretsManager client = new AmazonSecretsManagerClient
(secretsDetail.AccessKeyID, secretsDetail.SecretKey, amazonSecretsManagerConfig);
GetSecretValueRequest request = new GetSecretValueRequest();
request.SecretId = secretName;
request.VersionStage = secretsDetail.VersionStage == null ?
"AWSCURRENT" : secretsDetail.VersionStage;
GetSecretValueResponse response = null;
This code block will build the client get the response back.
The AmazonSecretsManagerConfig
will get the endpoint information. This will help to get value from the SecretManagerClient
. The AccessKeyID
and SecretKey
will give you the details of the Response
.
The below code will extract the data from memory stream and give us the plain string
which we can convert in the Json format.
try
{
response = client.GetSecretValueAsync(request).Result;
} catch (DecryptionFailureException)
{
throw;
}
if (response.SecretString != null)
{
return secret = response.SecretString;
}
else
{
memoryStream = response.SecretBinary;
StreamReader reader = new StreamReader(memoryStream);
string decodedBinarySecret = System.Text.Encoding.UTF8.GetString
(Convert.FromBase64String(reader.ReadToEnd()));
return decodedBinarySecret;
}
Swagger Test
Result
The attached source code will give all the details about how it is built. Please feel free to write comments in case of any more explanation needed.
Notes
- The code is up and runing. You just need to pass the correct values and it will give the data.
- You can use the configured swagger to test the code.
- If you are facing any challanges or any errors, please mention in the comments.
History
- 11th March, 2019: Initial version