GM.Secrets.AzureKeyVault 2.0.0

dotnet add package GM.Secrets.AzureKeyVault --version 2.0.0
                    
NuGet\Install-Package GM.Secrets.AzureKeyVault -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="GM.Secrets.AzureKeyVault" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GM.Secrets.AzureKeyVault" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="GM.Secrets.AzureKeyVault" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add GM.Secrets.AzureKeyVault --version 2.0.0
                    
#r "nuget: GM.Secrets.AzureKeyVault, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package GM.Secrets.AzureKeyVault@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=GM.Secrets.AzureKeyVault&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=GM.Secrets.AzureKeyVault&version=2.0.0
                    
Install as a Cake Tool

GM.Secrets

Layers an app's secrets into IConfiguration, so code reads them like any other setting — IConfiguration["ApiKey"], IOptions<T> / IOptionsMonitor<T>, connection strings — without knowing whether a value came from appsettings, a local file, or a secret store. Which store (Doppler, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault) is picked per environment with one environment variable, SECRETS_PROVIDER.

  • GM.Secrets — builder.AddGMSecrets(...): the local appsecrets.json layer, store selection, and loading the store into configuration (with optional reload for rotation).
  • GM.Secrets.Doppler — a Doppler config, via its REST API and a service token.
  • GM.Secrets.AwsSecretsManager — AWS Secrets Manager, via AWSSDK.SecretsManager.
  • GM.Secrets.AzureKeyVault — Azure Key Vault, via Azure.Security.KeyVault.Secrets + DefaultAzureCredential.
  • GM.Secrets.Vault — HashiCorp Vault KV v2, via its HTTP API (token or AppRole).

Install

dotnet add package GM.Secrets
dotnet add package GM.Secrets.Doppler            # and/or the store(s) you deploy with
dotnet add package GM.Secrets.AwsSecretsManager
dotnet add package GM.Secrets.AzureKeyVault
dotnet add package GM.Secrets.Vault

Register

builder.AddGMSecrets();

That's all the code. The store is chosen by environment variables: SECRETS_PROVIDER=AzureKeyVault loads the referenced GM.Secrets.AzureKeyVault package and configures it from its own variables (AZURE_KEYVAULT_URI, ...). Only that package is loaded; the others are never touched. Reference the store packages the app can be deployed with — an app that only runs on Azure needs just GM.Secrets.AzureKeyVault.

To set a store's options in code instead, register it; that registration wins over the package's defaults:

builder.AddGMSecrets(secrets => secrets.AddVault(o => o.MountPoint = "kv"));

Then read secrets the usual way:

var apiKey = builder.Configuration["Payments:ApiKey"];
builder.Services.Configure<DbCredentials>(builder.Configuration.GetSection("DbCredentials"));

public sealed class PaymentClient(IOptionsMonitor<DbCredentials> db) { /* db.CurrentValue */ }

Never log a secret value; error messages from the stores carry names and status codes only.

Configuration layers

Lowest to highest precedence:

