Azure Storage Account Keys Automatic Rotation

Azure Infrastructure


A new feature called Managed Storage Account Keys popped up last month that promises to make rotating Azure Storage Account Keys easier. I have to give a ton of credit to my colleague Dmitriy S. who helped with a lot of the discovery and troubleshooting.

Why rotate?

It is recommended to periodically rotate your Storage Account Keys. Storage Account Keys give the holder full access to your storage account and all data within it. Rotating the keys periodically help mitigate the risk of unauthorized access.

The old way

Previously, we had this article called “Set up Azure Key Vault with end-to-end key rotation and auditing,” which describes automation storage account key rotation. While that will still work, it’s very complex to setup, involves using an Automation Account and Runbook, Functions, and a Logic App. We now have a much easier way!

The new way

Using Managed Storage Account Keys, we can easily set up automatic key rotation by just deploying a Storage Account and a Key Vault. The article called Azure Key Vault Storage Account Keys describes the feature and developer experience. However, the “Getting started” section was a bit confusing, incomplete and it looks like it contains some errors. So, let’s go through it together.

Set-up permissions

I’m going to assume you have a Key Vault and Storage Account already and they have registered providers. The first thing we need is the ObjectId of Key Vault. Note, we need the ObjectId of the Key Vault service (“first party identity”), NOT your specific Key Vault. This object ID is different for each tenant. The instructions on the official documentation say:

Get-AzureRmADServicePrincipal -SearchString "AzureKeyVault"

However, that didn’t work for one of my tenants (which was a Enterprise Enrollment). A more accurate way to get the ObjectId is to first login using “Connect-AzureAD” and then using the following command:

$servicePrincipal = Get-AzureADServicePrincipal -Filter "AppId eq 'cfa8b339-82a2-471a-a3c9-0fc0be7a4093'"

This won’t work on MSDN Azure subscriptions, but neither did the first way. I’ve found that the AppId above is consistent across all of my tenants but could be different for AzureChina, AzureGov, etc. Next, we need to assign the “Storage Account Key Operator Service Role” role which gives the Key Vault list and regenerate permissions:

$storageAccountId = (Get-AzureRmStorageAccount -StorageAccountName wspladiag02 -ResourceGroupName wspla-rg).Id
New-AzureRmRoleAssignment -ObjectId $servicePrincipal.ObjectId -RoleDefinitionName 'Storage Account Key Operator Service Role' -Scope $storageAccountId

Storage account onboarding

The official documentation is unclear on the next steps, in my opinion. But, here’s how we set up daily key rotation using PowerShell. First, we need to make sure we (user performing operation) has “set” operation allowed within the Key Vault’s access policies. If you don’t, you’ll get this error later on:

Add-AzureKeyVaultManagedStorageAccount : Operation "set" is not allowed by vault policy

So to prevent that, let’s add the current user:

$keyVaultName = "kv-infra-secrets"
$keyVaultResourceGroupName = "RG-Infrastructure"
Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ResourceGroupName $keyVaultResourceGroupName -UserPrincipalName "" -PermissionsToStorage set, get, regeneratekey

I gave the user get and regeneratekey also but those aren’t required unless you want to use other commands. Now let’s create a TimeSpan object:

$regenerationPeriod = [System.Timespan]::FromDays(1)

Next, we use a new command to add the Storage Account as “Managed” by this Key Vault. If you don’t have this command, remember to update to the latest Azure PowerShell.

$parameters = @{
VaultName = $keyVaultName
AccountResourceId = $storageAccountId
AccountName = "mystoragetest1"
ActiveKeyName = "key1"
RegenerationPeriod = $regenerationPeriod
Add-AzureKeyVaultManagedStorageAccount @parameters

That’s it! The Storage Account Key will be rotated on the schedule you set up. You can verify everything by using Get-AzureKeyVaultManagedStorageAccount. You can also regenerate the keys manually using Update-AzureKeyVaultManagedStorageAccountKey if you don’t want to wait.

3 comments… add one
  • Micah J Sep 7, 2017

    Great article, hats off to your and your colleagues on this as $MS documentation was a bit pants and I was struggling.

    One minor update, is that to get-azurekeyvaultManagedStorageAccount you need to add ‘list’ to your permissions.

    Set-AzureRmKeyVaultAccessPolicy -VaultName $keyVaultName -ResourceGroupName $keyVaultResourceGroupName -UserPrincipalName “” -PermissionsToStorage set, get, regeneratekey

    thanks again!!

  • Ahmadreza Khadem Sep 11, 2017

    Thanks very helpful

  • Dmitriy Shmuylovskiy Nov 15, 2017

    Thanks Wahid, great article.

    What I’ve mentioned howver that “-userPrinicalName” does not work in our case. I’m using “-objectID” instead and retrieving this value with this contract:

    (Get-AzureRmADUser | where-object {$_.UserPrincipalName -like “$userServicePrincialName*”}).id.guid

Leave a Comment

%d bloggers like this: