Skip to content

Azure Key Vault Plugin

Our Azure Key Vault plugin enables secure loading of secrets from Azure Key Vault using declarative instructions within your .env files.

The plugin automatically integrates with Azure authentication, including Managed Identity for Azure-hosted applications, Azure CLI credentials for local development, and service principal credentials for non-Azure environments.

  • Zero-config authentication - Just provide your vault URL, authentication happens automatically
  • Managed Identity support - No credentials needed for Azure-hosted apps (App Service, Container Instances, VMs, Functions, AKS)
  • Azure CLI authentication - Works seamlessly with az login for local development
  • Auto-infer secret names from environment variable names (e.g., DATABASE_URLdatabase-url)
  • Support for service principal credentials (for non-Azure environments)
  • Support for versioned secrets
  • Automatic token caching and renewal
  • Lightweight implementation using REST API (47 KB bundle, no heavy Azure SDK dependencies)

In a JS/TS project, you may install the @varlock/azure-key-vault-plugin package as a normal dependency. Otherwise you can just load it directly from your .env.schema file, as long as you add a version specifier. See the plugins guide for more instructions on installing plugins.

.env.schema
# 1. Load the plugin
# @plugin(@varlock/azure-key-vault-plugin)
#
# 2. Initialize the plugin - see below for more details on options
# @initAzure(vaultUrl="https://my-vault.vault.azure.net/")
# ---

The plugin tries authentication methods in this priority order:

  1. Service Principal - If all three credentials (tenantId, clientId, clientSecret) are provided
  2. Managed Identity - Automatically used when running on Azure infrastructure
  3. Azure CLI - Falls back to az login for local development

For most use cases, you only need to provide the vault URL:

.env.schema
# @plugin(@varlock/azure-key-vault-plugin)
# @initAzure(vaultUrl="https://my-vault.vault.azure.net/")
# ---

How this works:

  • Local development: Run az login → automatically uses Azure CLI credentials
  • Azure-hosted apps (App Service, Container Instances, VMs, Functions, AKS): Enable Managed Identity → automatically authenticates (no secrets needed!)
  • Works everywhere with zero configuration beyond the vault URL!

Service principal credentials (For non-Azure environments)

Section titled “Service principal credentials (For non-Azure environments)”

If you’re deploying outside of Azure (e.g., AWS, GCP, on-premises), wire up service principal credentials:

  1. Create a service principal with the necessary permissions (see Azure Setup section below)

  2. Wire up the credentials in your config. Add config items for the tenant ID, client ID, and client secret, and reference them when initializing the plugin.

    .env.schema
    # @plugin(@varlock/azure-key-vault-plugin)
    # @initAzure(
    # vaultUrl="https://my-vault.vault.azure.net/",
    # tenantId=$AZURE_TENANT_ID,
    # clientId=$AZURE_CLIENT_ID,
    # clientSecret=$AZURE_CLIENT_SECRET
    # )
    # ---
    # @type=azureTenantId @sensitive
    AZURE_TENANT_ID=
    # @type=azureClientId @sensitive
    AZURE_CLIENT_ID=
    # @type=azureClientSecret @sensitive
    AZURE_CLIENT_SECRET=
  3. Set your credentials in deployed environments. Use your platform’s env var management UI to securely inject these values.

If you need to connect to multiple vaults, but never at the same time, you can alter the vault URL using a function:

.env.schema
# @plugin(@varlock/azure-key-vault-plugin)
# @initAzure(vaultUrl="https://my-vault-${ENV}.vault.azure.net/")
# ---

Or if you need to connect to multiple vaults simultaneously, register multiple named instances:

.env.schema
# @initAzure(id=prod, vaultUrl="https://my-vault-prod.vault.azure.net/")
# @initAzure(id=dev, vaultUrl="https://my-vault-dev.vault.azure.net/")
# ---
PROD_SECRET=azureSecret(prod, "database-url")
DEV_SECRET=azureSecret(dev, "database-url")

Once the plugin is installed and initialized, you can start adding config items that load values using the azureSecret() resolver function.

The azureSecret() function fetches secrets from Azure Key Vault.

.env.schema
# Auto-infer secret names (DATABASE_URL -> "database-url")
DATABASE_URL=azureSecret()
API_KEY=azureSecret()
# Explicit secret names
CUSTOM_SECRET=azureSecret("my-custom-secret-name")

You can fetch specific versions of secrets by appending @version to the secret name:

.env.schema
# Fetch latest version (default)
API_KEY=azureSecret("api-key")
# Fetch specific version
API_KEY_V1=azureSecret("api-key@abc123def456")

Your managed identity, service principal, or user needs one of:

  • Access Policy: “Get” permission for secrets
  • RBAC: “Key Vault Secrets User” role
Section titled “Managed Identity for Azure-hosted apps (Recommended)”

Managed Identity is the Azure-native way to authenticate - no credentials needed!

  1. Enable system-assigned managed identity for your Azure resource

    Terminal window
    # For App Service
    az webapp identity assign --name my-app --resource-group my-rg
    # For Container Instance
    az container create --assign-identity --name my-container ...
    # For VM
    az vm identity assign --name my-vm --resource-group my-rg
  2. Grant Key Vault access to the identity

    Get the identity’s principal ID:

    Terminal window
    PRINCIPAL_ID=$(az webapp identity show --name my-app --resource-group my-rg --query principalId -o tsv)

    Then grant access using either RBAC or Access Policy:

    Option A: RBAC (Recommended)

    Terminal window
    az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee $PRINCIPAL_ID \
    --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault-name>

    Option B: Access Policy

    Terminal window
    az keyvault set-policy \
    --name my-vault \
    --object-id $PRINCIPAL_ID \
    --secret-permissions get
  3. That’s it! Your app will automatically authenticate using Managed Identity.

Service principal for non-Azure environments

Section titled “Service principal for non-Azure environments”
  1. Create a service principal

    Terminal window
    az ad sp create-for-rbac --name "varlock-keyvault-reader"

    Save the appId, password, and tenant from the output.

  2. Grant Key Vault access

    Option A: RBAC (Recommended)

    Terminal window
    az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee <appId> \
    --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault-name>

    Option B: Access Policy

    Terminal window
    az keyvault set-policy \
    --name my-vault \
    --spn <appId> \
    --secret-permissions get
  1. Install the Azure CLI if you haven’t already: Installation guide

  2. Log in to Azure

    Terminal window
    az login
  3. Verify your identity

    Terminal window
    az account show
  4. Grant Key Vault access to your user account (if needed)

    Terminal window
    az keyvault set-policy \
    --name my-vault \
    --upn your-email@domain.com \
    --secret-permissions get

Initialize an Azure Key Vault plugin instance for accessing secrets.

Key/value args:

  • vaultUrl (required): Azure Key Vault URL (e.g., https://my-vault.vault.azure.net/)
  • tenantId (optional): Azure AD tenant ID (directory ID)
  • clientId (optional): Service principal application (client) ID
  • clientSecret (optional): Service principal client secret (password)
  • id (optional): Instance identifier for multiple vaults
# @initAzure(vaultUrl="https://my-vault.vault.azure.net/")
# ---

Represents an Azure AD tenant ID (UUID format). This type is marked as @sensitive.

# @type=azureTenantId
AZURE_TENANT_ID=

Represents a service principal application (client) ID (UUID format). This type is marked as @sensitive.

# @type=azureClientId
AZURE_CLIENT_ID=

Represents a service principal client secret (password). This type is marked as @sensitive.

# @type=azureClientSecret
AZURE_CLIENT_SECRET=

Fetch a secret from Azure Key Vault.

Array args:

  • instanceId (optional): instance identifier to use when multiple plugin instances are initialized
  • secretName (optional): secret name or name with version using @ syntax. If omitted, uses the variable name (converted to kebab-case).
# Auto-infer secret name (DATABASE_URL -> "database-url")
DATABASE_URL=azureSecret()
# Explicit secret name
CUSTOM_SECRET=azureSecret("my-custom-secret")
# Specific version
API_KEY_V1=azureSecret("api-key@abc123def456")
# With instance ID
PROD_SECRET=azureSecret(prod, "database-url")

  • Verify the secret exists: az keyvault secret list --vault-name my-vault
  • Remember: Azure uses hyphens, not underscores (use database-url not database_url)
  • Check for typos in the secret name
  • Check your RBAC role: az role assignment list --assignee <your-id> --scope <vault-scope>
  • Or check access policies: az keyvault show --name my-vault --query properties.accessPolicies
  • Ensure your identity has “Get” permission for secrets
  • Local dev: Run az login and ensure service principal env vars are empty
  • Azure-hosted apps: Verify Managed Identity is enabled and has Key Vault permissions
  • Other environments: Verify service principal credentials are correct and properly injected
  • Test identity: az account show
  • Verify the vault URL is correct
  • Check network access: Ensure firewall rules allow access from your IP/resource
  • Verify the vault exists in the specified subscription