PowerShell Azure Automation Runbook: Basics to Production

PowerShell Azure Automation Runbook: Basics to Production

PowerShell Tips Editor 5 min read
PowerShell Azure Automation Runbook: Basics to Production

Azure Automation runbooks let you run PowerShell in the cloud without provisioning or maintaining a server. They are the right choice when you need recurring cloud maintenance jobs — stopping idle VMs, rotating secrets, or pruning old storage blobs — and you want Azure to handle retries, logging, and scheduling. Before you reach for Azure Functions or a local scheduled task, consider whether the workload is cloud-native, infrequent, and requires managed identity auth; if all three are true, a runbook is usually the simplest path.

Quick Answer

Create a PowerShell runbook in an Azure Automation Account, connect to Azure resources using the system-assigned Managed Identity (Connect-AzAccount -Identity), publish the runbook, then attach a recurring schedule or webhook to trigger it automatically.

Creating an Automation Account and Uploading a Module

An Automation Account is the container for runbooks, credentials, schedules, and modules. You need one before writing any runbook code. The Az.Accounts and Az.Compute modules must be present in the account’s module gallery before your runbook can import them — the sandbox that runs your code does not share your local PSModulePath.

# Create the Automation Account
New-AzAutomationAccount `
    -ResourceGroupName "rg-automation" `
    -Name "aa-corp-maintenance" `
    -Location "eastus" `
    -AssignSystemIdentity

# Import a module from the PowerShell Gallery into the account
New-AzAutomationModule `
    -ResourceGroupName "rg-automation" `
    -AutomationAccountName "aa-corp-maintenance" `
    -Name "Az.Compute" `
    -ContentLinkUri "https://www.powershellgallery.com/api/v2/package/Az.Compute"

Wait for the module provisioning state to reach Succeeded before publishing runbooks that depend on it. You can poll with Get-AzAutomationModule and check the ProvisioningState property.

Writing a Runbook That Connects via Managed Identity

Managed Identity eliminates stored credentials entirely. When the runbook calls Connect-AzAccount -Identity, Azure injects a short-lived token scoped to the identities that have been granted RBAC roles on target resources. No client secrets, no certificate rotation.

param(
    [string]$ResourceGroupName = "rg-prod",
    [int]$DaysIdle = 7
)

# Authenticate using the system-assigned Managed Identity
Connect-AzAccount -Identity -ErrorAction Stop

# Find VMs that have been deallocated for more than $DaysIdle days
$idleVMs = Get-AzVM -ResourceGroupName $ResourceGroupName -Status |
    Where-Object { $_.PowerState -eq "VM deallocated" }

foreach ($vm in $idleVMs) {
    Write-Output "Idle VM found: $($vm.Name)"
}

Always use -ErrorAction Stop on the connect call so that a missing RBAC role surfaces as a terminating error rather than a silent failure that corrupts downstream results.

Passing Input Parameters to a Runbook

Parameters are declared at the top of the runbook script with the standard param() block. They can be passed when starting a runbook manually, via a schedule’s parameter set, or through a webhook payload. Use strongly typed parameters — [string], [int], [bool] — to catch type mismatches early.

# Start the runbook manually and pass parameters
Start-AzAutomationRunbook `
    -ResourceGroupName "rg-automation" `
    -AutomationAccountName "aa-corp-maintenance" `
    -Name "Stop-IdleVMs" `
    -Parameters @{
        ResourceGroupName = "rg-prod"
        DaysIdle          = 14
    } `
    -Wait

The -Wait switch blocks until the job completes and returns the job object, which is useful for orchestration scripts that chain runbooks together.

Handling Runbook Output and Error Streams

Azure Automation captures five output streams: Output, Error, Warning, Verbose, and Debug. Write-Output goes to the Output stream and is the only stream visible in the job’s default view. Use Write-Warning for non-fatal alerts and Write-Error for recoverable errors you want logged without stopping the runbook. Wrap critical sections in try/catch with -ErrorAction Stop so the job status shows as Failed rather than Completed when something goes wrong.

Scheduling Runbooks with Recurring Schedules

Schedules in Azure Automation define when a runbook fires; you link a schedule to a runbook to wire them together. You can have one runbook linked to multiple schedules — for example, a daily run during business hours and a weekly run on Sunday that passes different parameters.

# Create a daily schedule starting tomorrow at 02:00 UTC
$startTime = (Get-Date).Date.AddDays(1).AddHours(2)

New-AzAutomationSchedule `
    -ResourceGroupName "rg-automation" `
    -AutomationAccountName "aa-corp-maintenance" `
    -Name "Daily-2AM-UTC" `
    -StartTime $startTime `
    -DayInterval 1

# Link the schedule to the runbook with parameters
Register-AzAutomationScheduledRunbook `
    -ResourceGroupName "rg-automation" `
    -AutomationAccountName "aa-corp-maintenance" `
    -RunbookName "Stop-IdleVMs" `
    -ScheduleName "Daily-2AM-UTC" `
    -Parameters @{ ResourceGroupName = "rg-prod"; DaysIdle = 7 }

Linking a Runbook to a Webhook for Event-Driven Triggers

Webhooks give external systems a way to trigger a runbook over HTTPS without Azure credentials. Logic Apps, GitHub Actions, or monitoring alerts can POST to the webhook URL to start a job. The URL contains a shared secret, so treat it like a password — store it in Key Vault and rotate it before expiry. Webhook payloads arrive in the $WebhookData parameter as JSON; use ConvertFrom-Json to extract fields into your runbook logic.

Common Errors

  • Managed Identity does not have the required RBAC role: The runbook call to Connect-AzAccount -Identity succeeds, but subsequent Get-AzVM or Set-Az* calls return AuthorizationFailed. Fix by assigning the correct built-in role (e.g., Virtual Machine Contributor) to the Automation Account’s system identity on the target resource group via New-AzRoleAssignment.
  • Module version conflict: Your runbook imports Az.Compute 6.x from the account gallery, but your local dev machine has 7.x, causing parameter name mismatches at runtime. Always check Get-AzAutomationModule version before writing runbook code, and pin your local environment to match.

Related Cmdlets / See Also

Wrapping Up

Azure Automation runbooks give PowerShell workloads a serverless home in the cloud. By pairing Managed Identity authentication, typed parameters, and recurring schedules you get secure, repeatable cloud maintenance with full job logging and no infrastructure to manage. Start with a simple runbook, validate it in the Test pane, then publish and schedule it for production use.

Send-Item -To