PowerShell: Create an Azure Automation Account
Posted on: March 2nd, 2025
An automation account let you set your scripts in Azure IaaS into runbooks, allowing them to easily interact with Azure resources, Entra ID objects, etc. and use aspects of Azure's ecosystem like role-based access permissions, a system or user managed identity, scheduling, and more. Automation accounts are very simple to set up in the GUI, but I have two arguments for creating them with PowerShell instead. For one, uniformity. In an environment where you require tagging for all resources, want those tags to only have certain possible values, or need to ensure all automation accounts get placed in the same geographic region, automating the setup of these can help immensely in enforcing uniformity across all automation accounts. Using do-until loops and if statements along with Read-Host will let you and your team enter all the information needed while keeping that input within predefined values. And my second argument, it's fun!
Before Getting Started
If you haven't gotten the Az modules installed yet, do so before trying to run any of the cmdlets further in the article. At the very least you will need the Az.Accounts and Az.Automation modules. That said, I would recommend installing the "Az" module, which will install all the Az modules. If you aren't sure if you have those modules installed or need help getting them installed, check out my article on managing PowerShell modules.
In order to make these commands work, you'll need to connect with an account that has (at least) Automation Contributor assigned in the subscription or resource group that you want to create your automation account in. You will need your tenant ID and subscription ID for it to work. Once you run Connect-AzAccount as you see in the below code block, you will be prompted to authenticate. You'll get an output with some session information. You can suppress this by piping to Out-Null.
### Use Connect-AzAccount to connect to Azure
$tenantID = 'XXXXX'
$subId = 'YYYYY'
Connect-AzAccount -Tenant $tenantID -Subscription $subId
Create an Automation Account
Our meat and potatoes here will be New-AzAutomationAccount. We can create an automation account with a single line if we're being minimal. Required properties are -Name, to name the automation account, -ResourceGroupName, the name of the resource group your automation account will live in, and -Location, the Geographic location your automation account will be assigned.
### Create an automation account, set the name and location
New-AzAutomationAccount -Name 'TestAutomationAccount' -ResourceGroupName 'Automations-PROD' -Location 'East US'
That is as simple as creating an automation account can be. In my opinion, it doesn't quite satisfy what I would consider necessary in an enterprise environment. Let's expand upon it and add more properties, specifically a set of tags and a switch that will automatically assign a system managed identity. Including the -AssignSystemIdentity switch on its own will enable a system-managed identity automatically. The -Tags property will accept a hash table with up to 50 tags defined, the maximum a resource in Azure can accept. We can make the output of Connect-AzAccount a variable and get the Account attribute for a "createdBy" tag. Get-Date can give us the value for a "dateCreated" tag. Our last tag will be "Environment", we'll add a Read-Host that accepts input. That input will be limited to certain values. Invalid values will cause a re-prompt.
### Create an automation account, set the name, location, tags, and assign a system-managed identity
$tenantID = 'XXXXX'
$subId = 'YYYYY'
$rg = 'Automations-PROD'
$azConnect = Connect-AzAccount -Tenant $tenantID -Subscription $subId
do {
$aaName = Read-Host "Enter a name for your automation account"
if ($aaName -eq '') {
Write-Host 'Invalid input detected Enter DEV, TEST, or PROD, or leave blank for PROD.' -ForegroundColor Red
}
} until ($aaName -ne '')
do {
$environment = Read-Host "Is this automation account for a DEV, TEST, or PROD environment? Leave blank for default (PROD)"
if ($environment -eq '') {$environment = "PROD"}
if (@('DEV','TEST','PROD') -inotcontains $environment) {
Write-Host 'Invalid input detected Enter DEV, TEST, or PROD, or leave blank for PROD.' -ForegroundColor Red
}
} until (@('DEV','TEST','PROD') -icontains $environment)
$tags = @{
"createdBy" = $azConnect.Account
"dateCreated" = (Get-Date -Format yyyyMMdd)
"Environment" = $environment
}
New-AzAutomationAccount -Name $aaName -ResourceGroupName $rg -Location 'East US' `
-Tags $tags -AssignSystemIdentity
You may be provisioning an automation account for someone else to work in. In that case, you may be done. But if you're making one for that you'll be working in yourself, then having an empty automation account won't do you much good. We can move forward in our script by creating one or more runbooks to hold our scripts and also a schedule to apply to them.
New-AzAutomationSchedule
Creating a schedule in this process should be entirely optional, but it may be helpful if you're importing a script rather than filling it in later. More on that to come in the next sections. We'll prompt if creating a schedule is desired and encase what comes next in an if-else that gathers information for a schedule if yes, skips ahead if not. Your required properties for New-AzAutomationSchedule will be -ResourceGroupName, -AutomationAccountName, -Name, and -StartTime. We can reuse the variables used previously for the resource group and automation account names. We will need to define the schedule's name and the start time. I'll also make the schedule weekly, only because I find weekly scheduling to be most useful for runbooks. You can modify this to have options.
### Create a schedule for an automation account
do {
$answerSchedule = Read-Host "Would you like to create a schedule for this automation account? (Y/N)"
if (@('y','n') -inotcontains $answerSchedule) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until (@('y','n') -icontains $answerSchedule)
if ($answerSchedule -ieq 'y') {
$tz = ([System.TimeZoneInfo]::Local).Id
do {
$scheduleName = Read-Host "Enter the name of this schedule"
if ($scheduleName -eq '') {
Write-Host "Invalid input detected. Please enter a name for this schedule" -ForegroundColor Red
}
} until ($scheduleName -ne '')
do {
$hours = Read-Host "Enter the hours of your start time (0-23)"
$minutes = Read-Host "Enter the minutes of your start time (0-59)"
if (@(00..23) -notcontains $hours -or @(00..59) -notcontains $minutes) {
Write-Host "Invalid input detected on either your Hours or Minutes. Please enter 0-23 for hours and 0-59 for minutes." -ForegroundColor Red
}
} until (@(00..23) -contains $hours -and @(00..59) -contains $minutes)
if (@(0..9) -contains $hours) {$hours = '0' + $hours}
if (@(0..9) -contains $minutes) {$minutes = '0' + $minutes}
$startTime = $hours + ':' + $minutes
do {
$answerWeekly = Read-Host "Would you like this schedule to run weekly? (Y/N)"
if (@('y','n') -inotcontains $answerSchedule) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until (@('y','n') -icontains $answerSchedule)
if ($answerWeekly -ieq 'y') {
do {
$day = Read-Host "Enter the day of the week this schedule should activate. (ex. 'Monday', 'Tuesday', etc.)"
if (@('monday','tuesday','wednesday','thursday','friday','saturday','sunday') -inotcontains $day) {
Write-Host "Invalid input detected. Please enter the name of the day of the week that this schedule should activate on." -ForegroundColor Red
}
} until (@('monday','tuesday','wednesday','thursday','friday','saturday','sunday') -icontains $day)
New-AzAutomationSchedule -ResourceGroupName $rg -AutomationAccountName $aaName -Name $scheduleName `
-WeekInterval 1 -DaysOfWeek $day -StartTime $startTime -TimeZone $tz
} else {
New-AzAutomationSchedule -ResourceGroupName $rg -AutomationAccountName $aaName -Name $scheduleName `
-StartTime $startTime -OneTime -TimeZone $TimeZone
}
}
You now have a schedule that can be assigned to your runbooks once they are created. In our next section we will create a runbook, or multiple if desired.
Create Runbook
For our last section, we'll create our runbook. We will also have the option to create multiple if necessary. The requirements for New-AzAutomationRunbook are not wildly different from New-AzAutomationAccount. We will reuse our resource group and automation account names again. We will also reuse the tags from earlier, supply a name for the runbook and description, and optionally select an existing PS1 file to be imported with Import-AzAutomationRunbook. You can specify what kind of runbook this is with the -Type property. For our purposes, we will assume it is PowerShell. This can also be changed in the GUI at any time.
After our runbook is created, we will also give the option to register it to the schedule we defined earlier with Register-AzAutomationScheduledRunbook, only if it was defined. The required properties are all values we will already have at this point: the name of the resource group, automation account, runbook, and schedule. They will all be applied automatically and the runbook will associate to the schedule if you choose for that to happen.
### Create a runbook for the new automation account, optionally apply schedule, import PS1 file
Add-Type -AssemblyName System.Windows.Forms
function Select-Script {
$scriptSelect = New-Object System.Windows.Forms.OpenFileDialog
$scriptSelect.Filter = "PowerShell Scripts (*.ps1)|*.ps1"
$scriptSelect.Title = "Select a PowerShell Script"
if ($scriptSelect.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
return $scriptSelect.FileName
}
return $null
}
do {
$answerCreateRb = Read-Host "Would you like to create a runbook? (Y/N)"
if ($('y','n') -inotcontains $answerCreateRb) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until ($('y','n') -icontains $answerCreateRb)
if ($answerCreateRb -ieq 'y') {
do {
do {
$rbName = Read-Host "Enter the name of this runbook"
if ($rbName -eq '') {
Write-Host "Invalid input detected. Please enter a name for this schedule" -ForegroundColor Red
}
} until ($rbName -ne '')
do {
$description = Read-Host "Enter a short description for this runbook"
if ($description -eq '') {
Write-Host "Invalid input detected. While a description is not a required property, please provide one for documentation." -ForegroundColor Red
}
} until ($description -ne '')
do {
$answerImportScript = Read-Host "Would you like to add $rbName to $scheduleName? (Y/N)"
if ($('y','n') -inotcontains $answerImportScript) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until ($('y','n') -icontains $answerImportScript)
if ($answerImportScript -ieq 'n') {
New-AzAutomationRunbook -ResourceGroupName $rg -AutomationAccountName $aaName -Name $rbName `
-Tags $tags -Type PowerShell -Description $description
} else {
do {
$scriptPath = Select-Script
if (!$scriptPath) {
Write-Host "No file selected." -ForegroundColor Red
}
} until ($scriptPath)
Import-AzAutomationRunbook -ResourceGroupName $rg -AutomationAccountName $aaName -Name $rbName `
-Tags $tags -Type PowerShell -Description $description -Path $scriptPath -Published
}
if ($scheduleName) {
do {
$answerAddRbToSchedule = Read-Host "Would you like to add $rbName to $scheduleName? (Y/N)"
if ($('y','n') -inotcontains $answerAddRbToSchedule) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until ($('y','n') -icontains $answerAddRbToSchedule)
if ($answerAddRbToSchedule -ieq 'y') {
Register-AzAutomationScheduledRunbook -ResourceGroupName $rg -AutomationAccountName $aaName -RunbookName $rbName -ScheduleName $scheduleName
}
}
do {
$answerCreateAnotherRb = Read-Host "Would you like to create a runbook? (Y/N)"
if ($('y','n') -inotcontains $answerCreateAnotherRb) {
Write-Host "Invalid input detected. Please enter Y for yes or N for no." -ForegroundColor Red
}
} until ($('y','n') -icontains $answerCreateAnotherRb)
} until ($answerCreateAnotherRb -ieq 'n')
}
This will loop until you specify that you are finished, and the script will end. Each cmdlet that creates an automation account, runbook, schedule, etc. will output information about your new resource if successfully created. These can be suppressed by piping to Out-Null.
Final Thoughts
You now have a new automation account with a schedule and one or more runbooks. There may still be work to do, like assigning permissions to your system-managed identity, adding variables to your automation account's shared resources, or any other configuration. All of which, luckily for us, can also be managed with PowerShell. I may write more about that in the future. For now, this is a finished product that hopefully someone finds interesting or, with a few adjustments, useful. You can find a script with each section combined on my public GitHub repo. Feel free to download and play around with it yourself.
What do you think? Would you do this differently or add anything? I'd like to hear it! Reach out to me at [email protected] or on LinkedIn. I am always happy to discuss PowerShell and technology in general.