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 — supplies the
IFieldEncryptorfor[Encrypted]columns, keyed from Vault. - Rotating DB credentials — 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. Both 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 — so 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);
});
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 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 the lease every
RefreshInterval. 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.
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.fetchandvault.credentials.lease(withdb.name,vault.database.role, and lease-duration tags). 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.