tsafe-azure 1.2.1

Azure Key Vault HTTP client for tsafe — pull/push secrets between AKV and the local encrypted vault
Documentation

tsafe-azure

Azure Key Vault integration for tsafe.

What this does

Synchronous HTTP client for pulling secrets from Azure Key Vault into the local tsafe vault. The local vault remains the single source of truth — Key Vault is a read source only. No secret data is ever written back to Azure unless you explicitly use tsafe kv-push.

Used by the tsafe kv-pull and tsafe kv-push commands.

Direct use

Most users should install the CLI:

cargo install tsafe-cli

This crate is published separately for consumers who want to call the Azure Key Vault HTTP API from Rust without pulling in the full CLI surface.

[dependencies]
tsafe-azure = "1"

Auth

Authentication is resolved in this order:

  1. Service principal — set all three of AZURE_TENANT_ID, AZURE_CLIENT_ID, and AZURE_CLIENT_SECRET to obtain a client-credentials token from AAD.
  2. Managed identity — if the service principal variables are absent, the IMDS endpoint (http://169.254.169.254/...) is tried automatically. Works inside Azure VMs, ACI, and App Service.

The vault URL is always required:

Variable Required Description
TSAFE_AKV_URL yes Key Vault endpoint, e.g. https://myvault.vault.azure.net
AZURE_TENANT_ID SP auth AAD tenant ID
AZURE_CLIENT_ID SP auth Service principal / app registration client ID
AZURE_CLIENT_SECRET SP auth Service principal client secret

TSAFE_AKV_URL must begin with https://. Plain HTTP is rejected.

Key normalisation

Secret names use hyphens in Key Vault (my-db-password). On import they are normalised to MY_DB_PASSWORD (uppercase, hyphens replaced with underscores) so they are immediately usable as environment variable names.

Example

use tsafe_azure::{KvConfig, acquire_token, pull_secrets};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let cfg = KvConfig::from_env()?;
    // acquire_token reads AZURE_TENANT_ID / CLIENT_ID / CLIENT_SECRET,
    // or falls back to managed identity automatically.
    let secrets = pull_secrets(&cfg, &|| acquire_token(&cfg), None)?;
    for (key, value) in &secrets {
        println!("{key}=<{} bytes>", value.len());
    }
    Ok(())
}

To pull only secrets whose names begin with a given prefix:

let secrets = pull_secrets(&cfg, &|| acquire_token(&cfg), Some("app-"))?;

push_secret and delete_secret are also part of the public API for the kv-push direction.

Retry behaviour

The HTTP client retries on 429 (throttled) responses, honouring the Retry-After header when present, and retries on transient transport errors with exponential backoff and jitter. Both retry budgets are capped at 30 seconds per attempt.

License

Same as the tsafe workspace — see the repository root.