Vault providers — HashiCorp, Azure, AWS, GCP
Which provider should I pick?
Section titled “Which provider should I pick?”All four expose the same three abstractions (ITransitEncryptionService,
ISecretStore, IDatabaseCredentialProvider). Pick based on where the rest of
your infrastructure lives:
| | HashiCorp | Azure Key Vault | AWS | GCP |
| - | :-: | :-: | :-: | :-: |
| Package | Granit.Vault.HashiCorp | Granit.Vault.Azure | Granit.Vault.Aws | Granit.Vault.GoogleCloud |
| Encryption backend | Transit engine | RSA-OAEP-256 | KMS | Cloud KMS (AES-256-GCM) |
| Native MAC (ITransitMacService) | Transit HMAC | Managed HSM HS256 (premium) | KMS HMAC_256 | Cloud KMS HMAC_SHA256 |
| MAC key versioning | min_decryption_version | enabled-version | Current/Previous alias | enabled-version |
| Ciphertext carries version | ✅ vault:v{N}:… | ❌ opaque | ❌ opaque | ❌ opaque |
| Server-side rewrap | ✅ /transit/rewrap | ❌ (decrypt+encrypt) | ❌ (decrypt+encrypt) | ❌ (decrypt+encrypt) |
| Secrets engine for ISecretStore | KV v2 | Secret | Secrets Manager | Secret Manager |
| Native binary payload | via __binary convention | via application/octet-stream | ✅ SecretBinary | ✅ ByteString |
| Dynamic DB creds | ✅ lease-aware | via secret polling | via secret polling | via secret polling |
| Auth for production | Kubernetes JWT | Managed Identity | IAM role | Workload Identity |
All four modules auto-disable in Development — you don’t need a running vault
locally.
HashiCorp Vault
Section titled “HashiCorp Vault”[DependsOn(typeof(GranitVaultHashiCorpModule))]public class AppModule : GranitModule { }How do I authenticate?
Section titled “How do I authenticate?”{ "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": "http://localhost:8200", "AuthMethod": "Token", "Token": "hvs.dev-only-token" }}Token auth is intended for local Vault dev servers only. Never commit a token.
Full configuration
Section titled “Full configuration”{ "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" } }}| Property | Default | Description |
| -------- | ------- | ----------- |
| Address | — | Vault 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) |
| LeaseRenewalThreshold | 0.75 | Renew lease at this fraction of TTL |
Transit MAC
Section titled “Transit MAC”The HashiCorp provider implements ITransitMacService
via transit/hmac + transit/verify (SHA-256), with native rolling rotation
through min_decryption_version. Provision the key with auto-rotation:
vault write -f transit/keys/granit-privacy-export-fragment-hmac \ type=hmac \ auto_rotate_period=2160h # 90 days, ISO 27001 A.10.1.2App policy needs update on transit/hmac/<key> and transit/verify/<key>.
Health checks
Section titled “Health checks”builder.Services.AddHealthChecks() .AddGranitVaultHashiCorpHealthCheck() // Vault sys/health probe .AddGranitSecretStoreHealthCheck(); // ISecretStore canaryThe 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.
Azure Key Vault
Section titled “Azure Key Vault”[DependsOn(typeof(GranitVaultAzureModule))]public class AppModule : GranitModule { }How do I authenticate?
Section titled “How do I authenticate?”Uses DefaultAzureCredential — Managed Identity in AKS, az login locally.
No credentials in configuration.
{ "Vault": { "Azure": { "VaultUri": "https://my-vault.vault.azure.net/" } }}Full configuration
Section titled “Full configuration”{ "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" } }}| Property | Default | Description |
| -------- | ------- | ----------- |
| Vault:Azure:VaultUri | — | Azure 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:DatabaseSecretName | null | Secret name for DB credentials (omit to disable) |
| Vault:Azure:RotationCheckIntervalMinutes | 5 | DB secret rotation polling interval |
| Vault:Azure:TimeoutSeconds | 30 | Azure SDK operation timeout |
Transit MAC
Section titled “Transit MAC”Azure splits by tier. Managed HSM (premium) exposes a native HS256
primitive on an oct-HSM key:
services.AddGranitVaultAzureManagedHsmMac();{ "Vault": { "Azure": { "ManagedHsm": { "Mac": { "HsmUri": "https://my-hsm.managedhsm.azure.net/", "KeyName": "granit-privacy-export-mac" }}}}}Azure Key Vault Standard tier has no HMAC primitive — register the portable
SecretBackedMacService
from Granit.Vault instead (the key material is stored in a Key Vault secret and
HMAC runs locally — a documented trust-boundary trade-off).
Health checks
Section titled “Health checks”builder.Services.AddHealthChecks() .AddGranitAzureKeyVaultHealthCheck() // GetKey probe on EncryptionKeyName .AddGranitSecretStoreHealthCheck(); // ISecretStore canaryAWS (KMS + Secrets Manager)
Section titled “AWS (KMS + Secrets Manager)”[DependsOn(typeof(GranitVaultAwsModule))]public class AppModule : GranitModule { }How do I authenticate?
Section titled “How do I authenticate?”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.
Full configuration
Section titled “Full configuration”{ "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" } }}| Property | Default | Description |
| -------- | ------- | ----------- |
| Vault:Aws:Region | — | AWS region endpoint (required) |
| Vault:Aws:KmsKeyId | — | KMS key ARN or alias for transit encryption (required) |
| Vault:Aws:DatabaseSecretArn | null | Secrets Manager ARN for DB credentials (omit to disable) |
| Vault:Aws:RotationCheckIntervalMinutes | 5 | DB secret rotation polling interval |
| Vault:Aws:AccessKeyId | null | Override; defaults to SDK credential chain |
| Vault:Aws:SecretAccessKey | null | Override; defaults to SDK credential chain |
| Vault:Aws:TimeoutSeconds | 30 | API call timeout |
Transit MAC
Section titled “Transit MAC”AWS KMS implements ITransitMacService via
GenerateMac / VerifyMac on HMAC_256 keys. KMS does not version an HMAC key
in place, so rolling rotation uses a Current + Previous alias pair:
{ "Vault": { "Aws": { "Mac": { "CurrentAlias": "alias/granit/privacy-export-mac-current", "PreviousAlias": "alias/granit/privacy-export-mac-previous" // optional but recommended }}}}Rotation runbook: provision a new HMAC_256 key, point PreviousAlias at the
outgoing key, then CurrentAlias at the new one. Verify keeps accepting the
previous tag throughout the grace window — both VerifyMac calls are always
issued (constant-time fallback) to defeat timing oracles.
Health checks
Section titled “Health checks”builder.Services.AddHealthChecks() .AddGranitKmsHealthCheck() // DescribeKey on KmsKeyId .AddGranitSecretStoreHealthCheck(); // ISecretStore canaryGoogle Cloud (KMS + Secret Manager)
Section titled “Google Cloud (KMS + Secret Manager)”[DependsOn(typeof(GranitVaultGoogleCloudModule))]public class AppModule : GranitModule { }How do I authenticate?
Section titled “How do I authenticate?”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" } }}Full configuration
Section titled “Full configuration”{ "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" } }}| Property | Default | Description |
| -------- | ------- | ----------- |
| Vault:GoogleCloud:ProjectId | — | GCP project id (required) |
| Vault:GoogleCloud:Location | — | Cloud KMS location, e.g. "europe-west1" (required) |
| Vault:GoogleCloud:KeyRing | — | Cloud KMS key ring name (required) |
| Vault:GoogleCloud:CryptoKey | — | Cloud KMS crypto key for transit encryption (required) |
| Vault:GoogleCloud:DatabaseSecretName | null | Secret Manager secret name for DB credentials (omit to disable) |
| Vault:GoogleCloud:RotationCheckIntervalMinutes | 5 | DB secret rotation polling interval |
| Vault:GoogleCloud:CredentialFilePath | null | Service account key JSON; ADC when null |
| Vault:GoogleCloud:TimeoutSeconds | 30 | API call timeout |
Transit MAC
Section titled “Transit MAC”Google Cloud implements ITransitMacService
via MacSign / MacVerify on a CryptoKey with purpose=MAC,
algorithm=HMAC_SHA256. It is version-state aware — verification against
DISABLED / DESTROYED versions is refused.
{ "Vault": { "GoogleCloud": { "Mac": { "CryptoKeyId": "granit-privacy-export-mac" } }}}Provision the CryptoKey via Terraform with purpose = "MAC",
algorithm = "HMAC_SHA256", and rotation_period = "7776000s" (90 days,
ISO 27001 A.10.1.2).
Health checks
Section titled “Health checks”builder.Services.AddHealthChecks() .AddGranitCloudKmsHealthCheck() // Verifies KMS key accessibility .AddGranitSecretStoreHealthCheck(); // ISecretStore canaryPublic API summary
Section titled “Public API summary”| Category | Types | Package |
| -------- | ----- | ------- |
| Modules | GranitEncryptionModule, GranitVaultHashiCorpModule, GranitVaultAzureModule, GranitVaultAwsModule, GranitVaultGoogleCloudModule | — |
| Encryption | IStringEncryptionService, IStringEncryptionProvider, AesStringEncryptionProvider | Granit.Encryption |
| Transit | ITransitEncryptionService, ReEncryptionOptions, RetiredKeyVersionException | Granit.Vault |
| MAC | ITransitMacService, TransitMacResult, SecretBackedMacService, SecretBackedMacOptions | Granit.Vault |
| Secrets | ISecretStore, SecretRequest, SecretVersion, SecretDescriptor, SecretMetadata, SecretStoreOptions, SecretVaultException + subclasses | Granit.Vault |
| Credentials | IDatabaseCredentialProvider | Granit.Vault |
| Observability | VaultMetrics, SecretStoreActivityTags | Granit.Vault |
| Health checks | SecretStoreHealthCheck, VaultHealthCheck, AzureKeyVaultHealthCheck, KmsHealthCheck, CloudKmsHealthCheck | per-provider |
| Extensions | AddGranitEncryption(), AddGranitVaultHashiCorp(), AddGranitVaultAzure(), AddGranitVaultAws(), AddGranitVaultGoogleCloud(), AddGranitVaultAzureManagedHsmMac(), AddGranitSecretBackedMacService(), AddGranitSecretStore<T>(), AddGranitSecretStoreHealthCheck() | — |