Skip to content

Configure HashiCorp Vault, Azure Key Vault, AWS, GCP in a .NET app

All four expose the same three abstractions (ITransitEncryptionService, ISecretStore, IDatabaseCredentialProvider). Pick based on where the rest of your infrastructure lives:

HashiCorpAzure Key VaultAWSGCP
PackageGranit.Vault.HashiCorpGranit.Vault.AzureGranit.Vault.AwsGranit.Vault.GoogleCloud
Encryption backendTransit engineRSA-OAEP-256KMSCloud KMS (AES-256-GCM)
Ciphertext carries versionvault:v{N}:…❌ opaque❌ opaque❌ opaque
Server-side rewrap/transit/rewrap❌ (decrypt+encrypt)❌ (decrypt+encrypt)❌ (decrypt+encrypt)
Secrets engine for ISecretStoreKV v2SecretSecrets ManagerSecret Manager
Native binary payloadvia __binary conventionvia application/octet-streamSecretBinaryByteString
Dynamic DB creds✅ lease-awarevia secret pollingvia secret pollingvia secret polling
Auth for productionKubernetes JWTManaged IdentityIAM roleWorkload Identity

All four modules auto-disable in Development — you don’t need a running vault locally.

[DependsOn(typeof(GranitVaultHashiCorpModule))]
public class AppModule : GranitModule { }
{
"Vault": {
"Address": "https://vault.example.com",
"AuthMethod": "Kubernetes",
"KubernetesRole": "my-backend"
}
}

Uses the Kubernetes service account token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token.

{
"Vault": {
"Address": "https://vault.example.com",
"AuthMethod": "Kubernetes",
"KubernetesRole": "my-backend",
"KubernetesTokenPath": "/var/run/secrets/kubernetes.io/serviceaccount/token",
"DatabaseMountPoint": "database",
"DatabaseRoleName": "readwrite",
"TransitMountPoint": "transit",
"KvMountPoint": "secret",
"LeaseRenewalThreshold": 0.75,
"SecretStore": {
"CacheSeconds": 0,
"HealthCheckSecretName": "healthcheck/probe"
}
}
}
PropertyDefaultDescription
AddressVault server URL
AuthMethod"Kubernetes""Kubernetes" or "Token"
KubernetesRole"my-backend"Vault Kubernetes auth role
DatabaseMountPoint"database"Database secrets engine mount
DatabaseRoleName"readwrite"Database role for dynamic credentials
TransitMountPoint"transit"Transit secrets engine mount
KvMountPoint"secret"KV v2 secrets engine mount (used by ISecretStore)
LeaseRenewalThreshold0.75Renew lease at this fraction of TTL
builder.Services.AddHealthChecks()
.AddGranitVaultHashiCorpHealthCheck() // Vault sys/health probe
.AddGranitSecretStoreHealthCheck(); // ISecretStore canary

The first check verifies Vault connectivity and authentication. The second (shared across all four providers) reads Vault:SecretStore:HealthCheckSecretName through ISecretStore — see Secret retrieval → Liveness probe.

[DependsOn(typeof(GranitVaultAzureModule))]
public class AppModule : GranitModule { }

Uses DefaultAzureCredential — Managed Identity in AKS, az login locally. No credentials in configuration.

{
"Vault": {
"Azure": {
"VaultUri": "https://my-vault.vault.azure.net/"
}
}
}
{
"Vault": {
"Azure": {
"VaultUri": "https://my-vault.vault.azure.net/",
"EncryptionKeyName": "string-encryption",
"EncryptionAlgorithm": "RSA-OAEP-256",
"DatabaseSecretName": "db-credentials",
"RotationCheckIntervalMinutes": 5,
"TimeoutSeconds": 30
},
"SecretStore": {
"CacheSeconds": 0,
"HealthCheckSecretName": "healthcheck/probe"
}
}
}
PropertyDefaultDescription
Vault:Azure:VaultUriAzure Key Vault URI (required)
Vault:Azure:EncryptionKeyName"string-encryption"Key name for encrypt/decrypt
Vault:Azure:EncryptionAlgorithm"RSA-OAEP-256""RSA-OAEP-256" or "RSA-OAEP"
Vault:Azure:DatabaseSecretNamenullSecret name for DB credentials (omit to disable)
Vault:Azure:RotationCheckIntervalMinutes5DB secret rotation polling interval
Vault:Azure:TimeoutSeconds30Azure SDK operation timeout
builder.Services.AddHealthChecks()
.AddGranitAzureKeyVaultHealthCheck() // GetKey probe on EncryptionKeyName
.AddGranitSecretStoreHealthCheck(); // ISecretStore canary
[DependsOn(typeof(GranitVaultAwsModule))]
public class AppModule : GranitModule { }

