Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The best way to authenticate to Azure services is with a managed identity, but some scenarios still require access keys or passwords. Rotate those credentials often to reduce the impact of a leak.
This tutorial shows how to automate periodic secret rotation for databases and services that use two sets of authentication credentials. For an overview of autorotation across different asset types, see Understanding autorotation in Azure Key Vault.
Specifically, this tutorial rotates Azure Storage account keys that are stored in Azure Key Vault as secrets. It uses a function that's triggered by an Azure Event Grid notification.
Important
For Azure Storage, prefer Microsoft Entra ID authorization with a managed identity over shared account keys. Where compliance allows, disable Shared Key authorization on the storage account and remove the need for key rotation entirely. Use the pattern in this tutorial only when a workload requires a storage account key or a connection string.
Here's the rotation solution described in this tutorial:

In this solution, Azure Key Vault stores each storage account access key as a version of the same secret, alternating between the primary and secondary key in successive versions. When one access key is stored as the latest version of the secret, the alternate key is regenerated and added to Key Vault as the new latest version. This design gives the application a full rotation cycle to pick up the newly regenerated key.
- Thirty days before the expiration date of a secret, Key Vault publishes the near-expiry event to Event Grid.
- Event Grid checks the event subscriptions and uses HTTP POST to call the function app endpoint subscribed to the event.
- The function app identifies the alternate key (not the latest one) and calls the storage account to regenerate it.
- The function app adds the regenerated key to Azure Key Vault as the new version of the secret.
Prerequisites
- An Azure subscription. Create one for free.
- Azure Cloud Shell. This tutorial uses portal Cloud Shell with the PowerShell environment.
- An Azure key vault.
- Two Azure storage accounts.
Note
Rotating a shared storage account key revokes any account-level shared access signature (SAS) generated from that key. After rotation, regenerate account-level SAS tokens to avoid disruption to applications.
If you don't have an existing key vault and two storage accounts, use this deployment link:
Under Resource group, select Create new. Name the group vault rotation and then select OK.
Select Review + create.
Select Create.

You now have a key vault and two storage accounts. Verify this setup in the Azure CLI or Azure PowerShell:
az resource list -o table -g vaultrotation
The result looks similar to the following output:
Name ResourceGroup Location Type Status
----------------------- -------------------- ---------- --------------------------------- --------
vaultrotation-kv vaultrotation westus Microsoft.KeyVault/vaults
vaultrotationstorage vaultrotation westus Microsoft.Storage/storageAccounts
vaultrotationstorage2 vaultrotation westus Microsoft.Storage/storageAccounts
Create and deploy the key rotation function
Next, create a function app with a system-assigned managed identity along with the other required components, and deploy the rotation function for the storage account keys.
The rotation function requires the following components and configuration:
- An Azure App Service plan.
- A storage account to manage function app triggers.
- An Azure role assignment that lets the function app access secrets in the key vault.
- The Storage Account Key Operator Service Role assigned to the function app so it can access storage account access keys.
- A key rotation function with an Event Grid trigger and an HTTP trigger (for on-demand rotation).
- An Event Grid event subscription for the SecretNearExpiry event.
Select the Azure template deployment link:
In the Resource group list, select vaultrotation.
In Storage Account RG, enter the name of the resource group where the storage account is located. Keep the default
[resourceGroup().name]if the storage account is in the same resource group as the rotation function.In Storage Account Name, enter the name of the storage account whose access keys you want to rotate. Keep the default
[concat(resourceGroup().name, 'storage')]if you use the storage account from Prerequisites.In Key Vault RG, enter the name of the resource group where the key vault is located. Keep the default
[resourceGroup().name]if the key vault is in the same resource group as the rotation function.In Key Vault Name, enter the key vault name. Keep the default
[concat(resourceGroup().name, '-kv')]if you use the key vault from Prerequisites.In App Service Plan Type, select the hosting plan. Premium Plan is required only when the key vault is behind a firewall.
In Function App Name, enter the function app name.
In Secret Name, enter the secret name that stores the access keys.
In Repo URL, enter the GitHub location of the function code:
https://github.com/Azure-Samples/KeyVault-Rotation-StorageAccountKey-PowerShell.git.Select Review + create.
Select Create.

After the deployment completes, you have a storage account, a server farm, a function app, and an Application Insights resource:

