![]() |
VOOZH | about |
dotnet add package Dosaic.Plugins.Persistence.VaultSharp --version 1.2.34
NuGet\Install-Package Dosaic.Plugins.Persistence.VaultSharp -Version 1.2.34
<PackageReference Include="Dosaic.Plugins.Persistence.VaultSharp" Version="1.2.34" />
<PackageVersion Include="Dosaic.Plugins.Persistence.VaultSharp" Version="1.2.34" />Directory.Packages.props
<PackageReference Include="Dosaic.Plugins.Persistence.VaultSharp" />Project file
paket add Dosaic.Plugins.Persistence.VaultSharp --version 1.2.34
#r "nuget: Dosaic.Plugins.Persistence.VaultSharp, 1.2.34"
#:package Dosaic.Plugins.Persistence.VaultSharp@1.2.34
#addin nuget:?package=Dosaic.Plugins.Persistence.VaultSharp&version=1.2.34Install as a Cake Addin
#tool nuget:?package=Dosaic.Plugins.Persistence.VaultSharp&version=1.2.34Install as a Cake Tool
Dosaic.Plugins.Persistence.VaultSharp is a Dosaic plugin that integrates HashiCorp Vault for secure secret storage. It provides a typed ISecretStorage<TBucket> abstraction backed either by a live Vault server (KV v2 + TOTP engines) or a local filesystem (useful for development and testing without a running Vault instance).
dotnet add package Dosaic.Plugins.Persistence.VaultSharp
or add as a package reference to your .csproj:
<PackageReference Include="Dosaic.Plugins.Persistence.VaultSharp" Version=""/>
The plugin is configured via the vault section in appsettings.yml / appsettings.json. The section is bound to VaultConfiguration using the [Configuration("vault")] attribute.
vault:
url: "http://localhost:8200"
token: "your-vault-token"
totpIssuer: "MyApp" # optional — default: Dosaic.Plugins.Persistence.VaultSharp
totpPeriodInSeconds: 30 # optional — default: 30
When useLocalFileSystem is true, secrets are stored as JSON files under localFileSystemPath. No Vault server is required. TOTP codes are generated locally using RFC 6238 (HMAC-SHA1).
vault:
useLocalFileSystem: true
localFileSystemPath: "./nodep-vault" # optional — default: ./nodep-vault
totpPeriodInSeconds: 30 # optional — default: 30
| Property | Type | Default | Description |
|---|---|---|---|
Url |
string |
"" |
Vault server base URL |
Token |
string |
"" |
Token used to authenticate with Vault |
TotpIssuer |
string |
"Dosaic.Plugins.Persistence.VaultSharp" |
Issuer label stored in the TOTP key |
TotpPeriodInSeconds |
int |
30 |
TOTP counter period in seconds |
UseLocalFileSystem |
bool |
false |
Store secrets on the local filesystem instead of Vault |
LocalFileSystemPath |
string |
"./nodep-vault" |
Root folder for local filesystem secrets |
The plugin uses two fixed Vault secret engine mount points:
| Engine | Mount |
|---|---|
| KV v2 | credentials |
| TOTP | totp |
Both engines must exist in Vault before the application starts.
When using PluginWebHostBuilder, the plugin is discovered automatically and VaultConfiguration is resolved from IConfiguration. You only need to register your secret storage buckets — typically in your own plugin or startup code:
services.AddSecretStorage<SecretBucket>();
services.AddVaultSharpPlugin(new VaultConfiguration
{
Url = "http://localhost:8200",
Token = "your-vault-token"
});
services.AddSecretStorage<SecretBucket>();
For local filesystem storage without a Vault server:
var config = new VaultConfiguration { UseLocalFileSystem = true, LocalFileSystemPath = "./nodep-vault" };
services.AddLocalFileSystemSecretStorage<SecretBucket>(config);
Buckets are plain enums that categorise secrets stored in Vault:
public enum SecretBucket
{
ApiKeys = 0,
DatabaseCredentials = 1,
ServiceAccounts = 2
}
public interface ISecretStorage<TSecretBucket> where TSecretBucket : struct, Enum
{
Task<Secret> GetSecretAsync(SecretId<TSecretBucket> secretId, CancellationToken cancellationToken = default);
Task<SecretId<TSecretBucket>> CreateSecretAsync(TSecretBucket bucket, Secret secret, CancellationToken cancellationToken = default);
Task<SecretId<TSecretBucket>> UpdateSecretAsync(SecretId<TSecretBucket> secretId, Secret secret, CancellationToken cancellationToken = default);
Task DeleteSecretAsync(SecretId<TSecretBucket> secretId, CancellationToken cancellationToken = default);
}
Inject it via the constructor:
public class MyService(ISecretStorage<SecretBucket> secrets)
{
// ...
}
SecretId<TBucket> is a read-only struct that identifies a stored secret. It encodes the bucket, type and a unique key into a URL-safe Sqid string via the Id property.
// Create a new random ID for a bucket + type combination
var id = SecretId<SecretBucket>.New(SecretBucket.DatabaseCredentials, SecretType.UsernamePassword);
// Encode / decode the opaque string representation
string opaqueId = id.Id;
var same = SecretId<SecretBucket>.FromSqid(opaqueId);
// Safe parsing (e.g. from user input)
if (SecretId<SecretBucket>.TryParse(input, out var parsed))
Console.WriteLine(parsed.Bucket); // DatabaseCredentials
All secret types derive from the abstract record Secret.
var secret = new UsernamePasswordSecret("admin", "s3cr3t");
var id = await secrets.CreateSecretAsync(SecretBucket.DatabaseCredentials, secret);
var retrieved = (UsernamePasswordSecret)await secrets.GetSecretAsync(id);
Console.WriteLine(retrieved.Username); // admin
Extends UsernamePasswordSecret with an additional ApiKey field.
var secret = new UsernamePasswordApiKeySecret("svc-account", "p@ssw0rd", "api-key-abc123");
var id = await secrets.CreateSecretAsync(SecretBucket.ApiKeys, secret);
var retrieved = (UsernamePasswordApiKeySecret)await secrets.GetSecretAsync(id);
Console.WriteLine(retrieved.ApiKey); // api-key-abc123
Stores a username, password, and a TOTP key. On create / update the Totp must contain a TotpKey with the Base32-encoded seed. On read the Totp is populated with a TotpCode containing the current OTP, its expiry time and remaining seconds.
// Write — provide the Base32 seed key
var secret = new UsernamePasswordTotpSecret(
"admin",
"p@ssw0rd",
new Totp(null, new TotpKey("JBSWY3DPEHPK3PXP"))
);
var id = await secrets.CreateSecretAsync(SecretBucket.ServiceAccounts, secret);
// Read — the live TOTP code is resolved automatically
var retrieved = (UsernamePasswordTotpSecret)await secrets.GetSecretAsync(id);
Console.WriteLine(retrieved.Totp.TotpCode.Code); // e.g. "482910"
Console.WriteLine(retrieved.Totp.TotpCode.RemainingSeconds); // seconds until code expires
Console.WriteLine(retrieved.Totp.TotpCode.ValidTillUtc); // UTC expiry timestamp
var secret = new CertificateSecret("-----BEGIN CERTIFICATE-----\n...", "optional-passphrase");
var id = await secrets.CreateSecretAsync(SecretBucket.ServiceAccounts, secret);
var retrieved = (CertificateSecret)await secrets.GetSecretAsync(id);
Console.WriteLine(retrieved.Certificate);
// Update in-place — the SecretId stays the same
var updated = new UsernamePasswordSecret("admin", "new-password");
await secrets.UpdateSecretAsync(id, updated);
// Delete
await secrets.DeleteSecretAsync(id);
TotpCodeGenerator is a static helper that generates TOTP codes locally (RFC 6238, HMAC-SHA1) without calling Vault. It is used internally by LocalFileSystemSecretStorage but is also available for direct use:
// Generate a 6-digit TOTP code from a Base32 key
string code = TotpCodeGenerator.Generate("JBSWY3DPEHPK3PXP", periodInSeconds: 30);
// Get remaining seconds and expiry for the current period
var (remaining, validUntil) = TotpCodeGenerator.GetPeriodInfo(periodInSeconds: 30);
ISecretStorage<T> registrationsUsernamePassword, UsernamePasswordApiKey, UsernamePasswordTotp, CertificateDosaic ActivitySource (via Dosaic.Hosting.Abstractions.Tracing / TrackStatusAsync) tagged with secret.bucket, secret.key, and secret.type; Ok/Error status is set automaticallyvault (Vault HTTP health endpoint) or vault-local-filesystem (directory write probe) registered automatically as a readiness checkPluginWebHostBuilderThe plugin registers a readiness health check automatically:
| Mode | Check name | Probe |
|---|---|---|
| Vault server | vault |
GET /v1/sys/health via IVaultClient |
| Local filesystem | vault-local-filesystem |
Creates and deletes a .health-probe file in LocalFileSystemPath |
Both checks report Unhealthy on failure, preventing the application from receiving traffic until the backend is reachable.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.34 | 97 | 6/10/2026 |
| 1.2.33 | 98 | 6/2/2026 |
| 1.2.31 | 99 | 5/28/2026 |
| 1.2.30 | 99 | 5/7/2026 |
| 1.2.29 | 96 | 5/5/2026 |
| 1.2.28 | 100 | 4/30/2026 |
| 1.2.27 | 109 | 4/29/2026 |
| 1.2.26 | 110 | 4/29/2026 |
| 1.2.25 | 108 | 4/27/2026 |
| 1.2.24 | 97 | 4/21/2026 |
| 1.2.23 | 104 | 4/14/2026 |
| 1.2.22 | 108 | 4/10/2026 |
| 1.2.21 | 110 | 4/10/2026 |
| 1.2.20 | 107 | 4/10/2026 |
| 1.2.19 | 108 | 4/9/2026 |
| 1.2.18 | 115 | 4/2/2026 |
| 1.2.17 | 106 | 4/1/2026 |
| 1.2.16 | 102 | 4/1/2026 |
| 1.2.15 | 115 | 3/31/2026 |
| 1.2.14 | 106 | 3/30/2026 |