Access Db connection parameter from AWS Secrets from lambda using dotnet core

2.1k views Asked by At

I am trying to develop a AWS Serverless API project using API gateway and lambda functions. I am using SAM model provided by AWS and Visual studio's AWS Serverless project template which includes cloudformation template too.

I do not want to store DB information in configuration file due to security reasons, I would like to know how can I use AWS Secrets Manager to get DB connection information in lambda function at run-time.

A code sample would be a great help as I could only find python examples using Boto3, .net core samples or explanation for serverless API and lmbda is not that much available on internet I guess. Any help or clue would be appreciated.

Thanks.

1

There are 1 answers

0
amsh On BEST ANSWER

[Approach 1]

You may use dynamic referencing in Cloudformation as follows:

  • Create DB credentials in the Secret Manager.
  • (Optional) Pass these credentials to the DB while creating it from Cloudformation.
  • Pass these credentials to the Lambda Function's environment variables in Cloudformation.
  • In the Lambda code simple read the referenced environment variables:
Console.WriteLine(Environment.GetEnvironmentVariable("DB_USERNAME"));

Example of dynamic referencing with DB:

{
    "MyRDSInstance": {
        "Type": "AWS::RDS::DBInstance",
        "Properties": {
            "DBName": "MyRDSInstance",
            "AllocatedStorage": "20",
            "DBInstanceClass": "db.t2.micro",
            "Engine": "mysql",
            "MasterUsername": "{{resolve:secretsmanager:MyRDSSecret:SecretString:username}}",
            "MasterUserPassword": "{{resolve:secretsmanager:MyRDSSecret:SecretString:password}}"
        }
    }
}

This approach is simple yet will need redeploys on credentials updates.

[Approach 2]

Alternatively, you may pass the Secret Manager variable names in the environment variables and then use those names to retrieve the values.

Add the nuget package for SecretsManager. Write class for querying:

public class SecretManager : ISecretManager
{
  public string Get(string secretName)
  {
    var config = new AmazonSecretsManagerConfig {RegionEndpoint = RegionEndpoint.EUWest1};
    var client = new AmazonSecretsManagerClient(config);

    var request = new GetSecretValueRequest
    {
      SecretId = secretName
    };

    GetSecretValueResponse response = null;
    try
    {
      response = Task.Run(async () => await client.GetSecretValueAsync(request)).Result;
    }
    catch (ResourceNotFoundException)
    {
      Console.WriteLine("The requested secret " + secretName + " was not found");
    }
    catch (InvalidRequestException e)
    {
      Console.WriteLine("The request was invalid due to: " + e.Message);
    }
    catch (InvalidParameterException e)
    {
      Console.WriteLine("The request had invalid params: " + e.Message);
    }

    return response?.SecretString;
  }
}

Use the class as follows:

var secretManager = new SecretManager();
var mongoDb = JsonConvert.DeserializeObject<MongoConnectionString>(secretManager.Get(Environment.GetEnvironmentVariable("SECRET_NAME")));
var database = new MongoClient(mongoDb.ConnectionString);

Please refer to this article for more details.