IntermediateLesson 7 of 16

Variables, Secrets & Key Vault

Learn how Azure DevOps handles configuration, secret values, variable groups, runtime expressions, and Azure Key Vault integration so your pipelines stay flexible without leaking credentials.

🧒 Simple Explanation (ELI5)

Think of a pipeline like a traveler going through different airports. The traveler needs labels like destination and seat number, and also private documents like a passport. Variables are the labels. Secrets are the private documents. Key Vault is the locked safe that stores the most sensitive documents until they are needed.

If you hardcode everything in the ticket, changing destinations becomes painful and exposing private data becomes easy. Good pipelines keep public settings reusable and sensitive settings protected.

🔧 Technical Explanation

Variable Types in Azure DevOps

TypePurposeExample
Inline YAML variableSimple reusable values in one pipelineenvironment: dev
Pipeline UI variableConfigured in the pipeline editorToggle feature flag for one definition
Variable groupShared values across many pipelinesCommon ACR name, cluster name
Secret variableMasked in logs and protected in UIAPI keys, passwords, PATs
Key Vault linked variable groupSecrets pulled from Azure Key VaultDatabase password from vault
Output variableValue produced by one job and consumed laterImage tag generated during build

Syntax You Must Know

yaml
variables:
  environment: 'dev'
  imageName: 'webapp'

steps:
  - script: echo $(environment)

# Compile-time
${{ variables.imageName }}

# Runtime expression
$[ variables['Build.SourceBranch'] ]

Macro syntax $(name) is what you use most often in task inputs and scripts. Template syntax ${{ }} is resolved earlier when Azure DevOps expands the YAML. Runtime expressions $[ ] are useful for conditional logic and dynamic assignment.

Security Rule

Secret variables are masked in logs, but masking is not magic. If your script transforms the secret, prints JSON with it embedded, or passes it to a tool that echoes config, the value can still leak indirectly.

Variable Groups

Variable groups live under Pipelines → Library. They let multiple pipelines reuse the same values. This is useful for shared platform configuration like registry names, resource groups, namespaces, or public endpoints.

yaml
variables:
- group: shared-platform-config
- name: environment
  value: staging

Azure Key Vault Integration

For sensitive values, connect a variable group to Azure Key Vault. Azure DevOps fetches current secret values from the vault and injects them into the pipeline without storing the raw value in the YAML file.

  1. Create secrets in Azure Key Vault.
  2. Create or reuse an Azure service connection with permission to read vault secrets.
  3. Create a variable group and select Link secrets from an Azure Key Vault as variables.
  4. Select the vault and secret names to expose.
Secret Flow
Key Vault
Variable Group
Pipeline Job
Task / Script

🛠️ Hands-on

Use Variable Groups in YAML

yaml
trigger:
- main

variables:
- group: aks-shared
- name: imageTag
  value: '$(Build.BuildId)'

stages:
- stage: Build
  jobs:
  - job: BuildApp
    pool:
      vmImage: ubuntu-latest
    steps:
    - script: echo "Building $(imageRepository):$(imageTag)"
    - script: echo "Target namespace is $(namespace)"

Consume Key Vault Secrets in an Azure CLI Task

yaml
- task: AzureCLI@2
  displayName: 'Call secure endpoint'
  inputs:
    azureSubscription: 'sc-platform-prod'
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: |
      curl -H "Authorization: Bearer $(api-token)" \
        https://internal.example.com/health

Pass a Secret to Helm Without Printing It

bash
helm upgrade --install payments ./charts/payments \
  --namespace production \
  --set image.tag=$(Build.BuildId) \
  --set-string secrets.connectionString=$(db-connection-string)

Prefer --set-string for secret-like values so Helm does not reinterpret characters. For larger secure config, use Kubernetes secrets or external secret operators instead of pushing too much through command line arguments.

🐛 Debugging Scenarios

Scenario 1: Secret Appears as Empty String

Scenario 2: Key Vault Secrets Fail to Load

Scenario 3: Secret Leaks in Logs

⚠️
Common Mistake

Teams often move hardcoded passwords into secret variables but still write them to files and then publish those files as artifacts. Protect the whole flow, not just the source value.

📋 Interview Questions

Beginner

What is a variable group?

A shared collection of variables stored in Azure DevOps Library so multiple pipelines can reuse common configuration.

What is the difference between a variable and a secret variable?

A secret variable is protected and masked in logs, while a normal variable is not intended for sensitive information.

Why integrate Azure Key Vault with Azure DevOps?

To centralize secret storage, reduce duplication, improve rotation practices, and avoid storing raw secrets directly in pipeline definitions.

What does $(variableName) mean?

It is macro syntax that Azure DevOps expands at runtime when the job executes.

Can one pipeline use variables from multiple groups?

Yes. You can reference multiple variable groups in one pipeline as long as the pipeline has permission to use them.

Intermediate

When should you use Key Vault instead of Azure DevOps secret variables?

When secrets are shared across systems, need rotation, require central governance, or must be consumed by multiple workloads outside Azure DevOps.

How do output variables help multi-stage pipelines?

They allow one job or stage to produce dynamic values, such as a computed image tag, that later jobs can consume without recalculating or hardcoding them.

What are the risks of overusing variable groups?

Shared groups can become a hidden dependency, blur environment boundaries, and accidentally expose more variables than a pipeline really needs.

How do you keep environment-specific config clean?

Use separate variable groups or templates per environment, keep names explicit, and apply least privilege so Dev pipelines cannot read Prod-only secrets.

How does secret masking fail in practice?

Masking only knows the literal secret value. If the value is transformed, split, base64-encoded, or written to artifacts, it may no longer be masked and can leak.

Scenario-Based

A deployment works in Dev but fails in Prod because a variable is wrong. How do you prevent that class of issue?

I separate config by environment, use naming conventions, store sensitive values in Key Vault, validate critical values early in the pipeline, and keep configuration reviewable instead of spreading it across ad hoc UI settings.

A secret is empty only on self-hosted agents. What would you investigate?

I would check agent version, task behavior, environment injection, permission to variable groups, and whether a custom script clears environment variables before the task runs.

How would you rotate secrets with minimal downtime?

Store secrets centrally in Key Vault, support dual-valid credentials where possible, update consumers to accept the new secret, validate in lower environments, then retire the old value only after successful rollout.

What is your stance on storing kubeconfig or certificates as secret variables?

It is possible but usually not ideal. I prefer managed service connections, federated identity, secure files, or workload identity because they reduce handling complexity and leakage risk.

How do you explain config vs secret to a beginner developer?

Config tells the app where and how to run. Secrets prove identity or grant privileged access. Both may change by environment, but only secrets need strong confidentiality controls.

🌍 Real-World Usage

A real enterprise platform team usually standardizes shared non-secret variables in Library, keeps environment secrets in Key Vault, and exposes only the minimum set needed per pipeline. This supports safer CI/CD for build, ACR push, and AKS deploy flows without hardcoding anything in source control.

🧾 Summary

Variables make pipelines reusable. Secrets make them safe. Key Vault adds central control and better operational hygiene. Mature Azure DevOps delivery depends on separating public configuration from sensitive data and understanding exactly when each value is expanded and where it can leak.