Azure Powershell May 2016 Edition (Version 1.4.0) And Azure SDK 2.9 Changes–Obtaining Storage Account Keys Example
Hello Everyone, in this blog post I’m going to discuss some changes that happened in the Azure SDK and Azure PowerShell module that may be affecting you or will affect you if you update to the latest version.
The issue that affected me and probably will affect anyone that is deploying Azure Resource Manager Templates from Visual Studio or from PowerShell by using a Visual Studio Azure Resource Manger Solution. BTW, if you already updated your Azure SDK to 2.9 and created a new solution using this new SDK, you will not be affected.
This kind of solution/project in VS 2015 is really handy because it already gives us a deployment script that we can automate easily. Below we can see a solution and the description of what folder and script that gets created by using Azure SDK 2.8 or lower.
Note: these changes are not only limited to the scenario I just described, we had some major changes on the return values of some cmdlets from PowerShell module so you may be interested on checking out the whole article.
Visual Studio Resource Manager project created from Azure SDK 2.8 or lower:
Our focus is on Deploy-AzureResourceGroup.ps1 file that sits at the Scripts folder, as mentioned in the picture above this is the script that deploys your ARM Template.
The change that I’m describing happened on module Azure.Storage that is used by Azure Powershell cmdlets, to check if you’re using that particular version open an elevated PowerShell command prompt window and type:
Get-Module -ListAvailable -Name AzureRM.Storage
Look for the Version, and if it is 1.1.0 you are using the first version that changed some object properties.
To get the current version of the Azure Powershell module, you can run the same cmdlet but changing the module name to Azure, that will give you the following output:
This version 1.4.0 matches the version that appears in Control Panel:
The problem that affected me (and possibly others) is a change reflected on Get-AzureRmStorageAccountKey cmdlet. This cmdlet returns the storage keys that later can be used in other cmdlets, can be used on AzCopy tool (to copy blobs to and from Storage Accounts), etc. Up to version 1.3.4 of Azure Powershell module and Azure SDK 2.8 this was the way we worked with this cmdlet:
Obtaining the keys:
$storageKeys = Get-AzureRmStorageAccountKey -ResourceGroupName pmcrg01 -Name pmcstorage05
Keys returned object from that cmdlet:
Which means that the object contains two properties, Key1 and Key2 as we can see also in this cmdlet output:
$storageKeys | Get-Member
Some scripts and specially the one mentioned earlier in this blog use these keys in this way:
$storageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $storageAccountResourceGroupName -Name $storageAccountName).Key1
That line gets the Key1 property that will be used later. If we execute the same line using the latest version of Azure PowerShell we get a null result:
The question is, why do that happened? The output of Get-AzureRmStorageAccountKey has changed, let me repeat the Get-AzureRmStorageAccountKey cmdlet and output again to $storageKeys object without accessing the Key1 property directly and show the $storageKeys object:
Have you noticed the difference? They keys are there but presented differently. The StorageAccountKeys type have changed in the backend side:
So, how do I access the key 1 of my storage account now? We simply use the Value property that is an array with the key values so you can access the first key for example by executing the cmdlet in this way:
$storageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName pmcrg01 -Name pmcstorage05).Value[0]
Change from 0 to 1 to get access to the key 2.
Problem solved. But what if you want to keep compatibility with the old version of Azure Powershell and Azure SDK? You can use the following example:
$StorageAccountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $StorageAccountResourceGroupName -Name $StorageAccountName
if ($StorageAccountKeys.PSObject.Properties['Key1'] -eq $null)
{
$StorageAccountKey = $StorageAccountKeys.Value[0]
}
else
{
$StorageAccountKey = $StorageAccountKeys.Key1
}
This piece of PowerShell code will work on both. And to fix your pre Azure SDK 2.9 Visual Studio Azure Resource Group project, edit your Deploy-AzureResourceGroup.ps1 script and replace this line with that above sample final working code that keeps compatibility with old and new Azure PowerShell module and Azure SDK.:
$StorageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $StorageAccountResourceGroupName -Name $StorageAccountName).Key1
BTW, the changes are not only related to this particular storage account cmdlet, lets take a look on Get-AzureRmVM cmdlet, let me show how it was before and how it is now:
Before Azure PowerShell 1.4 – basically before it outputs JSON strings
That when accessed directly got converted to PS Objects
In this particular case the changes are harmful, we continue to access those properties in the same way. In the example below where I get the same virtual machine but now using 1.4.0 Azure PowerShell module:
As I mentioned,, if we used the same syntax that I used previously we get the same results:
Lastly but not less important, some cmdlets accepts a storage context object (Microsoft.WindowsAzure.Commands.Common.Storage.AzureStorageContext) instead of the keys, as an example we can create a blob container by simply obtaining the context object directly from a storage account by executing the following lines:
# Getting the storage account resource
$sa = Get-AzureRmStorageAccount -StorageAccountName pmcstorage05 -ResourceGroupName pmcrg01
# Creating a container using the SA directly or the context
$sa | New-AzureStorageContainer "testcontainer"
$sa.Context | New-AzureStorageContainer "testcontainer1"
Details of a AzureStorageContext object:
I would like you to have at least five takeaways from this:
- Always keep at least two computers to work with your deployments (through PowerShell or ARM Templates), a dev/test and a production one
- We have a monthly update cycle for Azure PowerShell and a little bit longer one for Azure SDK on Visual Studio but still, updates are frequently, so update the dev/test VM first and test your deployment scripts and templates, only after everything is tested or fixed update the production deployment computer (can be Azure VMs )
- You can uninstall the current Azure PowerShell module and install a previous version if need to but keep in mind that some changes may be something that comes from the backend and may not work as expected if using an outdated version of Azure SDK or Azure Powershelll module. All Azure PowerShell Modules are available on GitHub.
- Use storage AzureStorageContext as much as possible because is more efficient (you don’t need to obtain the keys for later on create the context object).
- Azure is always evolving for better.
Thanks, see you in the next blog post.
Paulo