Using user-assigned managed identities in Azure Automation Runbooks

Thomas Watson
5 min readFeb 3, 2022

--

Using an Automation runbook to control Azure VMs using a user assigned managed identity

Part one is here: Creating an Azure Automation Account with User-Assigned Managed Identity using Terraform
(All code for this short series is available here: tommakesmusic/Medium_blog (github.com) NOTE: this code is not ready for a production environment and is provided for your entertainment and education only!)

In part one of this small series, we created an automation account that uses a user-assigned managed identity to carry out its automations. We haven’t given it anything to do, however. It is time to create the runbook that will start and stop our virtual machines.

This part of the process turned out to be the most difficult, because, as mentioned in part 1, my plan was to deploy this via an Azure DevOps pipeline and every tutorial that I could find pretty much used the command line/Powershell to login to the Azure account locally. Indeed, Microsoft’s own documentation is unclear (and even misleading) on some of the steps — but we’ll get to that later.

As with part one, most of the HCL code looks almost like the examples from the ‘Azurerm’ documentation. Here is the code to deploy a runbook:

Deploying a runbook in Azure

Mentioned in the comments is that “ the Azure API requires a ‘publish_content_link’ to be supplied even when specifying your own content”. You can of course use a local file (as we did with the ARM template) but you must include a blank ‘publish_content_link{}’ to allow the HCL to validate. In my case, I decided just to use the GitHub version of the runbook. (I use the “raw” option from GitHub when using a uri here.)

Let us now turn our attention to the runbook. The runbook I used is based on this one https://github.com/azureautomation/stopstartazurevm--scheduled-vm-shutdownstartup- by Pradebban Raja at Microsoft. Most of the runbook will remain the same, but we need to allow the runbook to use our managed identity. Quite frankly, this part of the process was by far the least well documented, unless you are using the portal or the CLI. Here is the authentication code, copied and pasted from Microsoft (https://docs.microsoft.com/en-us/azure/automation/add-user-assigned-identity):

Microsoft code for using a user-assigned managed identity

Now we need to create an ‘azurerm_automation_schedule’ and an ‘azurerm_automation_job_schedule’, the latter of which is shown below. As these are well covered in the Hashicorp Azurerm documentation, we won’t spend too much time on them, except to note that the ‘azurerm_automation_job_schedule’ is where we pass the parameters into our runbook:

Link a runbook and a schedule together to create a job schedule
Link a runbook and a schedule together to create a job schedule

It is also important to know that due to yet another quirk of Terraform and Azure, all your parameter names must be in lowercase.

I have also included the ‘Az.ManagedServiceIdentity’ Powershell module in case we need to do more with the managed identity in the future. In my current version I don’t make use of this module but note that the module is not currently included in the standard modules created with the automation account and will have to be deployed if needed:

Including a Powershell module in case of future need
Az.ManagedServiceIdentity module

From the Microsoft documentation: “After you enable the user-assigned managed identity for your Automation account and give an identity access to the target resource, you can specify that identity in runbooks against resources that support managed identity.” They supply the code example used above and the line we are specifically interested in, on its own, below:

Microsoft code for allowing the runbook to use the managed identity
Microsoft code for allowing the runbook to use the managed identity

The problem with this is that it doesn’t work. When I supplied the ‘client_id’ of the managed identity we created (from the terraform HCL ‘azurerm_user_assigned_identity.automation-account-managed-id.client_id’), the runbook completed successfully but did not actually do anything except throw major errors due to the failed authentication of the managed identity.

It may be that I jumped to the conclusion too quickly that when Microsoft say “Client_Id” they mean the “client_id” of the managed identity. Unfortunately, I did not screen capture any of the error messages…. Perhaps those more experienced will spot this as a beginner’s error, but I genuinely thought ‘Client_Id’ = ‘client_id’.

With the error messages that I failed to save, and a little educated guesswork, I discovered the issue. In this case, what worked for me was using the ‘principal_id’ of the user-assigned managed identity. Once this was used, everything fell into place and worked flawlessly.

You can see the updated ‘azurerm_automation_job_schedule’ here:

and the updated Runbook here:

All the images above show only a part of the code, and the full versions can be found on my GitHub, link above. You will have to change the code to suit your own uses.

As always, this is a product of my learning process and the use you get out of it may vary. If it has been of help, I’m glad and and if you have spotted some glaring issues do let me know! As stated before, I am a beginner in DevOps and for context, this has been posted in Jan/Feb 2022 and may not age well!

Thanks for your time!

--

--

Thomas Watson

Late changer to IT. Working / learning as a DevOps engineer