HashiCorp Vault
Optional Socigy.OpenSource.DB.HashiCorp package: field encryption keyed from Vault and rotating PostgreSQL credentials from Vault's Database secrets engine, wired with one DI call each.
The optional Socigy.OpenSource.DB.HashiCorp package integrates Socigy with HashiCorp Vault for two things:
- Field encryption. It supplies the
IFieldEncryptorfor[Encrypted]columns, keyed from Vault. - Rotating DB credentials. It supplies an
IDbCredentialsProviderthat leases short-lived PostgreSQL credentials from Vault's Database secrets engine, which the generated connection factory consumes automatically.
dotnet add package Socigy.OpenSource.DB.HashiCorpSocigy.OpenSource.DB package and VaultSharp. The two Vault features are independent: register either or both.Field encryption
The data-encryption key is read from a Vault KV-v2 secret at startup and used for fast, local AES-256-CBC + HMAC encryption. Per-field crypto stays synchronous with no Vault round-trip per row. Store a Base64-encoded 32-byte key in Vault:
vault kv put secret/socigy/db-encryption-key key="$(openssl rand -base64 32)"Then register it:
builder.Services.AddSocigyVaultEncryption(o =>
{
o.Address = "https://vault.example.com:8200";
o.Token = builder.Configuration["Vault:Token"]; // or AppRoleId + AppRoleSecretId
o.KvMountPoint = "secret";
o.KeySecretPath = "socigy/db-encryption-key";
o.KeyField = "key";
});At host start the package reads the key and installs the ambient SocigyFieldEncryption encryptor, so every [Encrypted] column just works.
Rotating database credentials
Configure Vault's Database secrets engine with a role per database, then map each Socigy database name to its Vault role:
builder.Services.AddSocigyVaultCredentials(o =>
{
o.Address = "https://vault.example.com:8200";
o.AppRoleId = builder.Configuration["Vault:RoleId"];
o.AppRoleSecretId = builder.Configuration["Vault:SecretId"];
o.DatabaseMountPoint = "database";
o.BaseConnectionString = "Host=db.internal;Port=5432;Pooling=true"; // no user/pass
o.DatabaseRoles["AuthDb"] = "auth-db-role";
o.DatabaseRoles["UserDb"] = "user-db-role";
o.RefreshInterval = TimeSpan.FromMinutes(30); // fallback only; renewal normally tracks the lease TTL
});
builder.AddAuthDb(); // the generated factory picks up IDbCredentialsProvider automatically
builder.AddUserDb();How it fits together:
- At startup the package leases credentials for each configured database and composes a connection string (
BaseConnectionString+ the leasedUsername/Password), cached in memory. The string is built withDbConnectionStringBuilder, so leased passwords containing;,=, quotes or spaces are escaped correctly. - The generated connection factory calls the provider synchronously for the current connection string each time it opens a connection. See Connections & DI.
- A background timer renews credentials at ~2/3 of the actual lease TTL (
LeaseDurationSecondsreturned by Vault), so they are refreshed before they expire even when the role issues short leases.RefreshIntervalis only a fallback used when the lease TTL is unknown. When credentials rotate, new connections use the new string and Npgsql's old pool drains naturally.
Authentication
Both Add… calls accept either a token (Token) or AppRole (AppRoleId + AppRoleSecretId). AppRole is recommended for production workloads.
The Vault auth token is kept alive automatically by a background service: it renews the token (renew-self) before it expires, and when renewal can no longer extend it (max TTL) and AppRole credentials are configured, it re-logs-in for a fresh token. A static, non-renewable token cannot be kept alive — for long-running services use AppRole, a periodic token, or a renewable token. The library logs a clear error if it detects a token it cannot keep alive.
https:// Vault Address in production. If the address is plaintext http:// to a non-loopback host, the library logs a warning — tokens, keys, and leased credentials would otherwise travel unencrypted. Plain http:// to loopback is fine for local development.Diagnostics
All background actions are observable so admins can track what the library does:
- OpenTelemetry spans under the existing
Socigy.OpenSource.DBActivitySource:vault.encryption.key.fetch,vault.credentials.lease(withdb.name,vault.database.role, and lease-duration tags), andvault.token.renew/vault.token.reloginfor background auth-token upkeep. Subscribe withAddSource("Socigy.OpenSource.DB")(see Diagnostics & OpenTelemetry). ILoggermessages under categoriesSocigy.OpenSource.DB.Vault.EncryptionandSocigy.OpenSource.DB.Vault.Credentials: key load, each credential lease (database, role, user, lease seconds), renewal ticks, and failures. The connection factory also logs when it refreshes rotating credentials, andSocigyFieldEncryption.Configurelogs when an encryptor is installed.