appsettings.json → appsettings.{Environment}.json
  → appsecrets.json → appsecrets.{Environment}.json   (AddGMSecrets — any environment, when present)
  → the store SECRETS_PROVIDER selects                 (AddGMSecrets — none when unset)
  → environment variables → command line
  • appsecrets.json holds local secret values. Keep it gitignored; the package also keeps appsecrets*.json out of dotnet publish. A JSON object there ("Db": { "User": "..." }) is a section like any other. SECRETS_FILE points the layer at a file elsewhere; turn it off with secrets.AppSecretsFile.Enabled = false.
  • The store overrides the files: a key it has wins, a key it lacks falls back to appsecrets and appsettings. It is loaded at startup (a failure stops startup) and, with SECRETS_RELOAD_INTERVAL, re-fetched on that interval — IConfiguration and IOptionsMonitor<T> see the new values without a restart (IOptions<T> doesn't; it is read once). A failed refresh keeps the last values. Stores that aren't selected are never created.

Environment variables

The settings that decide where secrets come from are read from process environment variables only — never appsettings, appsecrets.json, the command line or a store — so a store's credentials never sit next to the secrets they unlock.

Variable Default Does
SECRETS_PROVIDER none the store to load: Doppler, AwsSecretsManager, AzureKeyVault or Vault; unset loads none
SECRETS_RELOAD_INTERVAL off re-fetch the store this often, e.g. 00:05:00
SECRETS_FILE appsecrets.json in the content root the local secrets file, anywhere: absolute or relative to the content root, e.g. D:\secrets\myapp.json (must exist; myapp.{Environment}.json beside it is loaded too)

A SECRETS_PROVIDER whose package isn't referenced, a malformed value, or a store missing its settings fails at startup with the variable's name (never its value).

Security

What the library does:

  • Credentials only from the environment. SECRETS_PROVIDER and every store's address and credentials are read from process environment variables — never from appsettings, appsecrets.json, the command line or a store — so the place secrets come from is never set by those secrets.
  • No secret values in errors. Failures name the variable, the path or the HTTP status; a malformed variable's value is left out of its error, and a store's token never appears in one.
  • Tokens only over TLS. Vault and Doppler refuse a plain http address unless it is on this machine (a dev server), since their tokens travel in request headers. Vault mounts and paths are checked so a value can't step to another endpoint (.., ?, #).
  • Only the selected store is loaded. SECRETS_PROVIDER must be a plain name; only GM.Secrets.{name} is loaded, and unselected stores are never created.
  • Local secrets stay local. appsecrets*.json in the project is excluded from dotnet publish.

What you do:

  • Keep credentials (DOPPLER_TOKEN, VAULT_TOKEN, AWS_SECRET_ACCESS_KEY, AZURE_CLIENT_SECRET) in environment variables — user variables locally, the platform's secret settings when deployed — and out of committed files such as launchSettings.json. In Azure and AWS prefer a managed identity / IAM role, which needs no credential at all.
  • Gitignore appsecrets*.json, and never put a real secret in appsettings*.json.
  • Give each app's identity read access to its own secrets only (Key Vault Secrets User, secretsmanager:GetSecretValue on one ARN, a Vault policy on one path, a Doppler service token per config). Rotate anything that was committed or shared.
  • Never log configuration values; secrets are ordinary configuration once loaded.

Secret stores

Store SECRETS_PROVIDER Variables Secret names → configuration keys
Doppler Doppler DOPPLER_TOKEN, optional DOPPLER_PROJECT, DOPPLER_CONFIG (with a personal or CLI token it defaults from the app environment: Development → dev, Staging → stg, Production → prd), DOPPLER_API_URL SAMPLE__USER → SAMPLE:USER (keys are case-insensitive)
AWS Secrets Manager AwsSecretsManager AWS_SECRETS_MANAGER_SECRET_IDS (comma-separated), AWS_REGION, AWS_ENDPOINT_URL_SECRETS_MANAGER (emulators); credentials from the AWS default chain (IAM role, AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY, AWS_PROFILE) a JSON secret is flattened (__ and nesting → sections); a plain secret is keyed by its name (/ → :)
Azure Key Vault AzureKeyVault AZURE_KEYVAULT_URI, optional AZURE_KEYVAULT_PREFIX; credentials from DefaultAzureCredential (managed identity, az login, Visual Studio, or an app registration: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET) Sample--User → Sample:User; enabled, unexpired secrets only
HashiCorp Vault Vault VAULT_ADDR (https; plain http only for this machine); VAULT_TOKEN, or VAULT_ROLE_ID + VAULT_SECRET_ID (AppRole), else the vault login token in ~/.vault-token; VAULT_PATHS (comma-separated), VAULT_MOUNT (secret), VAULT_NAMESPACE KV v2 data flattened (nesting and __ → sections)

Lists are comma-separated: VAULT_PATHS=myapp/shared,myapp/production (later ones win). Every store's options can also be set in code: .AddVault(o => ...). On a developer machine the stores' own logins work as-is: vault login, aws sso login / AWS_PROFILE, az login, a Doppler token — the samples repo shows each.

Add a store

Implement ISecretsStore — one method, LoadAllAsync, returning every secret keyed in configuration form (ConfigurationSecrets.FlattenJson / NormalizeKey help). To make SECRETS_PROVIDER=MyStore find it, ship it in a package named GM.Secrets.MyStore that declares a factory reading its settings from environment variables:

[assembly: SecretsStore("MyStore", typeof(MyStoreFactory))]

internal sealed class MyStoreFactory : ISecretsStoreFactory
{
    public ISecretsStore Create(SecretsVariables variables, IHostEnvironment environment) =>
        new MyStore(new MyStoreOptions { Url = variables.GetUri("MYSTORE_URL") });
}

A store in any other assembly can be registered in code instead: builder.AddGMSecrets(s => s.AddProvider("MyStore", variables => new MyStore(...))).

Samples

GM.Secrets.Samples — a runnable API that reads its secrets through configuration, locally and from each store.

License

MIT — see LICENSE.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on GM.Secrets.AzureKeyVault:

Package Downloads
GM.API

An opinionated ASP.NET Core Web API starter for .NET. A single AddGMAPI/UseGMAPI pair wires up controllers, CORS, API versioning, Swagger docs, FluentValidation, Serilog, and middlewares for exception handling, request logging (with sensitive-data masking) and request localization. Loads secrets into configuration from a local appsecrets.json or the store the SECRETS_PROVIDER environment variable names (Doppler, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault). Bundles the GM.API.* companion packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 491 10/30/2026