Azure Key Vault resolver
Config resolver that swaps azure-kv: placeholders for live values fetched from Azure Key Vault.
Overview
The Piko config loader resolves <prefix>:<value> placeholder strings against any registered resolver. The Azure package handles the azure-kv: prefix. The loader strips the prefix and hands the resolver a vault-name/secret-name body. The resolver looks up https://<vault-name>.vault.azure.net/, fetches the secret through the official azsecrets SDK, and returns the value. A #<key> suffix selects a field inside a JSON-shaped secret.
The resolver code stays small because it inherits the loader machinery. The loader holds a shared circuit breaker and a short-lived resolution cache, so a failing vault fails fast and repeated lookups of the same placeholder skip the round trip. The resolver itself caches one azsecrets client per vault, so repeated lookups against the same vault reuse the connection pool.
The resolver authenticates with DefaultAzureCredential, which walks an authentication chain: environment variables, Workload Identity, Managed Identity, Azure CLI, and so on. The constructor accepts no static credentials.
The Azure SDK dependency tree lives in a separately versioned module, piko.sh/piko/wdk/config/config_resolver_azure. The core Piko module does not depend on it, so an application that never touches Key Vault never pulls in the Azure SDK. Add the module and run go mod tidy to bring in the dependency. This resolver slots into the same config.Resolver contract as the AWS, GCP, Kubernetes, and Vault siblings, so combining or swapping secret backends stays uniform.
Requirements
- Azure credentials reachable through
DefaultAzureCredential. In production this means a Managed Identity assigned to the host, for example App Service, an AKS pod identity, or a VM. Locally it meansaz loginor environment-variable credentials. - An Azure RBAC role on the Key Vault that includes
Getfor secrets. TheKey Vault Secrets Userrole covers this. TheKey Vault Readerrole covers both metadata and values. The legacy access policy permissionGetfor secrets also works. - Network egress to
<vault-name>.vault.azure.netover HTTPS.
Configuration
NewResolver takes no arguments. It constructs DefaultAzureCredential internally.
import "piko.sh/piko/wdk/config/config_resolver_azure"
resolver, err := config_resolver_azure.NewResolver()
if err != nil {
return err
}
Reference secrets in your config struct with the azure-kv: prefix and the vault-name/secret-name body:
database:
password: azure-kv:my-prod-vault/db-password
stripe:
secret_key: azure-kv:my-prod-vault/api-keys#stripe
Bootstrap
import (
"piko.sh/piko"
"piko.sh/piko/wdk/config/config_resolver_azure"
)
resolver, err := config_resolver_azure.NewResolver()
if err != nil {
return err
}
ssr := piko.New(
piko.WithConfigResolvers(resolver),
)
That single WithConfigResolvers option is the only wiring step. NewResolver takes no arguments and the returned *Resolver satisfies the config.Resolver contract, so the integration adds no glue code beyond these two lines.
The package also exports a Register() shortcut that constructs a resolver and registers it in the global resolver registry through config.RegisterResolver, useful from init().
Secret resolution runs in the compiled bootstrap path that loads config, so the interpreted dev mode used for pure-Go providers does not affect it.
See also
Sibling resolvers:
- AWS Secrets Manager,
aws-secret:prefix. - GCP Secret Manager,
gcp-secret:prefix. - Kubernetes Secrets,
kubernetes-secret:prefix. - HashiCorp Vault,
vault:prefix.
Companion provider:
- Piko config provider, the default Piko config provider that consumes resolvers.
Framework docs:
- How to manage configuration and secrets, the end-to-end config-and-secrets workflow.
- Secrets API reference,
Resolverregistration and the placeholder format. - About configuration, design rationale, precedence rules, and the resolver model.
External:
- Azure Key Vault documentation, authoritative reference.
- DefaultAzureCredential, the auth chain this resolver uses.