Deneblab.StashLock.Client
0.1.23
dotnet add package Deneblab.StashLock.Client --version 0.1.23
NuGet\Install-Package Deneblab.StashLock.Client -Version 0.1.23
<PackageReference Include="Deneblab.StashLock.Client" Version="0.1.23" />
<PackageVersion Include="Deneblab.StashLock.Client" Version="0.1.23" />
<PackageReference Include="Deneblab.StashLock.Client" />
paket add Deneblab.StashLock.Client --version 0.1.23
#r "nuget: Deneblab.StashLock.Client, 0.1.23"
#:package Deneblab.StashLock.Client@0.1.23
#addin nuget:?package=Deneblab.StashLock.Client&version=0.1.23
#tool nuget:?package=Deneblab.StashLock.Client&version=0.1.23
Deneblab.StashLock.Client
Async-first secrets management client for StashLock vault with simplified 2-part API design.
Features
- 2-Part API Design: Clean separation between VaultKey configuration and SecretsStore opening
- Multiple Secret Sources: Remote encrypted vaults, local dev files, environment variables
- Async-First: Modern async/await patterns throughout
- Zero Dependencies: No external package dependencies
- Early Initialization: Load secrets before host builder setup
- Auto-Discovery: Automatic dev secrets file detection
Installation
dotnet add package Deneblab.StashLock.Client
Quick Start
Production: Remote Encrypted Vault
using Deneblab.StashLock.Client;
using Deneblab.StashLock.Client.Configuration;
// Set environment variable
// STASHLOCK_VAULT_KEY=mybox.prod.v1.secretpassword
// Get vault key from environment
var vaultKey = VaultKey.FromEnvironment();
// Open remote encrypted secrets store
var store = await SecretsStoreAsync.OpenRemoteAsync(vaultKey);
// Retrieve secrets
var dbPassword = await store.GetAsync("Database:Password");
var apiKey = await store.GetAsync("ExternalApi:Key");
Development: Plain JSON File
// Auto-discover dev secrets file
var store = await SecretsStoreAsync.TryOpenDevFileAsync();
if (store == null)
{
// Fallback: explicit file path
store = await SecretsStoreAsync.OpenFileAsync("./dev-secrets.json");
}
var secret = await store.GetAsync("MySecret");
Early Initialization Pattern
// Load secrets BEFORE host builder
var simpleEnv = SimpleEnv.Detect();
var vaultKey = VaultKey.FromEnvironment();
var store = await SecretsStoreAsync.OpenRemoteAsync(vaultKey);
// Now create host builder
var builder = WebApplication.CreateBuilder(args);
// Configure with loaded secrets
var dbConnection = await store.GetAsync("Database:ConnectionString");
builder.Services.AddDbContext<MyContext>(options =>
options.UseSqlServer(dbConnection));
API Overview
Part 1: VaultKey Configuration
Get vault keys from different sources:
// From environment variable STASHLOCK_VAULT_KEY
var vaultKey = VaultKey.FromEnvironment();
// From file
var vaultKey = VaultKey.FromFile("/path/to/vault.key");
// Direct string
var vaultKey = VaultKey.FromString("box.tag.version.password");
Part 2: SecretsStore Opening
Open secrets stores from different storage backends:
// Remote encrypted vault (production)
var store = await SecretsStoreAsync.OpenRemoteAsync(vaultKey);
// Plain JSON file (development)
var store = await SecretsStoreAsync.OpenFileAsync("./secrets.json");
// Auto-discover dev file
var store = await SecretsStoreAsync.TryOpenDevFileAsync();
Retrieve Secrets
// Get single secret
string value = await store.GetAsync("SecretKey");
// Get section as dictionary
var dbConfig = await store.GetSectionAsDictionaryAsync("Database");
// Returns: { "Host": "localhost", "Password": "secret", ... }
Environment Variables
| Variable | Purpose | Required |
|---|---|---|
STASHLOCK_VAULT_KEY |
Vault key or file path | Yes (for remote) |
STASHLOCK_API_URL |
Vault API base URL | No (has default) |
STASHLOCK_API_KEY |
API authentication key | No |
Vault Key Format
Vault keys use the format: box.tag.version.password
- box: Vault box name (e.g.,
myapp,production) - tag: Environment tag (e.g.,
prod,staging,dev) - version: Version identifier (e.g.,
v1,v2,2024-01) - password: Secret password for encryption
Example: myapp.prod.v1.secret123
Development Secrets File
Create a secrets.json file in your dev directory:
{
"Database:ConnectionString": "Server=localhost;Database=dev",
"Database:Password": "dev-password",
"ExternalApi:Key": "dev-api-key",
"ExternalApi:Url": "https://api-dev.example.com"
}
The client will auto-discover this file when running in Dev or Test mode.
Error Handling
try
{
var vaultKey = VaultKey.FromEnvironment();
var store = await SecretsStoreAsync.OpenRemoteAsync(vaultKey);
}
catch (VaultConfigurationException ex)
{
Console.WriteLine($"Configuration error: {ex.Message}");
}
catch (VaultNotFoundException ex)
{
Console.WriteLine($"Vault not found: {ex.VaultKey}");
}
catch (DecryptionException ex)
{
Console.WriteLine("Decryption failed - check password");
}
Migration from Old API
Old API (SecretsStoreFactoryAsync)
var factory = new SecretsStoreFactoryAsync();
var store = await factory.TryCreateFromAllAsync(
vaultKeyPlainText: "box.tag.version.password"
);
var secret = store.Get("MySecret"); // Sync
New API (2-Part Design)
var vaultKey = VaultKey.FromString("box.tag.version.password");
var store = await SecretsStoreAsync.OpenRemoteAsync(vaultKey);
var secret = await store.GetAsync("MySecret"); // Async
License
MIT License - see LICENSE file for details
Repository
https://github.com/deneblab/stashlock
Support
For issues and questions, please visit: https://github.com/deneblab/stashlock/issues
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 was computed. 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. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.