Note
This ARM template uses App Service source-control (Kudu) deployment to pull the function code from GitHub. For a production workload, we recommend a package-based deployment such as func azure functionapp publish or zip deploy with WEBSITE_RUN_FROM_PACKAGE instead. If the deployment fails, select Redeploy to retry.
Deployment templates and code for the rotation function are in Azure-Samples/KeyVault-Rotation-StorageAccountKey-PowerShell.
Add the storage account access keys to Key Vault secrets
First, assign yourself the Key Vault Secrets Officer role so that you can manage secrets in the vault:
az role assignment create --role "Key Vault Secrets Officer" --assignee <email-address-of-user> --scope /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/vaultrotation-kv
You can now create a secret whose value is a storage account access key. Along with the value, add the storage account resource ID, secret validity period, and key ID as tags so that the rotation function can regenerate the key in the storage account.
Determine the storage account resource ID. It's the id property:
az storage account show -n vaultrotationstorage
List the storage account access keys so you can get the key values:
az storage account keys list -n vaultrotationstorage
Add the secret to the key vault with a validity period of 60 days and (for demonstration) an expiration date of tomorrow to trigger rotation immediately. Run this command with your retrieved values for key1Value and storageAccountResourceId:
tomorrowDate=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%M:%SZ")
az keyvault secret set --name storageKey --vault-name vaultrotation-kv --value <key1-value> --tags "CredentialId=key1" "ProviderAddress=<storage-account-resource-id>" "ValidityPeriodDays=60" --expires $tomorrowDate
This secret triggers a SecretNearExpiry event within several minutes, which in turn triggers the function to rotate the secret with an expiration set 60 days out. In that configuration, the SecretNearExpiry event fires every 30 days (30 days before expiry), and the rotation function alternates between key1 and key2.
Verify that access keys regenerated by retrieving the storage account key and the Key Vault secret, then comparing them.
Use this command to get the secret information:
az keyvault secret show --vault-name vaultrotation-kv --name storageKey
Notice that CredentialId is updated to the alternate keyName and that value is regenerated:

Retrieve the access keys to compare the values:
az storage account keys list -n vaultrotationstorage
Notice that the key value matches the secret in the key vault:

Use an existing rotation function for multiple storage accounts
You can reuse the same function app to rotate keys for more than one storage account.
To add another storage account's keys to an existing rotation function, you need:
- The Storage Account Key Operator Service Role assigned to the function app so it can access storage account access keys.
- An Event Grid event subscription for the SecretNearExpiry event.
Select the Azure template deployment link:
In the Resource group list, select vaultrotation.
In Storage Account RG, enter the name of the resource group where the storage account is located. Keep the default
[resourceGroup().name]if the storage account is in the same resource group as the rotation function.In Storage Account Name, enter the name of the storage account whose access keys you want to rotate.
In Key Vault RG, enter the name of the resource group where the key vault is located. Keep the default
[resourceGroup().name]if the key vault is in the same resource group as the rotation function.In Key Vault Name, enter the key vault name.
In Function App Name, enter the function app name.
In Secret Name, enter the secret name that stores the access keys.
Select Review + create.
Select Create.

Add storage account access key to Key Vault secrets
Determine the storage account resource ID. You can find this value in the id property.
az storage account show -n vaultrotationstorage2
List the storage account access keys so you can get the key2 value:
az storage account keys list -n vaultrotationstorage2
Add the secret to the key vault with a validity period of 60 days and (for demonstration) an expiration date of tomorrow to trigger rotation immediately. Run this command with your retrieved values for key2Value and storageAccountResourceId:
tomorrowDate=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%M:%SZ")
az keyvault secret set --name storageKey2 --vault-name vaultrotation-kv --value <key2-value> --tags "CredentialId=key2" "ProviderAddress=<storage-account-resource-id>" "ValidityPeriodDays=60" --expires $tomorrowDate
Use this command to get the secret information:
az keyvault secret show --vault-name vaultrotation-kv --name storageKey2
Notice that CredentialId is updated to the alternate keyName and that value is regenerated:

Retrieve the access keys to compare the values:
az storage account keys list -n vaultrotationstorage2
Notice that the key value matches the secret in the key vault:

Disable rotation for a secret
To disable rotation for a secret, delete the Event Grid subscription for that secret. Use the Azure PowerShell Remove-AzEventGridSubscription cmdlet or the Azure CLI az eventgrid event-subscription delete command.
Use AI to customize the rotation function for other services
This tutorial demonstrates secret rotation for Azure Storage accounts, but you can adapt the rotation function for other Azure services that use dual credentials. GitHub Copilot can help you modify the PowerShell rotation function code to work with your service.
I'm using the Azure Key Vault dual-credential secret rotation tutorial for Storage accounts. Help me modify the PowerShell rotation function to work with Azure Cosmos DB instead. The function should:
1. Connect to Cosmos DB and regenerate the secondary key
2. Store the new key in Key Vault as a new secret version
3. Alternate between primary and secondary keys on each rotation
Show me the changes needed to the PowerShell function code, including the correct Cosmos DB PowerShell cmdlets.
GitHub Copilot is powered by AI, so surprises and mistakes are possible. For more information, see Copilot FAQs.
