---
title: "Rotate Azure AI Service Keys with Zero Downtime"
description: "Rotate Azure AI service keys safely with Azure Key Vault, refresh every application instance, and verify the switch before retiring the old key."
canonical: "https://adamtheautomator.com/azure-ai-service-key-rotation/"
---

# Rotate Azure AI Service Keys with Zero Downtime

> Rotate Azure AI service keys safely with Azure Key Vault, refresh every application instance, and verify the switch before retiring the old key.

Source: https://adamtheautomator.com/azure-ai-service-key-rotation/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Rotate Azure AI Service Keys with Zero Downtime](https://adamtheautomator.com/wp-content/uploads/publisher/4065d9c85b2b81f8a4cbc18a260aacb3/bd0d0a4c7f5b174292f649a4165c834b4b5d5342386221679e5f76c92d5d3524.webp)

# Rotate Azure AI Service Keys with Zero Downtime

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)30 October 20267 min. read

Categories: [Cloud](/category/cloud/)

Tags:[Azure](/tag/azure/)[Security](/tag/security/)[Azure CLI](/tag/azure-cli/)[PowerShell](/tag/powershell/)

Table of Contents

*   [Why Azure AI Gives You Two Keys](#why-azure-ai-gives-you-two-keys)
*   [Prerequisites](#prerequisites)
*   [Inventory Every Key Consumer](#inventory-every-key-consumer)
*   [Find Candidate Azure Resources](#find-candidate-azure-resources)
*   [Record Refresh Behavior](#record-refresh-behavior)
*   [Establish the Baseline and Rotation State](#establish-the-baseline-and-rotation-state)
*   [Regenerate the Standby Key](#regenerate-the-standby-key)
*   [Use Azure CLI](#use-azure-cli)
*   [Use Azure PowerShell](#use-azure-powershell)
*   [Publish the New Key and Refresh Every Instance](#publish-the-new-key-and-refresh-every-instance)
*   [Verify the Switch Before Retiring Key 1](#verify-the-switch-before-retiring-key-1)
*   [Test the Production Path](#test-the-production-path)
*   [Check Every Instance and 401](#check-every-instance-and-401)
*   [Rotate Key 1 and Preserve a Standby](#rotate-key-1-and-preserve-a-standby)
*   [Roll Back Before the Point of No Return](#roll-back-before-the-point-of-no-return)
*   [Automate the Sequence and Work Toward Keyless](#automate-the-sequence-and-work-toward-keyless)
*   [Preserve the Rotation Gates](#preserve-the-rotation-gates)
*   [Replace Shared Keys](#replace-shared-keys)

Would you regenerate Key 1 while half your production instances are still using it? Let’s say one worker refreshed its Azure OpenAI credential, three web instances cached the old value, and a forgotten script still reads an environment variable. Regenerating that key turns the forgotten consumers into a stream of `401` errors.

The safe rotation uses both Azure AI service keys as an active and standby pair. Azure Key Vault can publish a replacement, but it cannot prove that every process picked it up. Long-running workers can keep the old credential even after deployment reports green, so keep the former active key valid until telemetry accounts for every consumer.

## Why Azure AI Gives You Two Keys

Azure AI resources expose Key 1 and Key 2 so you can replace one credential while the other continues serving requests. The [Microsoft key rotation procedure](https://docs.azure.cn/en-us/ai-services/rotate-keys) states, “This is a necessary step because once a key is regenerated, the older version of that key stops working immediately.” Any client holding the regenerated value begins receiving `401 access denied` errors.

Treat the two values as active and standby credentials. They authenticate to the same resource endpoint and usually have the same data-plane access. The labels do not make Key 1 safer or more important.

| Rotation State | Application Uses | Safe Credential to Regenerate |
| --- | --- | --- |
| Starting state | Key 1 | Key 2 |
| Verification state | New Key 2 | None |
| Completed state | New Key 2 | Key 1 |

* * *

_**WARNING: Never regenerate both keys together. Doing so removes the overlap that makes a zero-downtime rotation possible.**_

* * *

## Prerequisites

Use a controlled runner with Azure AI and secret-store access. The examples were syntax-checked with [Azure CLI 2.85.0](https://pypi.org/project/azure-cli/2.85.0), PowerShell 7.6.1, Az.CognitiveServices 1.16.0, Az.KeyVault 6.4.3, and resource-graph extension 2.1.1.

*   An authenticated Azure CLI or PowerShell session with key-regeneration permission. [Cognitive Services Contributor](https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/role-based-access-control/built-in-roles/ai-machine-learning.md#cognitive-services-contributor) can manage keys, though a resource-scoped custom role is tighter.
    
*   An Azure Key Vault secret that applications read through a managed identity. Give the rotation runner secret-write permission and each application secret-read permission.
    
*   A health check or synthetic inference request plus application telemetry that exposes `401` responses, availability, and instance identity.
    
*   A change window long enough to cover every credential cache and at least one normal traffic period.
    

If you cannot prove which key production uses, stop before regeneration. An unverified maintenance change can break production.

## Inventory Every Key Consumer

Your [consumer inventory](https://csrc.nist.gov/pubs/sp/800/57/pt2/r1/final) is the real prerequisite. Search deployment manifests, Key Vault references, CI/CD variables, application settings, scheduled jobs, local scripts, API gateways, and third-party integrations for the Azure AI endpoint and secret name.

### Find Candidate Azure Resources

Use Azure Resource Graph to find resource properties that mention the account or secret. Set the same identifiers your rotation will use.

```bash
AI_ACCOUNT="<azure-ai-account-name>"
SECRET_NAME="azure-ai-api-key"

INVENTORY_QUERY="
resources
| where tostring(properties) contains '$AI_ACCOUNT'
    or tostring(properties) contains '$SECRET_NAME'
| project name, type, resourceGroup, subscriptionId, location
| order by type asc, name asc
"

az graph query -q "$INVENTORY_QUERY" --first 1000 --output table
```

Each row gives you a resource to inspect and an owner to contact. Resource Graph does not expose every application setting or off-Azure consumer. Treat an empty result as the start of the remaining search across those systems.

### Record Refresh Behavior

*   Record each consumer’s owner, runtime, secret source, refresh mechanism, and health signal.
    
*   Mark whether the process reads secrets at startup, polls Key Vault, or supports an explicit refresh.
    
*   Find every scaled instance and long-running worker. One stale pod is enough to keep the former key alive.
    
*   Remove direct key copies from source repositories and pipeline variables after moving them to the central secret.
    

The inventory should resolve to one secret name and one active key label. Separate application copies leave you with multiple secrets to audit and rotate.

* * *

_**PRO TIP: Tag the Key Vault secret with `CredentialId=Key1` or `CredentialId=Key2`. Your runbook can then select the standby credential without comparing secret values.**_

* * *

## Establish the Baseline and Rotation State

Record the Azure AI account, resource group, Key Vault, secret name, active key label, and application health before changing anything. The Azure CLI key commands accept only `Key1` or `Key2` for regeneration.

```bash
AI_ACCOUNT="<azure-ai-account-name>"
AI_RESOURCE_GROUP="<azure-ai-resource-group>"
KEY_VAULT="<key-vault-name>"
SECRET_NAME="azure-ai-api-key"
ACTIVE_KEY="Key1"
STANDBY_KEY="Key2"
SYNTHETIC_URL="https://<production-app>/health/azure-ai"
LOG_WORKSPACE_ID="<log-analytics-workspace-id>"
```

Run the application’s normal health check and a synthetic Azure AI request now. Save the success rate, `401` count, latency, deployment revision, and instance count in the change record. [Baseline data](https://sre.google/sre-book/testing-reliability/) gives the later verification gate something better than optimism to compare against.

The following diagram should make the safe sequence visible before anyone runs a mutating command.

![Safe key rotation sequence](https://adamtheautomator.com/wp-content/uploads/publisher/93714752d48a78117da035378a41265fbeedc24d749bdc92c4b77c3158ba5465.png)

## Regenerate the Standby Key

Regenerate only the credential that no application currently uses. The operation changes the selected value immediately and leaves the endpoint, deployments, and other key in place. Run it from a protected administration host because the returned object contains secret material.

* * *

_**WARNING: The next commands invalidate the old Key 2 value. Confirm that `STANDBY_KEY` is absent from every production consumer before running them.**_

* * *

### Use Azure CLI

The Azure CLI can regenerate Key 2 and capture the new value without printing it to the terminal. The `regenerate` command returns both keys, so query only the value you need.

```bash
NEW_STANDBY_KEY="$(az cognitiveservices account keys regenerate \
  --name "$AI_ACCOUNT" \
  --resource-group "$AI_RESOURCE_GROUP" \
  --key-name "$STANDBY_KEY" \
  --query key2 \
  --output tsv)"
```

Run the command from a dedicated administration host to limit same-host process inspection.

### Use Azure PowerShell

PowerShell can keep the regenerated value in memory and pass it to Key Vault as a `SecureString`. The [`New-AzCognitiveServicesAccountKey` cmdlet](https://learn.microsoft.com/en-us/powershell/module/az.cognitiveservices/new-azcognitiveservicesaccountkey?view=azps-16.4.0) accepts `Key1` or `Key2`.

```powershell
$newKeys = New-AzCognitiveServicesAccountKey `
  -ResourceGroupName '<azure-ai-resource-group>' `
  -Name '<azure-ai-account-name>' `
  -KeyName Key2 `
  -Force

$secretValue = ConvertTo-SecureString $newKeys.Key2 -AsPlainText -Force

Set-AzKeyVaultSecret `
  -VaultName '<key-vault-name>' `
  -Name 'azure-ai-api-key' `
  -SecretValue $secretValue `
  -Tag @{ CredentialId = 'Key2' } | Out-Null

Remove-Variable newKeys, secretValue
```

The cmdlet returns both values, so never pipe its output to a build log.

## Publish the New Key and Refresh Every Instance

Store the regenerated Key 2 as a new version of the existing secret. The Azure CLI example also removes the value from the shell after Key Vault accepts it.

```bash
az keyvault secret set \
  --vault-name "$KEY_VAULT" \
  --name "$SECRET_NAME" \
  --value "$NEW_STANDBY_KEY" \
  --tags CredentialId=Key2 \
  --output none

unset NEW_STANDBY_KEY
```

Publishing a new secret version does not prove that running processes consumed it. [App Service Key Vault references](https://techcommunity.microsoft.com/blog/appsonazureblog/app-service-environment-ase-v3-key-vault-reference-behavior/3191780), for example, cache versionless references and normally refresh them within 24 hours. Use the documented refresh API, your application’s dynamic configuration signal, or a rolling restart that keeps healthy instances online.

```bash
APP_ID="$(az webapp show --name "$APP_NAME" \
  --resource-group "$APP_RESOURCE_GROUP" --query id -o tsv)"

az rest --method post \
  --uri "https://management.azure.com${APP_ID}/config/configreferences/appsettings/refresh?api-version=2022-03-01"
```

Repeat the refresh for every app, slot, worker, and region in the inventory.

## Verify the Switch Before Retiring Key 1

Verification must prove application behavior, instance coverage, and error health. Azure OpenAI monitoring requires diagnostic settings before resource logs are available for queries, so configure the logs before the change window.

| Gate | Evidence Required | Failure Response |
| --- | --- | --- |
| Synthetic request | Successful call through the production path | Restore Key 1 configuration |
| Instance coverage | Every revision and worker refreshed | Refresh or roll the stale instance |
| Authentication health | No new `401` spike against baseline | Pause the rotation |
| Service health | Availability and latency remain inside existing thresholds | Investigate before regeneration |

### Test the Production Path

Call the same application endpoint your external monitor uses. The endpoint must perform a small Azure AI request through the production configuration path.

```bash
curl --fail --silent --show-error \
  --output /dev/null \
  --write-out 'HTTP %{http_code}\n' \
  "$SYNTHETIC_URL"
```

The expected output is `HTTP 200`. Any timeout, non-2xx response, or application error puts the rotation on HOLD and sends the application back to Key 1.

### Check Every Instance and `401`

Query the workspace-backed [`AppRequests` table](https://raw.githubusercontent.com/MicrosoftDocs/azure-monitor-docs/main/articles/azure-monitor/reference/tables/apprequests.md) for requests from each reporting instance.

```bash
az monitor log-analytics query \
  --workspace "$LOG_WORKSPACE_ID" \
  --analytics-query '
AppRequests
| where TimeGenerated > ago(30m)
| summarize Requests=count(),
            Unauthorized=countif(ResultCode == "401"),
            LastSeen=max(TimeGenerated)
  by AppRoleName, AppRoleInstance
| order by AppRoleName asc, AppRoleInstance asc
' \
  --output table
```

GO requires one fresh row for every expected app instance and worker, with `Unauthorized` equal to `0`. Missing instances or any new `401` count means HOLD. Keep the gate open through one complete secret refresh cycle and a representative traffic period. Five calm minutes mean very little if the nightly worker runs at 2 a.m.

The image below should show the telemetry an operator checks before approving the irreversible step.

![Key rotation telemetry](https://adamtheautomator.com/wp-content/uploads/publisher/e2c20f7ec787174d401dcf10af1c7bea8863f56e65e62433841df890c93b6816.png)

## Rotate Key 1 and Preserve a Standby

Only regenerate Key 1 after the verification gate proves every consumer uses the new Key 2. The Azure AI account management API’s [regeneration parameters accept Key1 or Key2](https://azuresdkdocs.z19.web.core.windows.net/java/azure-resourcemanager-cognitiveservices/1.5.0-beta.2/com/azure/resourcemanager/cognitiveservices/models/RegenerateKeyParameters.html).

```bash
az cognitiveservices account keys regenerate \
  --name "$AI_ACCOUNT" \
  --resource-group "$AI_RESOURCE_GROUP" \
  --key-name Key1 \
  --output none
```

Leave applications on Key 2. Key 1 is now the fresh standby for the next cycle, which avoids an unnecessary second application switch. Update the change record with the rotation time, resource ID, active key label, standby key label, secret version, runner identity, verification evidence, and any exceptions.

Never record either key value. Your audit trail must prove what changed and who changed it. The credential itself is not a souvenir.

## Roll Back Before the Point of No Return

Rollback remains simple while the former active Key 1 is still valid. Republish the previous Key Vault secret version, refresh every application instance, and rerun the baseline health check. Fix the failed Key 2 refresh before attempting another switch.

Regenerating Key 1 permanently invalidates its old value, so the rollback window ends at that step. After that point, recovery moves forward with the valid new Key 2 or freshly generated Key 1. Microsoft’s dual-credential rotation tutorial follows the same safety rule by waiting for applications to consume the latest secret before rotating the alternate credential.

If you suspect a compromise, contain it first. Move known consumers to the standby key, [regenerate the exposed value immediately](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html#273-revocation), and treat unknown consumers as incident scope. If containment requires breaking an untracked script, accept the `401` and fix the inventory after the credential is dead.

## Automate the Sequence and Work Toward Keyless

Automation is safe only when its code enforces every manual gate you just used.

### Preserve the Rotation Gates

Run the workflow in Azure Functions or an Azure Automation runbook. Give its managed identity resource-scoped permission to regenerate the Azure AI keys, write the Key Vault secret, and emit logs. The workflow must stop when refresh coverage or health checks fail.

Do not confuse an API key stored as a Key Vault _secret_ with a Key Vault cryptographic _key_. Key Vault autorotation can create new cryptographic key versions by policy. Rotating an Azure AI API secret still requires custom logic that changes the Azure AI resource and refreshes its consumers.

### Replace Shared Keys

The better end state removes shared secrets. Where the service supports it, use [Microsoft Entra ID keyless connections](https://devblogs.microsoft.com/azure-sql/go-passwordless-when-calling-azure-openai-from-azure-sql-using-managed-identities/) and give each workload a managed identity. After every consumer succeeds with tokens, [disable access-key authentication](https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.AI.DisableLocalAuth/) by setting `properties.disableLocalAuth` to `true`. Verify that a worker using the old key receives an authentication failure.

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fazure-ai-service-key-rotation%2F&text=Rotate%20Azure%20AI%20Service%20Keys%20with%20Zero%20Downtime)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fazure-ai-service-key-rotation%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fazure-ai-service-key-rotation%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/publisher/3ec5d9c85b2b81178e9ac5b3109d7e40/a17dc7e937f939221a5e25aadd5f5749c67f0e262d984e9b032a40d083fe81f4.png)

### [Find Expiring App Registration Secrets Before an Outage](/find-expiring-app-registration-secrets/)

Report expiring app registration secrets and certificates with PowerShell and Microsoft Graph, route each one to its owner, and rotate it safely.

![](https://adamtheautomator.com/wp-content/uploads/publisher/2e05d9c85b2b819f9960cc3af514f9a0/4edae5c1327c7aaa91f7cd7fb033f216b4ba0310906a424978cd0f2b4bca4345.webp)

### [Azure Data Sovereignty Guardrails: Cut Jurisdictional Risk](/azure-data-sovereignty-guardrails/)

Master Azure data sovereignty with residency policies, encryption keys, operator oversight, and compliance controls to prevent jurisdictional data access.

![](https://adamtheautomator.com/wp-content/uploads/2026/08/featured_image-3.webp)

### [Build an Azure Home Lab for Certs Without Overspending](/azure-home-lab-certification-practice/)

Build a nested Azure Hyper-V home lab with budget alerts, a domain controller, and Azure Arc mapped to AZ-900, AZ-104, and AZ-305 exams.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
