Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Use Azure Key Vault Secrets in Pipelines

By Kokil Thapa | Last reviewed: September 2026

Hard-coded passwords in pipeline YAML are a breach waiting to happen. To use Azure Key Vault secrets in pipelines, you store credentials in a vault and let CI/CD fetch them at runtime through managed identity or a service connection. That pattern keeps secrets out of Git, audit logs, and pull-request diffs. If you already understand vault objects, start with our Azure Key Vault keys, secrets, and certificates overview; this guide focuses on wiring those secrets into Azure Pipelines and similar workflows.

How do you use Azure Key Vault secrets in Azure Pipelines?

Azure DevOps can pull secrets from Key Vault in two main ways. Variable groups sync vault secrets into named pipeline variables. The AzureKeyVault task downloads secrets into the job environment for that run only. Both approaches beat pasting values into library variables or YAML files.

On production Laravel deployments I maintain, database URLs and API keys live in vaults. The pipeline reads them during deploy. Local developers use .env files. Production never echoes those values in build logs when masking is configured correctly.

Pipeline to Key Vault Secret FlowAzure DevOpsYAML PipelineManaged IDRBAC authAzure Key VaultSecrets storeRuntime fetch at job startDB-CONNECTION-STRING, STRIPE-KEY, SMTP-PASSMasked in logs, never committed to Git
Use Azure Key Vault secrets in pipelines by authenticating with managed identity and fetching values at job runtime.

Step 1: Create secrets in the vault

Store each credential as a named secret. Use kebab-case names like prod-db-password or stripe-secret-key. One secret per value makes rotation and auditing simpler than bundling JSON blobs unless your app expects structured config.

az keyvault secret set \
  --vault-name "myapp-prod-kv" \
  --name "prod-db-password" \
  --value "your-strong-password-here"

Microsoft documents vault creation and secret management in the Azure Key Vault secrets quickstart. Enable soft delete and purge protection on production vaults. Accidental deletion without recovery is painful during a Friday deploy.

In Azure DevOps, open Pipelines → Library → + Variable group. Toggle Link secrets from an Azure key vault as variables. Pick your subscription and vault. Select the secrets you need. Azure DevOps maps each secret name to an identically named variable.

  1. Create the variable group and link the vault.
  2. Grant the pipeline access when prompted, or configure RBAC manually.
  3. Reference the group in YAML with - group: my-prod-secrets.
  4. Use variables as $(prod-db-password) in tasks and scripts.

Step 3: Use the AzureKeyVault task in YAML

The task approach suits jobs that need fresh secrets each run without syncing a library group. Add it as the first step in a deployment job.

steps:
  - task: AzureKeyVault@2
    inputs:
      azureSubscription: 'my-azure-service-connection'
      KeyVaultName: 'myapp-prod-kv'
      SecretsFilter: 'prod-db-password,stripe-secret-key'
      RunAsPreJob: true

  - script: |
      php artisan migrate --force
    env:
      DB_PASSWORD: $(prod-db-password)

For broader pipeline design patterns, see our Azure DevOps YAML pipelines practical guide and build your first Azure Pipelines CI/CD pipeline walkthrough.

What permissions does a pipeline need to read Key Vault secrets?

Key Vault access works through Azure RBAC or the legacy access policy model. RBAC is the current default for new vaults. Assign the pipeline identity the Key Vault Secrets User role at vault scope. That role allows get and list on secrets without granting key or certificate permissions.

Two identity options exist. A user-assigned managed identity on a self-hosted agent is clean for long-running infrastructure. Azure DevOps service connections use a service principal or workload identity federation. Both need the same RBAC role on the vault resource.

RBAC Setup for Pipeline AccessService Principalor Managed IDAssign RoleKey VaultKey Vault Secrets User roleScope: /subscriptions/.../vaults/myapp-prod-kvActions: Microsoft.KeyVault/vaults/secrets/getActions: Microsoft.KeyVault/vaults/secrets/list
Grant Key Vault Secrets User RBAC role to the pipeline service principal or managed identity before linking secrets.

Assign RBAC with Azure CLI

PRINCIPAL_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
VAULT_ID=$(az keyvault show --name myapp-prod-kv --query id -o tsv)

az role assignment create \
  --role "Key Vault Secrets User" \
  --assignee-object-id "$PRINCIPAL_ID" \
  --assignee-principal-type ServicePrincipal \
  --scope "$VAULT_ID"

Wait a few minutes after role assignment. Azure RBAC propagation is not instant. A common failure is a 403 on the first pipeline run right after setup. Re-run the job before debugging YAML.

