AWS

Since Amazon and Microsoft are competitors in cloud providers market, there are always nuances when you try to integrate pieces from different tech stacks. Let’s dive into how to read AWS SMM parameters in .Net Core 3 application.

Our application will read database settings from AWS Parameter store. For that you would need a POCO class:

1
2
3
4
5
6
public class DatabaseSettings
{
    public string UserName { get; set; }
    public string Password { get; set; }
    public int Port { get; set; }
}

To make this sample more production ready let’s assume that you have micro-service platform “sample-platform” and .Net Core service with the name “account-service”.

Setup

For production configuration, you would need some generic settings scripts/env-development.json:

1
2
3
4
5
{
  "DatabaseSettings--UserName": "SERVICE-SPECIFIC-USER-NAME",
  "DatabaseSettings--Password": "SERVICE-SPECIFIC-PASSWORD",
  "DatabaseSettings--Port": "2222"
}

And there are some account service-specific settings scripts/env-account-service-development.json:

1
2
3
4
{
  "DatabaseSettings--UserName": "web-api-user",
  "DatabaseSettings--Password": "web-api-user-password"
}

Lets store those settings to AWS with chamber. If you are don’t use chamber before please read Organize and Manage AWS Parameter Store for reference.

1
2
3
4
CHAMBER_KMS_KEY_ALIAS=aws/ssm
AWS_REGION=us-east-1
chamber import sample-platform/development env-development.json 
chamber import sample-platform/account-service/development env-account-service-development.json 

Ok, now you are ready to configure our .Net Core application.

Configure .Net Core 3 application

To access the AWS Parameter Store, you need to install Amazon.Extensions.Configuration.SystemsManager NuGet package to your project:

1
nuget install Amazon.Extensions.Configuration.SystemsManager -Version 1.2.0

Then in CreateHostBuilder you need to add ConfigureAppConfiguration to build configuration with the following steps:

Define some service environment variables:

1
2
3
var environmentName = (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development").ToLower();
var platformName = "sample-platform";
var serviceName = "account-service";

Load the appsettings and environment variables:

1
2
builder.AddJsonFile("appsettings.json");
builder.AddEnvironmentVariables();

Configure access to the AWS:

1
2
3
4
5
6
7
8
AWSOptions awsOptions = null;

if (Environment.GetEnvironmentVariable("AWS_ACCESS_KEY_ID") != null)
{
    awsOptions = new AWSOptions();
    awsOptions.Region = RegionEndpoint.USEast1;
    awsOptions.Credentials = new EnvironmentVariablesAWSCredentials();
}

AWS Parameters processing in .Net Core 3 application

AWS Parameter consist treats full parameter path as:

  • Path: /part-1/part-2/part-3/
  • Name: param-1

Name can’t contain the symbol ‘/'. In either case, it would be a part of the path. And name can’t contain symbol ‘:’ which is by default separator for .Net Core configuration. Hence, you need to replace ‘:’ with ‘–', that you already did for all imported parameters names.

Now you need to process them before loading to configuration. For that, you would need to implement IParameterProcessor from Amazon.Extensions.Configuration.SystemsManager NuGet package.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class AWSParameterProcessor : IParameterProcessor
{
    public virtual bool IncludeParameter(Parameter parameter, string path) => true;

    public virtual string GetKey(Parameter parameter, string path)
    {
        var res = parameter.Name.Substring(path.Length).TrimStart('/').Replace("--", ConfigurationPath.KeyDelimiter);
        return res;
    }

    public virtual string GetValue(Parameter parameter, string path) => parameter.Value;
}

Now you can return to the ConfigureAppConfiguration and create the parameter processor.

1
var awsParameterProcessor = new AWSParameterProcessor();

Load platform generic parameters:

1
2
3
4
5
6
builder.AddSystemsManager((source) =>
{
    source.Path = $"/{platformName}/{environmentName}";
    source.AwsOptions = awsOptions;
    source.ParameterProcessor = awsParameterProcessor;
});

Load service specific parameters:

1
2
3
4
5
6
builder.AddSystemsManager((source) =>
{
    source.Path = $"/{platformName}/{serviceName}/{environmentName}";
    source.AwsOptions = awsOptions;
    source.ParameterProcessor = awsParameterProcessor;
}); 

Complete solutution

The final sample repository can be found here: aws-parameter-store-sample.