Kralizek AWS Secrets Manager Configuration Extensions

repository·master·Indexed 42 days ago

https://github.com/kralizek/awssecretsmanagerconfigurationextensions

A configuration provider for .NET's Microsoft.Extensions.Configuration that loads secrets from AWS Secrets Manager. It supports three loading modes: Discovery (via ListSecrets), KnownSecrets (fixed list via BatchGetSecretValue), and KnownSecret (single secret via GetSecretValue). Features include JSON secret flattening, custom key generation, periodic reloading via ReloadInterval, and support for Amazon EKS IRSA and LocalStack.

Tokens
4.5K
Snippets
22
Records
27
Agent score
48%

What's inside Kralizek.Extensions.Configuration.AWSSecretsManager

  1. Choose an AWS Secrets Manager access mode

    master

    The library provides three distinct modes for loading secrets, depending on your access patterns and IAM permissions:

    1. Discovery Mode (AddSecretsManagerDiscovery): Automatically finds and fetches secrets. It calls ListSecrets followed by BatchGetSecretValue. Requires secretsmanager:ListSecrets and secretsmanager:BatchGetSecretValue IAM permissions.
    2. KnownSecrets Mode (AddSecretsManagerKnownSecrets): Fetches a specific list of secrets without searching for them. It calls BatchGetSecretValue. Requires secretsmanager:BatchGetSecretValue IAM permissions.
    3. KnownSecret Mode (AddSecretsManagerKnownSecret): Fetches exactly one specific secret. It calls GetSecretValue. Requires secretsmanager:GetSecretValue IAM permissions.
    using Microsoft.Extensions.Configuration;
    
    // Discovery: calls ListSecrets + BatchGetSecretValue
    var configuration = new ConfigurationBuilder()
        .AddSecretsManagerDiscovery()
        .Build();
    
    // KnownSecrets: calls BatchGetSecretValue for a fixed list — no ListSecrets
    var configuration = new ConfigurationBuilder()
        .AddSecretsManagerKnownSecrets(new[] { "my-app/db", "my-app/api-key" })
        .Build();
    
    // KnownSecret: calls GetSecretValue for exactly one secret — no ListSecrets, no Batch
    var configuration = new ConfigurationBuilder()
        .AddSecretsManagerKnownSecret("my-app/prod")
        .Build();
  2. Map and customize configuration keys

    master

    When secrets are loaded into the .NET configuration system, you can control how their names (keys) are transformed:

    • Built-in Mapping: Use SecretKeyMappingOptions to shape configuration keys using predefined logic.
    • Full Customization: Use a context-based KeyGenerator for complete control over how secret names are converted into configuration keys.
    • Duplicate Handling: Use ResolveDuplicateKeys to manage scenarios where multiple secrets might map to the same configuration key within a single provider call.
  3. Choose an AWS Secrets Manager loading mode

    master

    The library provides three primary modes for loading secrets, depending on your security requirements and how you want to discover secrets:

    1. Discovery Mode: Automatically discovers and loads secrets by calling the AWS ListSecrets API. Use this when you want the application to find all secrets matching certain criteria without hardcoding names.
    2. KnownSecrets Mode: Loads a fixed, predefined set of secrets using BatchGetSecretValue. This is more secure than Discovery mode because it does not require ListSecrets permissions.
    3. KnownSecret Mode: Loads exactly one specific secret using GetSecretValue. This provides the highest level of least-privilege security.

    API Modes Comparison

    ModeExtension methodAWS API callsMinimum IAM permissions
    DiscoveryAddSecretsManagerDiscoveryListSecrets + BatchGetSecretValuesecretsmanager:ListSecrets, secretsmanager:BatchGetSecretValue
    KnownSecretsAddSecretsManagerKnownSecretsBatchGetSecretValuesecretsmanager:BatchGetSecretValue
    KnownSecretAddSecretsManagerKnownSecretGetSecretValuesecretsmanager:GetSecretValue
  4. Restore verbatim secret name key mapping in 2.0

    master

    In 2.0.0, the default key generation behavior changed. By default, the SecretNamePathSeparator (which defaults to /) is replaced by the .NET configuration delimiter (:), and leading/trailing delimiters are trimmed.

    For example, a secret named /my-app/production/database now produces my-app:production:database instead of /my-app/production/database.

    To restore the previous behavior where secret names are used verbatim, set options.KeyMapping.SecretNamePathSeparator = null in your configuration lambda.

    builder.AddSecretsManagerKnownSecret(
        "my-app/production",
        options =>
        {
            options.KeyMapping.SecretNamePathSeparator = null;
        });
  5. Pass AWS credentials and client configuration in 2.0

    master

    The direct overloads for AWSCredentials and RegionEndpoint have been removed. To provide custom credentials or region settings, you should either pass an AWSOptions object or provide a pre-built IAmazonSecretsManager client.

    // Option 1: Using AWSOptions
    var awsOptions = builder.Configuration.GetAWSOptions();
    builder.AddSecretsManagerDiscovery(awsOptions, options => { ... });
    
    // Option 2: Using a pre-built client
    var config = new AmazonSecretsManagerConfig { ServiceURL = "http://localhost:4566" };
    var client = new AmazonSecretsManagerClient(credentials, config);
    builder.AddSecretsManagerDiscovery(client, options => { ... });
  6. Configure AWS client creation

    master

    You can control how the AWS SDK is initialized when using the library. You can either configure global AWS options or provide your own pre-configured client instance.

    • Configure AWS Options: Use AWSOptions to set the region, profile, or other SDK-specific settings.
    • Custom Client: Pass a caller-created IAmazonSecretsManager instance directly to the extension methods (e.g., AddSecretsManager*(client, ...)).
  7. Configure for LocalStack or Local Development

    master

    To use LocalStack, configure a custom IAmazonSecretsManager client with the LocalStack ServiceURL and pass it to the registration method. For local development, it is recommended to use KnownSecret or KnownSecrets with stable names rather than ARNs, as Discovery mode relies on ARNs that LocalStack may regenerate.

    var client = new AmazonSecretsManagerClient(new AmazonSecretsManagerConfig
    {
        ServiceURL = "http://localhost:4566",
        AuthenticationRegion = "us-east-1"
    });
    
    builder.Configuration.AddSecretsManagerKnownSecrets(
        secretIds: new[] { "my-secret" },
        secretsManager: client);
  8. Handle operational scenarios like logging and reloading

    master

    The library supports common production requirements:

    • Bootstrap Logging: Configure the library to enable logging while the configuration is still being built (useful for debugging startup issues).
    • Reloading Secrets: In ASP.NET Core applications, you can configure secrets to reload periodically, allowing the application to pick up updated values from AWS Secrets Manager without a restart.
  9. Migrate from 1.x to 2.0

    master

    Version 2.0 introduces breaking changes by replacing the single AddSecretsManager method with three specialized methods. You must update your call sites to use one of the following based on your requirement:

    1. Discovery Mode: Use AddSecretsManagerDiscovery() to load all secrets via ListSecrets (supports filtering).
    2. KnownSecrets Mode: Use AddSecretsManagerKnownSecrets(IEnumerable<string> secretIds) to load a specific list of secrets by ARN or name.
    3. KnownSecret Mode: Use AddSecretsManagerKnownSecret(string secretId) to load exactly one secret.

    Additionally, SecretsManagerConfigurationProviderOptions has been replaced by specific options classes for each mode: SecretsManagerDiscoveryOptions, SecretsManagerKnownSecretsOptions, and SecretsManagerKnownSecretOptions.

    // Discovery
    builder.AddSecretsManagerDiscovery();
    
    // KnownSecrets
    builder.AddSecretsManagerKnownSecrets(new[] { "my-secret-1", "my-secret-2" });
    
    // KnownSecret
    builder.AddSecretsManagerKnownSecret("my-app/prod");