Deployment of custom scripts via a storage account with user-assigned managed identity

For the provisioning of session hosts, it can be useful to copy files from a storage account that are required during provisioning or operation. However, these files should not be publicly available and a storage access key should not be used.

I can create a short-term shared access signature (SAS) so that a file can be downloaded from the operating system without a storage access key. This allows the files to be downloaded from a container. This can be achieved with a user-assigned managed identity.

In order to realize this, we first need a user-assigned managed identity and a Stroage account. The information is stored in variables within Nerdio. To add the identity to a session host, we use a scripted action.

As soon as the user-assigned managed identity and the Storage Account are created and the user-assigned managed identity is authorized, we can use the Scripted Action to assign the user-assigned managed identity to a VM. With another scripted action, we can now download and execute the files from the storage account.

Prerequisites

As a general requirement, PowerShell must be up to date on the VM and the following modules must be installed:

  • az.accounts
  • az.resources
  • az.storage
  • az.keyvault

For everything else, a Nerdio instance and a resource group are required, where the storage account and the user-assigned managed identity should be stored. This should also be added in Nerdio so that the authorizations are correct.

Create storage account

A storage account is created in the classic way. Different configurations can be made. A standard account with the availability ZRS or GRS, which can have a private endpoint, is usually sufficient for a storage account for a deployment. Below is a scripted action that automates this:

The parameters are then configured during execution:

The output can be used to create the variable in Nerdio:

Create user-assigned managed identity

A user-assigned managed identity is very easy to create. If this is to be created via the Azure portal, it can look like this:

Later we will need the information from the properties to create the variable in Nerdio

Alternatively, the following scripted action can be used:

The parameters are then configured during execution:

The output can be used to create the variable in Nerdio:

Create variables

We now create two secure variables in Nerdio, which contain all relevant information about the storage account and the user-assigned managed identity.

DeployStorageAccount

The storage account is used for deployment, which is why I call the variable DeployStorageAccount:

The variable bin contains a JSON formatted string with all relevant information:

DeploymentIdentity

As this is the User Assigned Managed Identity for the deployment, it is called DeploymentIdentity:

The variable bin contains a JSON formatted string with all relevant information:

In order to be able to use the User-Assigned Managed Identity later, we save not only the name, but all relevant information in order to find it with the CmdLet Get-AzUserAssignedIdentity.

Authorize user-assigned managed identity on the storage account

Now that the storage account and the User-Assigned Managed Identity have been created, the identity still needs to be authorized on the storage account.

This can also be configured with a scripted action. The prerequisite for this is that the two variables are configured.

The parameters are then configured during execution:

Scripted Action to add user-assigned managed identity to a VM

The following script is used to add the user-assigned managed identity to the VM. It takes into account whether a system-assigned managed identity or user-assigned managed identity already exists.

What the script for adding the user-assigned managed identity does not yet support is the possibility of assigning several user-assigned managed identities to a VM at the same time. However, as this script is executed when the VM is created, it makes no sense to pass a variable as a parameter. You would have to create copies of the script for different identities.

The script is now usually added as a step during VM deployment after the VM has been created:

Practical example

Now that we have created the storage account and created, authorized and assigned the user-assigned managed identity, we can download scripts from the container and execute them on the VM. To do this, we save two scripts in the deplyoment container. These scripts are usually used during the creation of the image.

I use the first script to save some information in the operating system so that I know later when the image was created:

With the second script, we deactivate the option to only shut down a VM from the start menu. This is to prevent the VM from being accidentally switched off but not deallocated.

Now that the scripts have been created on the storage account, you can download and execute them with the following scripted action:

Conclusion

In the meantime, Nerdio offers the possibility to install or execute packages or scripts in other ways. However, I created this way years ago, which still works, and I continue to set it up to have more flexibility.

The Deployment Storage Account in particular has already helped me to temporarily store PowerShell modules and then install them without Internet access. But that would be worth another blog post.

I hope the one or other script will also help you to solve one or more challenges in your deployment.