Learn by example: Enable Azure VM Boot Diagnostics leveraging Managed Storage Account using ARMClient Tool

Learn by example: Enable Azure VM Boot Diagnostics leveraging Managed Storage Account using ARMClient Tool

Using a Microsoft Managed Storage Account when enabling Azure VM Boot Diagnostics feature is an advantage to the customers, where they eliminate one more Storage Account that they need to manage. That’s awesome! Taking in consideration that the amount of data stored is very minimal, two files per VM. But still there is Storage Account to manage, not to mention the amount of those files that are being created and no one cleans them after the VM is deleted!

Leveraging a managed Storage Account for Boot Diagnostics data can be easily achieved when creating new VMs in Azure using an ARM template for example, because it can be declared in the template itself (just make sure the API version for the Microsoft.Compute/virtualMachines resource is “2020-06-01”), see below:

                "diagnosticsProfile": {
                    "bootDiagnostics": {
                        "enabled": true
                    }
                }

Basically, it is as we used to do it before, but without defining storageUri property. That’s actually the trick (beside the API version).

Now, the problem is what if you already have VMs deployed in Azure. How to switch them to use a Managed Storage Account?! The official documentation says it’s only possible through the portal. “Boot diagnostics using a manage storage account can currently only be applied through the Azure portal.” That is a solution, but it’s not scalable! How can we enable it for a group of VMs in one hit?

Eventually, there will be support to do this through various mechanisms such as PowerShell and Azure CLI. But, what about now? Can we create a scalable solution? Well! What if we think out of the box! Can we replace the whole properties of bootDiagnostics section in ARM and remove storageUri property. The answer, yes we can! And that’s what happens when you try to change the setting through the portal. Do you want to see that in action? Sure, click F12 and look at the request that’s being sent to ARM REST API when you click the Save button.

To simulate the same process and make it scalable for more VMs, I used a tool called ARMClient (it’s part of Kudu which is in the core of Azure App Service), I recommend that tool when making REST API calls to ARM because it simply makes authentication straight forward and managing access tokens something beyond your worries 😉

Let’s take a look at the script (running from PowerShell environment):

# https://github.com/projectkudu/ARMClient
#Login to Azure
ARMClient.exe login

#Setting parameters
[string] $enableBootDiagnostics = $true
$subscription = '<Subscription ID'
$resourceGroup = '<Resource Group>'
$vmsInResourceGroupId = "/subscriptions/$subscription/resourceGroups/$resourceGroup/providers/Microsoft.Compute/virtualMachines"

#Retrieving VMs in the Resource Group
$response = ([string] (armclient GET "$($vmsInResourceGroupId)?api-version=2019-12-01")) | ConvertFrom-Json
#$response.value[3].properties.diagnosticsProfile.bootDiagnostics

#Looping through the VMs and setting diagnosticsProfile to use Microsoft Managed Storage Account by removing the storageUri property
$response.value  | % {
armclient PATCH "$($_.Id)?api-version=2020-06-01" "{properties:{diagnosticsProfile:{bootDiagnostics:{enabled:$($enableBootDiagnostics.ToLower())}}}}"
}

So far, it’s not feasible to do it this through Azure Policy because the bootDiagnostics aliases are not part of the modifiable set of aliases in the modify action type. However, when this becomes possible. I recommend going the Azure Policy method, as it’s cleaner and way more scalable.

To sum up, the idea here was to show how we can make operations possible in Azure even if there is no way to do it in PowerShell, Azure CLI, …etc, until it becomes possible. Thanks to the Azure Resource Manager API, which is the heart of Azure!

Learn by example: Using Azure Managed Identity to access Azure Storage Account through PowerShell

Learn by example: Using Azure Managed Identity to access Azure Storage Account through PowerShell

In many occasions you will face a need to use PowerShell from an Azure VM (or VM Scale Set) to connect to an Azure Storage Account to store or to retrieve some data which most probably could be a blob within a container. At the same time, you’d like to store blobs securely and avoid having public accessible blobs. You are more likely want to avoid the need to create Shared Access Signatures (SAS tokens), or even expose and manage the Storage Account Access Keys. Well! The solution to that is through authenticating to the Storage Account using Azure Managed Identities.

There are two two types of Azure Managed Identities (an Azure artifact/resource that is backed with autonomous Azure AD Service Principal that is employing self-managed credentials):
System assigned managed identity (SAMI): It’s a mapped identity to the resource (it’s 1-1 relationship), where the lifecycle of the identity is tied to the lifecycle of the Azure resource itself (CSP responsibility).
User assigned managed identity (UAMI): It’s an independent identity that can be assigned to multiple Azure resources (it’s 1-∞ relationship), making it flexible. However, the lifecycle of the identity is managed separately from the resources (Customer responsibility).

In this post, I will demonstrate with user assigned managed identity as it has various implementation scenarios. Before you start make sure that you have created a USMI and assigned it to a VM in Azure.

In the example script-snippet below, you’ll notice the following

  1. The PowerShell modules needed to run the used cmdlets are the following. Make sure you install them wherever you’re running the script:
  2. Using parameter -Identity in Connect-AzAccount is the secret that allows us to leverage managed identities. Providing the other parameter -AccountId is necessary only when there are more than one Managed Identity linked to the Azure resource, to solve the confusion. Otherwise the first managed identity in the list will be selected by default. In other words, it’s not necessary if you are using only one user assigned managed identity or if you are using system assigned managed identity. More here.
  3. The cmdlet Get-AzUserAssignedIdentity was used to retrieve the ClientId of the managed identity. If you provide that value directly, then this line won’t be necessary. Also, you would need to assign the managed identity Reader access over the resource group it belongs to.
  4. When creating the Storage Account context, we needed to use the parameter –UseConnectedAccount to authenticate using OAuth Protocol. More here. After creating the context, then you’ll continue interacting with Azure Storage Container similar as you do typically.
  5. The permissions required to allow the managed identity to create a container and store a blob inside is Storage Blob Data Contributor.
$resourceGroupName = '<resourceGroupName>'
$managedIdentityName = '<managedIdentityName>'
$storageAccountName = '<storageAccountName>'
$newContainerName = '<newContainerName>'
$uploadFilePath =  '<uploadFilePath i.e. c:\temp\image.png>'
$fileName = $uploadFilePath.Split('\')[-1]

#the following couple lines are optional if you are providing the ClientID directly
Connect-AzAccount -Identity
$managedIdentity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroupName -Name $managedIdentityName

#using -AccountId is only necessary when you have multiple managed identities linked to the Azure resource (i.e. Storage Account)
Connect-AzAccount -Identity -AccountId $managedIdentity.ClientId

$storageAccount = New-AzStorageContext -StorageAccountName $storageAccountName –UseConnectedAccount

$container = New-AzStorageContainer -Name $newContainerName -Context $storageAccount.Context -Permission blob

Set-AzStorageBlobContent -File $uploadFilePath -Container $container.Name -Blob $fileName -Context $storageAccount.Context

As you noticed from the script-snippet above that there was no credentials/passwords/passphrases/secrets/keys/certificates exposed. That’s a big advantage of using managed identities, especially when storing scripts in code repository 😉 Think about it as the passwordless infrastructure experience. That’s the beauty of Azure Managed Identities!

As a side note, the same approach is achievable through Azure CLI. You’ll just need to use the equivalent commands.

I hope this was a good introduction for you to start leveraging managed identities in your scripts. Cheers 😃