> ## Documentation Index
> Fetch the complete documentation index at: https://www.checklyhq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy Checkly secrets from Azure Key Vault

> Authenticate to Azure with GitHub OIDC, load deployment secrets from Azure Key Vault, and deploy them at group or check scope.

Use GitHub OpenID Connect (OIDC) to give a trusted deployment job short-lived access to Azure Key Vault. The job maps each Key Vault secret to the `CHECKLY_SECRET_*` name expected by your Checkly constructs, then runs `checkly deploy`.

For the scoping model and operational guidance behind this workflow, read [Manage secrets at scale](/docs/platform/manage-secrets-at-scale).

<Accordion title="Prerequisites">
  * A Checkly Monitoring as Code project that declares secrets with `secret()` and `secret: true` at [group or check scope](/docs/platform/manage-secrets-at-scale#choose-the-narrowest-scope).
  * An Azure Key Vault that uses the Azure role-based access control (RBAC) permission model.
  * A Microsoft Entra application or user-assigned managed identity with a [federated identity credential for GitHub Actions](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust).
  * The identity has the `Key Vault Secrets User` role on the vault that contains this project's secrets.
  * `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, `AZURE_SUBSCRIPTION_ID`, `AZURE_KEY_VAULT`, and `CHECKLY_ACCOUNT_ID` configured as GitHub Actions variables.
  * The Checkly API key stored in Key Vault as `checkly-api-key`, alongside the secrets required by this project.
</Accordion>

<Info>
  This guide uses a fictional payments service; replace its names and URL with
  your own application values. Checkly requires `CHECKLY_API_KEY` and
  `CHECKLY_ACCOUNT_ID`; the `AZURE_*` variables configure this workflow.
</Info>

## Configure Azure access

Follow Microsoft's [GitHub OIDC setup guide](https://learn.microsoft.com/en-us/azure/developer/github/connect-from-azure-openid-connect) to create a federated identity for the repository and GitHub environment that deploy Checkly.

Assign the identity the read-only [`Key Vault Secrets User` role](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide#azure-built-in-roles-for-key-vault-data-plane-operations) at the narrowest practical scope. The GitHub Actions runner must be able to reach the vault.

## Map Key Vault secrets to Checkly

The following example assumes your application uses two credentials stored in Key Vault as `payments-api-key` and `payments-admin-token`. These are example names, not Azure or Checkly requirements. Reference their deployment environment names in your constructs:

```typescript __checks__/payments.check.ts theme={null}
import { ApiCheck, CheckGroupV2 } from 'checkly/constructs'
import { secret } from 'checkly/util'

const paymentsGroup = new CheckGroupV2('payments', {
  name: 'Payments',
  environmentVariables: [
    {
      key: 'PAYMENTS_API_KEY',
      value: secret('PAYMENTS_API_KEY'),
      secret: true,
    },
  ],
})

new ApiCheck('payments-admin-health', {
  name: 'Payments admin health',
  group: paymentsGroup,
  environmentVariables: [
    {
      key: 'PAYMENTS_ADMIN_TOKEN',
      value: secret('PAYMENTS_ADMIN_TOKEN'),
      secret: true,
    },
  ],
  request: {
    method: 'GET',
    url: 'https://payments.example.com/admin/health',
    headers: [
      { key: 'Authorization', value: 'Bearer {{PAYMENTS_ADMIN_TOKEN}}' },
    ],
  },
})
```

`secret('PAYMENTS_API_KEY')` reads `CHECKLY_SECRET_PAYMENTS_API_KEY` when the CLI loads the project. The Key Vault name and the Checkly environment name do not need to match.

## Deploy from GitHub Actions

This workflow installs project dependencies before authenticating to Azure. It retrieves named secrets with [`az keyvault secret show`](https://learn.microsoft.com/en-us/cli/azure/keyvault/secret#az-keyvault-secret-show), masks each retrieved value, exports it only in the deployment shell, and does not write it to `GITHUB_ENV`.

```yaml .github/workflows/deploy-checkly.yml theme={null}
name: Deploy Checkly

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    permissions:
      contents: read
      id-token: write
    env:
      AZURE_CORE_OUTPUT: none
    steps:
      - uses: actions/checkout@v7
        with:
          persist-credentials: false

      - uses: actions/setup-node@v7
        with:
          node-version: 22
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Sign in to Azure with OIDC
        uses: azure/login@v3
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

      - name: Load secrets and deploy
        shell: bash
        env:
          AZURE_KEY_VAULT: ${{ vars.AZURE_KEY_VAULT }}
          CHECKLY_ACCOUNT_ID: ${{ vars.CHECKLY_ACCOUNT_ID }}
        run: |
          set -euo pipefail

          get_secret() {
            az keyvault secret show \
              --vault-name "$AZURE_KEY_VAULT" \
              --name "$1" \
              --query value \
              --output tsv
          }

          mask_secret() {
            local value="${1//%/%25}"
            value="${value//$'\r'/%0D}"
            value="${value//$'\n'/%0A}"
            printf '::add-mask::%s\n' "$value"
          }

          CHECKLY_API_KEY="$(get_secret checkly-api-key)"
          CHECKLY_SECRET_PAYMENTS_API_KEY="$(get_secret payments-api-key)"
          CHECKLY_SECRET_PAYMENTS_ADMIN_TOKEN="$(get_secret payments-admin-token)"

          mask_secret "$CHECKLY_API_KEY"
          mask_secret "$CHECKLY_SECRET_PAYMENTS_API_KEY"
          mask_secret "$CHECKLY_SECRET_PAYMENTS_ADMIN_TOKEN"

          export CHECKLY_API_KEY
          export CHECKLY_SECRET_PAYMENTS_API_KEY
          export CHECKLY_SECRET_PAYMENTS_ADMIN_TOKEN

          npx checkly deploy --force
```

The job grants only `contents: read` and `id-token: write`. The latter lets `azure/login` request a GitHub OIDC token; it does not grant repository write access. `AZURE_CORE_OUTPUT: none` prevents accidental Azure CLI output, while `--output tsv` explicitly returns only each requested value to the shell.

<Warning>
  Do not print or persist fetched values. This example assumes token-like,
  single-line secret values.
</Warning>

## Rotate a secret

Rotating a value in Azure Key Vault does not automatically update the copy stored by Checkly. Run this trusted deployment workflow again after rotation. The next deployment fetches the current value returned by Key Vault and updates the scoped Checkly secret.
