Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Access AWS Secrets Manager via .NET CORE

0.00/5 (No votes)
11 Mar 2019 1  
This article will help you to implement the functionality where you can store your sensitive data in the amazon Secrets Manager and access while bootstrapping the application.

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

  1. AWS Secrets Manager encrypts secrets at rest using encryption keys that you own and store in AWS Key Management Service (KMS).
  2. When you retrieve a secret, Secrets Manager decrypts the secret and transmits it securely over TLS to your local environment.
  3. 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

  1. The secrets changed or modified are version controlled.
  2. You can track which secret changed and when it is modifed.
  3. We can set a cloud watch logging for secrets whcih will give detail information of the versioning of the secrets.

Automatic Secrets Rotation

  1. With AWS Secrets Manager, you can rotate secrets on a schedule or on demand by using the Secrets Manager console, AWS SDK
  2. 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.
  3. 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

  1. AWSSD.Core by Amazon Webservice
  2. AWSSDK.SecretsManager by Amazon Seb Services
  3. Microsoft.AspNetCore.App
  4. Microsoft.NETCore.App
  5. 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.

/// This is a class which will give us all the information for extracting the data 
  public class SecretsDetail
    {
        public string Region { get; set; }       // The region you deployed your secrets 
        public string SecretName { get; set; }   // The secret name to access the secret 
        public string AccessKeyID { get; set; }  // access id created for the secret authorization
        public string SecretKey { get; set; }    // key for authorization
        public string VersionStage { get; set; } // Which version you want to access 
        public string ServiceURL { get; set; }   // the path of the endpoint
    }

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:

// Get the Secret name 
string secretName = secretsDetail.SecretName;
//Assign the region. 
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; // VersionStage defaults to AWSCURRENT if unspecified.
   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)
   {
       // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
       // Deal with the exception here, and/or rethrow at your discretion
       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

  1. The code is up and runing. You just need to pass the correct values and it will give the data.
  2. You can use the configured swagger to test the code.
  3. If you are facing any challanges or any errors, please mention in the comments.

History

  • 11th March, 2019: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here