If your vault still uses access policies, add get and list for secrets to the pipeline identity. New projects should migrate to RBAC. The Azure Key Vault overview explains permission models and migration paths.

Self-hosted agents need their own identity configuration. Our self-hosted Azure DevOps agents guide covers network and identity setup for agents outside Microsoft-hosted pools.

How do you reference Key Vault secrets in YAML without leaking them?

Secret variables behave differently from normal variables in Azure Pipelines. They are masked in logs. They are not passed to downstream tasks as plain environment variables unless you map them explicitly. Never print secret variables in scripts, even for debugging.

Variable group reference in multi-stage pipelines

variables:
  - group: my-prod-secrets
  - name: APP_ENV
    value: production

stages:
  - stage: Deploy
    jobs:
      - deployment: DeployWeb
        environment: production
        strategy:
          runOnce:
            deploy:
              steps:
                - script: echo "Deploying with vault-backed config"
                - task: AzureWebApp@1
                  inputs:
                    azureSubscription: 'my-azure-service-connection'
                    appName: 'myapp-prod'
                    appSettings: |
                      -DB_PASSWORD $(prod-db-password)
                      -STRIPE_KEY $(stripe-secret-key)

Mark non-vault variables as secret in the library when they cannot live in Key Vault yet. Prefer vault for anything that rotates or has compliance requirements. Pair this setup with secrets scanning in Git and CI with Gitleaks so accidental commits get caught early.

Mapping secrets to environment variables for scripts

Shell and PowerShell tasks need explicit env blocks. Laravel Artisan, Composer auth, and npm private registry tokens all follow this pattern.

- script: composer install --no-dev --prefer-dist
  env:
    COMPOSER_AUTH: $(composer-auth-json)

Generate strong local placeholders with our password generator tool during development. Never reuse production vault values on a laptop. Use separate vaults or secret names for dev, staging, and prod.

YAML Pipeline Secret ReferenceBuild StageVariable Groupvault-linkedDeploy StageApp Service$(prod-db-password) mapped via env blockSecret masking active in all log outputNo secret values in azure-pipelines.ymlSeparate groups per environment
Reference Key Vault secrets in YAML through linked variable groups and explicit env mappings in deploy stages.

Azure Key Vault vs variable groups vs pipeline secrets — which should you use?

Teams often mix three storage layers. Understanding the trade-offs prevents duplicate secrets and stale values.

MethodBest forRotationAudit trail
Azure Key VaultProduction credentials, API keys, connection stringsCentral rotation, version historyAzure Activity Log + vault diagnostics
Variable groups (non-vault)Non-sensitive config, feature flags, build numbersManual update in LibraryAzure DevOps audit events
Pipeline secret variablesSingle-pipeline tokens, short-lived experimentsPer-pipeline editLimited cross-pipeline visibility

Production systems should default to Key Vault. Variable groups linked to vaults give Azure DevOps a friendly variable surface. Plain library secrets are acceptable for low-risk values like a Slack webhook for build notifications.

HashiCorp Vault and AWS Secrets Manager solve similar problems on other clouds. Read our HashiCorp Vault secrets management guide, AWS Secrets Manager for pipelines, and multi-cloud secrets management comparison if your stack spans providers.

For GitLab-based PHP projects, the same principle applies even without Azure DevOps. External secret files and protected variables replace vault calls. See CI/CD with GitLab CI for Laravel for a parallel workflow on Linux servers I deploy regularly.

What are common mistakes when using Azure Key Vault in CI/CD?

Most failures I troubleshoot are permission or naming issues, not Azure DevOps bugs. The fixes are usually boring and fast once you know where to look.

  • 403 Forbidden on fetch: RBAC not propagated, wrong principal, or vault firewall blocking the agent IP.
  • Empty variable at runtime: Secret name mismatch between vault and YAML reference. Names are case-sensitive.
  • Secret printed in logs: Script echoes the value or passes it as a command-line argument. Use env blocks instead.
  • All secrets downloaded: Omitting SecretsFilter pulls every vault secret into the job. Apply least privilege.
  • Shared vault across environments: Prod and dev secrets in one vault increases blast radius. Split by environment.
  • No rotation plan: Vault stores the secret safely but stale passwords still work until rotated.
Pipeline Key Vault TroubleshootingPipeline failed?403 errorCheck RBAC roleEmpty variableMatch secret nameLeaked in logUse env mappingFix: Secrets User role + SecretsFilter + per-env vaultRe-run after 5 min RBAC propagation
Diagnose Azure Key Vault pipeline failures by checking RBAC, secret name spelling, and log masking before changing application code.

Network restrictions on the vault

