Deploying Azure Automation Account and Runbooks via Terraform
Azure Automation Accounts leverage Azure Runbooks to automate processes within organizations’ Azure tenants. This process can be very powerful and help organizations effectively manage, scan, and update their environments. This post is not about Azure Automation Accounts or Azure Runbooks but rather the process by which to deploy these Accounts and their associated scripts via Terraform.
If unfamiliar, Terraform is an open-source Infrastructure as code provider. One of it’s biggest selling points is that it can be used for deploying to a plethora of providers. Since we are dealing with Azure we will be using the Azure provider. We will also assume that you are already familiar with how to deploy Terraform to Azure. If you are not here is the Terraform walkthrough for Azure.
The first step in the deployment will be creating the Azure Automation Runbook. This is done via the azurerm_automation_account resource like below:
resource "azurerm_automation_account" "aa_demo" {
name = 'aademo'
location = azurerm_resource_group.rg_automation_account.location
resource_group_name = azurerm_resource_group.rg_automation_account.name
sku_name = "Basic"
}
This automation account is referencing a resource group that will also be created as part of the Terraform file. Automation Accounts like any other Azure resource requires a Resource Group. The Resource Group is setup like:
resource "azurerm_resource_group" "rg_automation_account" {
name = 'rg-aatest-dev-eus
location = "east us"
}
Unfortunately, the ability to create the Automation Account as a “RunAsAccount” cannot be configured at this this via Terraform. RunAsAccount is similar to a Managed Identity in Azure, aka the script will run as the resource…..thus RunAsAccount. That being said there is a github issue that outlines the steps that one could work around this. However; for initial setup it might be easier to create the Automation Account and toggle the Run. This located after the Automation Account has been created by going to “Run as Accounts”-> Create
So at this point the Terraform file will create the Resource Group and the Azure Automation Account. However, we still need to create the Runbook and upload the code that will be ran under it.
I have found the easiest way to do this is to store the script to be ran in the same project as the Terraform file. In this case we have the script in runbooks\poweshell\demo.ps1
This script will need to be imported into the Terraform file as a data reference of type local file. A block like this should do the trick:
data "local_file" "demo_ps1" {
filename = "../runbooks/powershell/demo.ps1"
}
Once we do this Terraform is aware of the existence of the demo.ps1 file. This is important as we will pass this reference to the Runbook.
To create the Runbook we will leverage the azure_automation_runbook resource.
resource "azurerm_automation_runbook" "demo_rb" {
name = "Demo-Runbook"
location = azurerm_resource_group.rg_automation_account.location
resource_group_name = azurerm_resource_group.rg_automation_account.name
automation_account_name = azurerm_automation_account.aa_demo.name
log_verbose = "true"
log_progress = "true"
description = "This Run Book is a demo"
runbook_type = "PowerShell"
content = data.local_file.demo_ps1.content
}
The content argument is key as that will pass the script that was referenced earlier and upload it’s contents as part of the deployment.
So now that the Automation Account has been created and the Runbook the demo.ps1 file can be executed in Azure. However; the need may still arise to schedule the execution of the demo.ps1 script. To do this we can leverage the azurerm_automation_job_schedule resource with first a schedule defined via azurerm_automation_schedule.
First the schedule:
resource "azurerm_automation_schedule" "sunday" {
name = "EverySundayEST"
resource_group_name = azurerm_resource_group.rg_automation_account.name
automation_account_name = azurerm_automation_account.aa_demo.name
frequency = "Week"
interval = 1
timezone = "America/New_York"
description = "Run every Sunday"
week_days = ["Sunday"]
}
This schedule is agnostic of the current Runbook and can be reused multiple times.
Next is the Terraform that links the Runbook and the schedule together:
resource "azurerm_automation_job_schedule" "demo_sched" {
resource_group_name = azurerm_resource_group.rg_automation_account.name
automation_account_name = azurerm_automation_account.aa_demo.name
schedule_name = azurerm_automation_schedule.sunday.name
runbook_name = azurerm_automation_runbook.demo_rb.name
depends_on = [azurerm_automation_schedule.sunday]
}
Now normally with Terraform the depends_on
does not need to be declared as it should recognize that the sunday
schedule is being reference and thus infer the demo_sched
won’t run until the sunday
schedule is created. However, at the time of this blog post there is an open bug on this issue. Thus, the workout is the explicitly call out the dependency.
After this everything is all done! Congratulations you should now be able to deploy an Azure Automation Account, Azure Runbooks, Schedules, and associated scripts via Terraform!
Hi, Great post, helped me a lot during my Terraform deployments.
Now leaning into Azure Bicep and I was wondering if this was possible using Azure Bicep as well.
It keeps the runbook up to date with the local file you store next to the template (terraform, arm, bicep).
Otherwise some powershell code should be ran next to it, to upload the local file to the runbook.
Thanks!
I believe this is a limitation between the two. I have not tried this yet; however, one more recent bicep improvement is the loadContext() functionality: https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions-files#loadtextcontent
This may be what you are looking for.