Use AWS Systems Manager Parameter Store as a .NET Configuration Provider
Tags: serverless, parameterstore, dotnet, tutorial
Published: 2022-05-17 14:50:11

Over the last few years, Microsoft has made many changes to improve your configuration management strategy in .NET. Long gone are the days where you have limited 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, custom configuration providers can be developed. Here, we'll focus on a configuration provider built by AWS that integrates with what my colleague calls the Swiss Army Knife for AWS configuration management -- 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 securely store things like passwords and secrets, but also database connection strings, UNC network paths, URLs and the like.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1hztbtjlzq8ok3ty53h.jpg)

Photo by [Patrick](https://unsplash.com/@pf91_photography?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/swiss-army-knife?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

## The Solution

In this tutorial, we’ll take a look at a .NET configuration provider developed by AWS that integrates with [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html). We'll develop a .NET API that we'll use to read configuration data from Parameter Store and we'll use the AWS CLI to seed that configuration data.

### Prerequisites

To complete this solution, you will need the .[NET CLI](https://docs.microsoft.com/en-us/dotnet/core/tools/) which is included in the [.NET 6 SDK](https://dotnet.microsoft.com/download/visual-studio-sdks). In addition, you will need to download the [AWS CLI](https://aws.amazon.com/cli/) and [configure your environment](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). You will also need to create an AWS IAM user with programmatic access with the appropriate permissions to create and read parameters in AWS Systems Manager Parameter Store.

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

### The Dev Environment

This tutorial was developed using Ubuntu 20.04, AWS CLI v2, .NET 6 SDK and Visual Studio Code 1.66.2. Some commands/constructs may very across systems.

### Create the Config Data with the AWS CLI

First, let’s use the AWS CLI to [create a few parameters in Parameter Store](https://docs.aws.amazon.com/cli/latest/reference/ssm/put-parameter.html).

```
$ 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

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 .NET 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);
                    });
                }
            );
```
The Program.cs file should now look like:

```
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();
```

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. This exercise is obviously for demonstration purposes only and not based on a true use case.

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

```
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 });

    }
}
```
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/
```
_*Note, here we have configured the app to run on port 5000.  Your app port may very._ 

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, which causes the third parameter to be omitted.

## Summary

We have completed the tutorial, 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.