Production vaults often allow only selected networks. Microsoft-hosted agents use dynamic outbound IPs. Either allow Azure DevOps service tags, use a self-hosted agent on a known subnet, or configure private endpoints with appropriate DNS. This trips teams that lock down vaults before testing pipeline access.

For AKS deployments, secrets often flow vault → pipeline → Kubernetes. Our deploy to AKS with Azure Pipelines and Kubernetes secrets management guide cover the next hop after the pipeline fetch.

Rotation without breaking builds

Key Vault supports secret versioning. Pipelines typically read the latest version. Coordinate rotation with a dual-write window when apps cache credentials. Update the vault value, redeploy, then revoke the old version if your compliance team requires it.

Broader CI/CD hygiene matters too. Follow CI/CD secrets management best practices and build pipeline automation best practices so vault integration fits a larger secure delivery model.

How do you use Key Vault secrets in GitHub Actions or other CI systems?

Azure Key Vault is not limited to Azure DevOps. GitHub Actions uses the azure/login action with OIDC federation, then Azure CLI or SDK calls to read secrets. Jenkins and GitLab CI can authenticate with a service principal and fetch secrets over the REST API.

- uses: azure/login@v2
  with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: Read Key Vault secret
  run: |
    DB_PASS=$(az keyvault secret show \
      --vault-name myapp-prod-kv \
      --name prod-db-password \
      --query value -o tsv)
    echo "::add-mask::$DB_PASS"
    echo "DB_PASS=$DB_PASS" >> $GITHUB_ENV

The federated identity pattern avoids storing client secrets in GitHub. That is the same trust model Azure DevOps workload identity federation uses. Only the long-lived client ID sits in GitHub secrets; the vault holds everything sensitive.

On client projects where I handle full delivery, vault wiring sits alongside server hardening and deploy automation. That work falls under Linux system administration and enterprise application development when the pipeline deploys to Ubuntu VMs rather than Azure App Service.

Key Takeaways

  • Store production credentials in Azure Key Vault; never commit them to YAML, Git, or unlinked library variables.
  • Assign Key Vault Secrets User RBAC to the pipeline service principal or managed identity at vault scope.
  • Link vault secrets through variable groups or the AzureKeyVault@2 task with an explicit SecretsFilter.
  • Map secrets to tasks via env blocks and treat log masking as mandatory, not optional.
  • Use separate vaults per environment and pair vault storage with rotation and Git secrets scanning.
  • Re-run failed jobs after RBAC changes; propagation delay causes false 403 errors on first attempt.

People Also Ask

Can Azure Pipelines read Key Vault secrets without storing them in the library?

Yes. The AzureKeyVault@2 task fetches secrets directly into the job environment at runtime. Values never persist in the Library UI unless you also link a variable group. Use the task when you want fetch-only access per job.

Do I need a service connection to use Azure Key Vault in pipelines?

Azure DevOps YAML pipelines typically use an Azure Resource Manager service connection backed by a service principal or workload identity. That connection authenticates the AzureKeyVault task and vault-linked variable groups. Self-hosted agents can alternatively use a managed identity without a stored client secret.

Are Key Vault secret names case-sensitive in pipelines?

Yes. A vault secret named Prod-Db-Password will not resolve when YAML references $(prod-db-password). Match names exactly between the vault, variable group mapping, and YAML variable references.

How much does Azure Key Vault cost for CI/CD secret storage?

Key Vault charges per secret operation and per secret stored. Typical CI/CD fetch volumes stay within a few dollars monthly for small teams. At roughly Rs 650/month (~USD 5) for modest secret counts, vault cost is negligible compared to a credential leak or emergency rotation.

Ship pipelines that never store passwords in Git

To use Azure Key Vault secrets in pipelines correctly, treat the vault as the single source of truth for production credentials. Wire RBAC once, link secrets through variable groups or the AzureKeyVault task, and keep YAML free of values. That is the same discipline I apply on booking platforms like Adventure Third Pole Trek and client portals such as Mijar Law Associates, where deploy pipelines must stay auditable.

If you need help connecting Azure Pipelines, Key Vault, and your application stack, review our custom software development services or support and maintenance offerings. For encoding tasks during local setup, the Base64 encoder and decoder is handy—but production secrets belong in the vault, not in chat or tickets.

Contact us to audit your current pipeline secrets setup or plan a migration from plain-text variables to Key Vault-backed deploys.

Frequently Asked Questions

Store credentials in Azure Key Vault and let CI/CD fetch them at runtime through managed identity or a service connection—never hard-code passwords in YAML, Git, or pull-request diffs.

