HashiCorpVault.Configuration.AspNetCore
1.2.0
dotnet add package HashiCorpVault.Configuration.AspNetCore --version 1.2.0
NuGet\Install-Package HashiCorpVault.Configuration.AspNetCore -Version 1.2.0
<PackageReference Include="HashiCorpVault.Configuration.AspNetCore" Version="1.2.0" />
<PackageVersion Include="HashiCorpVault.Configuration.AspNetCore" Version="1.2.0" />
<PackageReference Include="HashiCorpVault.Configuration.AspNetCore" />
paket add HashiCorpVault.Configuration.AspNetCore --version 1.2.0
#r "nuget: HashiCorpVault.Configuration.AspNetCore, 1.2.0"
#:package HashiCorpVault.Configuration.AspNetCore@1.2.0
#addin nuget:?package=HashiCorpVault.Configuration.AspNetCore&version=1.2.0
#tool nuget:?package=HashiCorpVault.Configuration.AspNetCore&version=1.2.0
Optimove.Infrastructure.Vault
HashiCorp Vault configuration provider for ASP.NET Core with OIDC authentication via Azure AD. Supports interactive browser-based login for local development.
Features
- OIDC Authentication: Interactive browser-based authentication with Azure AD
- Seamless Integration: Works with ASP.NET Core's
IConfigurationsystem - Automatic Key Conversion: Converts Vault's
__notation to .NET's:hierarchy - Environment Restriction: Optional restriction to specific environments (e.g., Development only)
- Multi-Targeting: Supports .NET 6.0, 7.0, 8.0, 9.0, 10.0
Installation
dotnet add package Optimove.Infrastructure.Vault
Quick Start
1. Configure Vault Integration
using Optimove.Infrastructure.Vault;
public class Startup
{
public Startup(IWebHostEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddVaultSecrets(env.EnvironmentName, vault =>
{
vault.Address = "https://vault.optimove.net:8200";
vault.BasePath = "cloudcore-inhouse-dev/myapp";
vault.Role = "ibd";
vault.MountPoint = "mobius";
vault.CallbackPort = 8250;
vault.AllowedEnvironment = "Development"; // or null for all environments
})
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfiguration Configuration { get; }
}
2. Store Secrets in Vault
Secrets in Vault should use double underscore (__) notation for hierarchical keys:
# In Vault KV v2 secrets engine
vault kv put mobius/cloudcore-inhouse-dev/myapp \
AzureAd__ClientId="your-client-id" \
AzureAd__TenantId="your-tenant-id" \
ConnectionStrings__Database="Server=..." \
ApiKeys__External="your-api-key"
3. Access Configuration
The secrets are automatically converted to colon notation and accessible via IConfiguration:
public class MyController : ControllerBase
{
private readonly IConfiguration _configuration;
public MyController(IConfiguration configuration)
{
_configuration = configuration;
}
public IActionResult Get()
{
var clientId = _configuration["AzureAd:ClientId"];
var connectionString = _configuration["ConnectionStrings:Database"];
var apiKey = _configuration["ApiKeys:External"];
// ...
}
}
Configuration Options
| Property | Type | Default | Description |
|---|---|---|---|
Address |
string | required | Vault server address (e.g., "https://vault.optimove.net:8200") |
BasePath |
string | required | Base path for secrets in Vault (e.g., "cloudcore-inhouse-dev/myapp") |
Role |
string | required | OIDC role name configured in Vault (ask your DevOps team) |
MountPoint |
string | "secret" |
Mount point for the KV secrets engine |
CallbackPort |
int | 8250 |
Starting port for OIDC callback. If busy, the listener falls back through CallbackPort + 1 .. CallbackPort + 50 so concurrent OIDC flows don't collide. Vault's role must permit http://localhost:*/oidc/callback. |
AllowedEnvironment |
string? | "Development" |
Restrict to specific environment, or null for all environments |
How It Works
Authentication Flow
- Request Authorization URL: The library requests an authorization URL from Vault
- Open Browser: Automatically opens your default browser to Azure AD login page
- User Login: You log in with your Visual Studio / Azure credentials
- OAuth Callback: Azure AD redirects to
http://localhost:{port}/oidc/callback, where{port}is the first free port in[CallbackPort, CallbackPort + 50] - Local Listener: The library captures the authorization code
- Exchange for Token: Exchanges the code for a Vault token
- Load Secrets: Uses the token to read secrets from Vault
- Populate Configuration: Secrets are added to
IConfiguration
Key Conversion
Vault secrets use double underscore notation (__) for hierarchical keys, which are automatically converted to .NET's colon notation (:):
Vault Secret Key → .NET Configuration Key
──────────────────────────────────────────────────────
AzureAd__ClientId → AzureAd:ClientId
AzureAd__TenantId → AzureAd:TenantId
ConnectionStrings__Db → ConnectionStrings:Db
Quoted-Integer Values
Vault stores everything as a string. If a value is entered with literal surrounding double quotes around an integer (e.g. "123" or "-5"), the quotes are stripped so IConfiguration.GetValue<int> can bind the value. Non-integer quoted strings pass through unchanged.
Vault Stored Value → IConfiguration Value
──────────────────────────────────────────────
"123" → 123
"-5" → -5
"hello" → "hello" (unchanged)
123 → 123 (unchanged)
Environment Restrictions
For security, it's recommended to restrict Vault integration to Development environment:
vault.AllowedEnvironment = "Development"; // Only runs in Development
To allow all environments:
vault.AllowedEnvironment = null; // Runs in all environments
To restrict to a specific environment:
vault.AllowedEnvironment = "Staging"; // Only runs in Staging
Prerequisites
Vault Configuration
Your DevOps team must configure Vault with:
- OIDC Auth Method enabled at
/auth/oidc - OIDC Role configured with your Azure AD tenant
- Allowed Redirect URIs including
http://localhost:8250/oidc/callback(or your custom port) - KV v2 Secrets Engine mounted (e.g., at
/mobius)
Local Development
- .NET 6.0 or later
- Visual Studio with Azure account signed in (for OIDC authentication)
- Network access to Vault server
- Port 8250 available (or configure a different port)
Troubleshooting
Browser Doesn't Open
If the browser doesn't open automatically, check the logs for the authorization URL and navigate manually.
Port Already in Use
The library automatically tries CallbackPort + 1 .. CallbackPort + 50 if the starting port is busy, so running multiple apps concurrently works out of the box. If you exhaust all 51 ports (rare — usually means stale listeners), pick a different starting port:
vault.CallbackPort = 9000;
Vault's OIDC role must allow http://localhost:*/oidc/callback for the fallback range to be accepted.
Secrets Not Loading
- Check Vault address and network connectivity
- Verify the role name matches Vault configuration
- Ensure you're authenticated with the correct Azure AD account in Visual Studio
- Check Vault logs for authentication errors
- Verify the base path and mount point are correct
Token Expiry
Vault tokens expire after a configured period. If you see authentication errors after some time, restart your application to re-authenticate.
Security Considerations
- Development Only: By default, this library only runs in Development environment
- Interactive Authentication: Requires manual browser login, preventing automated credential leaks
- Token Storage: Tokens are stored in memory only and expire when the application stops
- No Credentials in Code: Never hard-code Vault credentials or tokens
License
MIT
Support
For issues or questions, please contact the Optimove DevOps team or create an issue in the repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
-
net6.0
- Azure.Identity (>= 1.13.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- VaultSharp (>= 1.17.5.1)
-
net7.0
- Azure.Identity (>= 1.13.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- VaultSharp (>= 1.17.5.1)
-
net8.0
- Azure.Identity (>= 1.13.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- VaultSharp (>= 1.17.5.1)
-
net9.0
- Azure.Identity (>= 1.13.1)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- VaultSharp (>= 1.17.5.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.