When AccessKeyId / SecretAccessKey are null (recommended), the AWS SDK uses its default credential chain — IAM role on ECS/EKS, environment variables, EC2 instance profile, or shared credentials file (local dev only).

{
"Vault": {
"Aws": {
"Region": "eu-west-1",
"KmsKeyId": "alias/granit-encryption"
}
}
}

Set AccessKeyId / SecretAccessKey explicitly only for local dev against LocalStack or when the credential chain can’t find usable credentials.

{
"Vault": {
"Aws": {
"Region": "eu-west-1",
"KmsKeyId": "alias/granit-encryption",
"DatabaseSecretArn": "arn:aws:secretsmanager:eu-west-1:123…:secret:db-credentials",
"RotationCheckIntervalMinutes": 5,
"AccessKeyId": null,
"SecretAccessKey": null,
"TimeoutSeconds": 30
},
"SecretStore": {
"CacheSeconds": 0,
"HealthCheckSecretName": "healthcheck/probe"
}
}
}
PropertyDefaultDescription
Vault:Aws:RegionAWS region endpoint (required)
Vault:Aws:KmsKeyIdKMS key ARN or alias for transit encryption (required)
Vault:Aws:DatabaseSecretArnnullSecrets Manager ARN for DB credentials (omit to disable)
Vault:Aws:RotationCheckIntervalMinutes5DB secret rotation polling interval
Vault:Aws:AccessKeyIdnullOverride; defaults to SDK credential chain
Vault:Aws:SecretAccessKeynullOverride; defaults to SDK credential chain
Vault:Aws:TimeoutSeconds30API call timeout
builder.Services.AddHealthChecks()
.AddGranitKmsHealthCheck() // DescribeKey on KmsKeyId
.AddGranitSecretStoreHealthCheck(); // ISecretStore canary
[DependsOn(typeof(GranitVaultGoogleCloudModule))]
public class AppModule : GranitModule { }

Uses Application Default Credentials — Workload Identity in GKE, gcloud auth application-default login locally. Override only for a service account JSON file.

{
"Vault": {
"GoogleCloud": {
"ProjectId": "my-project",
"Location": "europe-west1",
"KeyRing": "my-keyring",
"CryptoKey": "string-encryption"
}
}
}
{
"Vault": {
"GoogleCloud": {
"ProjectId": "my-project",
"Location": "europe-west1",
"KeyRing": "my-keyring",
"CryptoKey": "string-encryption",
"DatabaseSecretName": "db-credentials",
"RotationCheckIntervalMinutes": 5,
"CredentialFilePath": null,
"TimeoutSeconds": 30
},
"SecretStore": {
"CacheSeconds": 0,
"HealthCheckSecretName": "healthcheck/probe"
}
}
}
PropertyDefaultDescription
Vault:GoogleCloud:ProjectIdGCP project id (required)
Vault:GoogleCloud:LocationCloud KMS location, e.g. "europe-west1" (required)
Vault:GoogleCloud:KeyRingCloud KMS key ring name (required)
Vault:GoogleCloud:CryptoKeyCloud KMS crypto key for transit encryption (required)
Vault:GoogleCloud:DatabaseSecretNamenullSecret Manager secret name for DB credentials (omit to disable)
Vault:GoogleCloud:RotationCheckIntervalMinutes5DB secret rotation polling interval
Vault:GoogleCloud:CredentialFilePathnullService account key JSON; ADC when null
Vault:GoogleCloud:TimeoutSeconds30API call timeout
builder.Services.AddHealthChecks()
.AddGranitCloudKmsHealthCheck() // Verifies KMS key accessibility
.AddGranitSecretStoreHealthCheck(); // ISecretStore canary
CategoryTypesPackage
ModulesGranitEncryptionModule, GranitVaultHashiCorpModule, GranitVaultAzureModule, GranitVaultAwsModule, GranitVaultGoogleCloudModule
EncryptionIStringEncryptionService, IStringEncryptionProvider, AesStringEncryptionProviderGranit.Encryption
TransitITransitEncryptionService, ReEncryptionOptions, RetiredKeyVersionExceptionGranit.Vault
SecretsISecretStore, SecretRequest, SecretVersion, SecretDescriptor, SecretMetadata, SecretStoreOptions, SecretVaultException + subclassesGranit.Vault
CredentialsIDatabaseCredentialProviderGranit.Vault
ObservabilityVaultMetrics, SecretStoreActivityTagsGranit.Vault
Health checksSecretStoreHealthCheck, VaultHealthCheck, AzureKeyVaultHealthCheck, KmsHealthCheck, CloudKmsHealthCheckper-provider
ExtensionsAddGranitEncryption(), AddGranitVaultHashiCorp(), AddGranitVaultAzure(), AddGranitVaultAws(), AddGranitVaultGoogleCloud(), AddGranitSecretStore<T>(), AddGranitSecretStoreHealthCheck()