Azure DevOps offers two paths. Link the vault to a Library variable group and reference secrets as $(secret-name) in YAML, or run AzureKeyVault@2 as the first step with an explicit SecretsFilter. Grant the pipeline Key Vault Secrets User RBAC at vault scope, authenticate via an Azure Resource Manager service connection, and map values into scripts through env blocks for tasks like php artisan migrate or AzureWebApp deploy settings.

Assign Key Vault Secrets User at vault scope to the service principal or managed identity behind your service connection. That RBAC role grants get and list on secrets without key or certificate access. Legacy access-policy vaults need the same get and list permissions added manually. Wait a few minutes after role assignment—403 on the first run usually means RBAC propagation delay, not broken YAML. Re-run before debugging further.

Yes, for typical Azure DevOps YAML pipelines. An Azure Resource Manager service connection backed by a service principal or workload identity federation authenticates vault-linked variable groups and the AzureKeyVault task. Self-hosted agents can alternatively use a user-assigned managed identity without a stored client secret.

Yes. The AzureKeyVault@2 task fetches secrets directly into the job environment at runtime with RunAsPreJob set true. Values never persist in the Library UI unless you also link a variable group. Use SecretsFilter to pull only named secrets—omitting it downloads every vault secret into the job, which violates least privilege and widens exposure if the run is compromised.

Secret variables from linked groups or the AzureKeyVault task are masked in logs and are not passed to downstream tasks unless you map them explicitly in env blocks. Never echo secret values or pass them as command-line arguments. Reference groups with - group: my-prod-secrets in multi-stage YAML, use $(prod-db-password) in task inputs, and pair vault storage with Git secrets scanning using tools like Gitleaks to catch accidental commits early.

Production credentials, API keys, and connection strings belong in Key Vault for central rotation, version history, and Azure Activity Log auditing. Variable groups linked to vaults give Azure DevOps a friendly variable surface for deploy stages. Plain library or pipeline secret variables suit low-risk values like Slack build-notification webhooks. Avoid storing the same credential in all three layers—that creates duplicate secrets, stale values, and unclear rotation ownership.

Yes. A vault secret named Prod-Db-Password will not resolve when YAML references $(prod-db-password). Match names exactly between the vault, variable group mapping, and YAML references or variables arrive empty at runtime with no obvious error beyond a failed deploy.

Key Vault charges per secret stored and per operation. Typical CI/CD fetch volumes for small teams stay around Rs 650/month (~USD 5)—negligible compared to a credential leak or emergency rotation.

Most failures are permission or naming issues, not Azure DevOps bugs. Watch for 403 after fresh RBAC setup, case-sensitive name mismatches causing empty variables, secrets printed via echo or CLI arguments, missing SecretsFilter pulling the entire vault, prod and dev sharing one vault, and credentials that never rotate despite safe storage. Diagnose by checking RBAC, secret name spelling, and log masking before changing application code.

Production vaults often allow only selected networks. Microsoft-hosted agents use dynamic outbound IPs that vault firewalls block unless you allow Azure DevOps service tags, run a self-hosted agent on a known subnet, or configure private endpoints with correct DNS. This trips teams that lock down vaults before testing pipeline access. Self-hosted agents need their own identity and network configuration aligned with vault rules.

Split vaults by environment—separate prod, staging, and dev. A shared vault increases blast radius if one pipeline misconfiguration exposes every credential. Use kebab-case names like prod-db-password and stripe-secret-key, enable soft delete and purge protection on production vaults, and keep local developers on .env files with separate vaults or secret names. Never reuse production vault values on a laptop.

Key Vault versions secrets and pipelines typically read the latest. Coordinate rotation with a dual-write window when apps cache credentials: update the vault value, redeploy consuming services, then revoke the old version if compliance requires it. Vault storage alone does not replace a rotation schedule—stale passwords still authenticate until changed. Pair rotation with redeploys on production Laravel apps where database URLs and API keys live in vaults.

GitHub Actions uses azure/login@v2 with OIDC federated identity—only the client ID sits in GitHub secrets—then az keyvault secret show via Azure CLI. Mask output with add-mask before writing to GITHUB_ENV. Jenkins and GitLab CI authenticate with a service principal and fetch secrets over the REST API. The federated identity pattern matches Azure DevOps workload identity federation and avoids storing client secrets in Git.

RBAC is the current default for new vaults. Assign Key Vault Secrets User to the pipeline identity at vault scope for get and list on secrets without granting key or certificate permissions. Legacy access-policy vaults need get and list added manually to the pipeline principal. New projects should use RBAC; Microsoft documents migration paths in the Key Vault overview. Assign roles with az role assignment create and verify the correct principal object ID before linking secrets.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: