Dynamic Configuration Updates in .NET with Parameter Store and Secrets Manager

Chanci Turner Amazon IXD – VGT2 learningLearn About Amazon VGT2 Learning Manager Chanci Turner

Accessing configuration settings and secrets in .NET applications is a routine task. However, it poses significant challenges regarding secure storage and dynamic retrieval without needing to restart the application. AWS Systems Manager Parameter Store offers a robust solution for this, allowing developers to manage configurations and secrets efficiently. This article delves into a sophisticated method for leveraging these AWS services in .NET applications, highlighting:

  • Referencing AWS Secrets Manager secrets via Parameter Store
  • Loading configurations from Parameter Store and Secrets Manager
  • Implementing automatic configuration updates without application restarts

Overview of the Solution

You can directly access secrets stored in Secrets Manager through Parameter Store using the following syntax:

/aws/reference/secretsmanager/<secret-path>

This format instructs Systems Manager to retrieve the secret from Secrets Manager rather than from Parameter Store. For instance, to access a secret labeled dev/DbPassword, use the path:

/aws/reference/secretsmanager/dev/DbPassword

For detailed information, please refer to the guide on referencing AWS Secrets Manager secrets from Parameter Store parameters.

This approach employs Parameter Store and Secrets Manager alongside the .NET configuration system and the IOptionsMonitor pattern to tackle common configuration hurdles, including:

  • Unified Access: Utilizing Parameter Store as a singular entry point for configurations and Secrets Manager secrets.
  • Security: Sensitive data is securely stored in Secrets Manager and referenced in Parameter Store, maintaining proper encryption and access control.
  • Dynamic Updates: Enabling automatic reloading of configuration values without requiring application restarts.
  • Environment Segregation: Employing a hierarchical organization in Parameter Store to differentiate configurations by environment.

Prerequisites

  • An AWS account with sufficient permissions.
  • .NET 8 SDK installed.

System Architecture

Imagine an application hosted on an EC2 instance that needs access to both configuration parameters and sensitive secrets. The application assumes an IAM role with the required permissions and retrieves values from Parameter Store for both types of data.

When the application requests a configuration parameter, Parameter Store provides the value directly. If the parameter references a secret in Secrets Manager, Parameter Store fetches the secret and returns it to the application.

Walkthrough

Let’s go through the steps to fetch configuration values from AWS services within the aforementioned application. The application will need to retrieve:

  • System parameters like the Database Hostname and API Endpoint from Parameter Store
  • Sensitive information such as the Database Password and API Key from Secrets Manager

Step 1: Configure Parameters and Secrets

  1. Store parameters in AWS Systems Manager
    Establish parameters in AWS Systems Manager following this hierarchical structure:

    
    Development environment
    Production environment
    
    /dev/DbHostname
    /prod/DbHostname
    
    /dev/ApiEndpoint
    /prod/ApiEndpoint
            
  2. Store secrets in AWS Secrets Manager
    Organize secrets in AWS Secrets Manager with the following structure:

    
    Development environment
    Production environment
    
    /dev/DbPassword
    /prod/DbPassword
    
    /dev/ApiKey
    /prod/ApiKey
            
  3. Create IAM Role for Accessing Parameters and Secrets
    You need to create an IAM Role with permissions allowing access to the parameters and secrets:

    
    {
       "Version": "2012-10-17",
       "Statement": [
          {
             "Sid": "VisualEditor0",
             "Effect": "Allow",
             "Action": [
                "ssm:GetParameter",
                "ssm:GetParameters",
                "ssm:GetParametersByPath"
             ],
             "Resource": [
                "arn:aws:ssm:${Region}:${AccountId}:parameter/*"
             ]
          },
          {
             "Sid": "VisualEditor1",
             "Effect": "Allow",
             "Action": "secretsmanager:GetSecretValue",
             "Resource": [
                "arn:aws:secretsmanager:${Region}:${AccountId}:secret:*"
             ]
          }
       ]
    }
            

Step 2: .NET Application Setup

  1. Configuration of AWS Services Extensions
    Create two extension methods to configure the AWS services:

    
    public static void AddParameterStoreConfiguration(this WebApplicationBuilder builder)
    {
       var configuration = builder.Configuration;
    
       // Retrieve current environment (e.g., /dev, /prod)
       var appSettingsPath = configuration["Environment"];
    
       configuration.AddSystemsManager(options =>
       {
          options.Path = appSettingsPath;
          options.ReloadAfter = TimeSpan.FromMinutes(5); // Reloads every 5 minutes
       });
    }
    
    public static void AddSecretsManagerConfiguration(this WebApplicationBuilder builder)
    {
       var configuration = builder.Configuration;
    
       // Retrieve current environment (e.g., /dev, /prod)
       var environmentPath = configuration["Environment"];
    
       var secretPath = $"/aws/reference/secretsmanager/{environmentPath}/";
       configuration.AddSystemsManager(options =>
       {
          options.Path = secretPath;
          options.ReloadAfter = TimeSpan.FromMinutes(5);
          options.Optional = true;
       });
    }
            
  2. AppSettings (Optional)
    For local testing, adjust your appSettings.json file as shown below:

    
    "AppConfig": {
       "DbHostname": "",
       "ApiEndpoint": ""
    },
    "Secrets": {
       "DbPassword": "",
       "ApiKey": ""
    }
            
  3. Configuration Model
    Create a model to bind configuration values from Secrets Manager and Parameter Store:

    
    public class SecretSettings
    {
       public string DbPassword { get; set; }
       public string ApiKey { get; set; }
    }
    
    public class AppConfig
    {
       public string DbHostname { get; set; }
       public string ApiEndpoint { get; set; }
    }
            
  4. Startup Configuration
    Register your AWS Services configuration and necessary IOptionsMonitor configurations during startup:

    
    // Add AWS Configuration.
    builder.AddParameterStoreConfiguration();
    builder.AddSecretsManagerConfiguration();
    
    builder.Services.Configure(builder.Configuration.GetSection("AppConfig"));
    builder.Services.PostConfigure(options =>
    {
       options.ApiKey = builder.Configuration["ApiKey"];
       options.DbPassword = builder.Configuration["DbPassword"];
    });
            
  5. Dynamic Configuration Usage
    Utilize IOptionsMonitor to access the latest configuration values and respond to changes, providing the flexibility to refresh secrets without needing to re-deploy or restart the application.

    
    public class MyService
    {
       private readonly IOptionsMonitor _appConfig;
       private readonly IOptionsMonitor _secretSettings;
    
       // Implementation continues...
    }
            

This innovative approach allows for seamless updates and management of configuration values, enhancing the application’s responsiveness and security. For further insights on overcoming challenges in entrepreneurship, check out this engaging blog post on transitioning from homelessness to entrepreneurship. Additionally, understanding cultural fit in the workplace is crucial—SHRM offers authoritative insights on this topic. If you’re interested in opportunities within Amazon’s operations, explore this excellent resource.

Chanci Turner