How to use AWS Systems Manager Parameter Store as a .NET Configuration Provider

Advertisements

Many changes were made to configuration in .NET Core. Long gone are the days where you have few configuration options. In .NET, there are now out of the box options for INI,  JSON, XML, command-line arguments, in-memory stores, environment variables and key-per-file, et al. And, if those options weren’t enough, you can still develop your own provider.  On top of that, .NET now offers tiers of configuration, where one tier can override another.  This feature comes in very handy for supporting multiple environments.

The Solution

In this tutorial, we’ll take a look at a configuration provider developed by AWS that seamlessly integrates with AWS Systems Manager Parameter Store. AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data as well as secrets. With AWS Systems Manager Parameter Store, you can store things like secrets, but also database connection strings, UNC network paths and the like.

Remember, for any example solution from AWS with .NET, we focus on the code that exemplifies the problem we are trying to solve. We don’t include logging, input validation, exception handling, etc., and we embed the configuration data within classes instead of using environment variables, configuration files, key/value stores and the like. These items should not be skipped for proper solutions.

Prerequisites

To complete this solution, you will need the .NET CLI which is included in the .NET 6 SDK. In addition, you will need to download the AWS CLI and configure your environment. You will also need to create an AWS IAM user with programmatic access with the appropriate permissions to create parameters in AWS Systems Manager Parameter Store.

Warning: some AWS services may have fees associated with them.

There are now out of the box options for INI,  JSON, XML, command-line arguments, in-memory stores, environment variables and key-per-file…

Create the Config Data with the AWS CLI

First, let’s use the AWS CLI to create a few parameters in Parameter Store.

$ aws ssm put-parameter ––name=/testapp/test-key ––value=test-value ––type=String

$ aws ssm put-parameter ––name=/testapp/test-key2 ––value=test-value2 ––type=String

$ aws ssm put-parameter ––name=/testapp2/test-key3 ––value=test-value3 ––type=String

* Notice the difference between the first two parameters and the last one.

Develop the Test App

Get all the code on GitHub.

Now that we have some parameters in the Parameter store, let’s create an application that will pull the key/value data as configuration. For this, we will use a simple API to illustrate the process. Use the following command to create a stubbed out API:

$ dotnet new webapi ––name Api

With the API in place, we now need to pull in the AWS Nuget package that contains the configuration provider for AWS Systems Manager Parameter Store. Use the following command to add the package reference:

$ dotnet add Api/ package Amazon.Extensions.Configuration.SystemsManager

The next step is to modify the Program.cs file to wire up the new configuration provider. Let’s modify Program.cs by adding the following line just below the builder variable declaration:

builder.WebHost.ConfigureAppConfiguration(
c => {
c.AddSystemsManager(source =>{
source.Path = "/testapp";
source.ReloadAfter =
TimeSpan.FromMinutes(10);
});
}
);
view raw Program.cs hosted with ❤ by GitHub

The Program.cs file should now look like so:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureAppConfiguration(
c => {
c.AddSystemsManager(source =>{
source.Path = "/testapp";
source.ReloadAfter =
TimeSpan.FromMinutes(10);
});
}
);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
view raw Program.cs hosted with ❤ by GitHub

So far, we have created a simple API and brought in a package that allows us to use AWS Parameter Store as a configuration store. The next step is to create a controller so that we can view the configuration data that is fetched from AWS Parameter Store.

Let’s go into the Controllers folder and create a file named, ParametersController.cs. In this file we’ll create a method named, GetParameter and we’ll complete the method like so:

[HttpGet]
public IActionResult GetParameter(){
string parameter1 = _configuration["test-key"];
string parameter2 = _configuration["test-key2"];
string parameter3 = _configuration["test-key3"];
return Ok(new List<string> { parameter1, parameter2, parameter3 });
}

Here’s the ParameterController.cs file in its entirety:

using Microsoft.AspNetCore.Mvc;
namespace Api.Controllers;
[ApiController]
[Route("[controller]")]
public class ParameterController : ControllerBase
{
private IConfiguration _configuration;
public ParameterController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpGet]
public IActionResult GetParameter()
{
string parameter1 = _configuration["test-key"];
string parameter2 = _configuration["test-key2"];
string parameter3 = _configuration["test-key3"];
return Ok(new List<string> { parameter1, parameter2, parameter3 });
}
}

Notice, the IConfiguration based object that gets injected into the controller and then set to a corresponding field. This configuration objects gives us access to all the application’s configuration data.

With the controller complete, we should be ready to test our application. Let’s start the application with the following command:

$ dotnet run ––project Api/

Now that the application is running, let’s navigate to, http://localhost:5000/Parameter in your favorite browser. You should see a response that looks something like this:

[
    "test-value",
    "test-value2",
    null
]

Notice that test-value3 is not present. This is because when we set up our configuration provider in Program.cs, we set the path to “/testapp”. By setting the path, Parameter Store is going to give us all parameters that are prefixed with the /testapp path. When creating the third parameter, we used a path of /testapp2.

c.AddSystemsManager(source =>{
source.Path = "/testapp";
source.ReloadAfter = TimeSpan.FromMinutes(10);
});
view raw Program.cs hosted with ❤ by GitHub

We have completed the solution, learning to create data in AWS Systems Manager Parameter Store via the AWS CLI as well as creating an application in AWS.NET to pull the configuration data from AWS Systems Manager Parameter Store.

Get all the code on GitHub.

Want to know more about the tech in this tutorial? Checkout these resources:

.NET CLI

AWS CLI 

Configuring the AWS CLI

ASP.NET Web APIs

AWS Systems Manager Parameter Store

Create parameters in Parameter Store via the AWS CLI

Advertisements
%d bloggers like this: