Never hard-code service principal secrets or Azure credentials in scripts. In CI/CD pipelines, use the built-in Azure service connection (Azure DevOps handles the authentication). In Azure Automation Runbooks and Azure-hosted VMs, use Connect-AzAccount -Identity which authenticates via the resource's Managed Identity—no secrets, no rotation, no risk of credential leak in logs.
Azure Automation with PowerShell
Install and authenticate with the Az module, manage Azure resource groups, virtual machines, and storage accounts via PowerShell scripts, and build Azure Automation runbooks for serverless scheduled automation.
🧒 Simple Explanation (ELI5)
The Az module is PowerShell's remote control for your entire Azure subscription. Instead of clicking through the Azure Portal for 30 minutes to create a resource group, add a VM, and configure a storage account, you type three commands and it is done. Azure Automation Runbooks take that further: they run your PowerShell script on a schedule in the cloud, without needing any local machine or VM to be running.
🔧 Why Do We Need It?
- Infrastructure as code: scripts in version control replace manual portal changes—every resource creation is documented, repeatable, and reviewable.
- Scale: provision 50 identical resource groups for a test environment by changing one variable, not clicking 50 times.
- Automation Accounts: schedule runbooks to start/stop VMs at off-peak hours, saving significant compute costs.
- CI/CD integration: Az module scripts are standard Azure DevOps pipeline steps—no extra tooling needed.
⚙️ Technical Explanation
The Az module is the official PowerShell module for Azure. It is organized into sub-modules: Az.Accounts (authentication), Az.Resources (resource groups, ARM deployments), Az.Compute (VMs, scale sets), Az.Storage (storage accounts, blobs), Az.Network (VNets, NSGs, load balancers), Az.Websites (App Services).
Authentication: Connect-AzAccount opens an interactive browser login. For CI/CD, use Connect-AzAccount -ServicePrincipal with a service principal client ID and certificate or secret. Managed Identity (Connect-AzAccount -Identity) is the most secure option for Azure-hosted VMs, pipelines, and Automation Accounts—no credentials to rotate.
Azure Automation is a cloud service that runs PowerShell and Python runbooks on a schedule or in response to webhooks. It supports Managed Identity for secure, credential-free Azure API access.
Installing the full Az module (Install-Module Az) downloads ~70 sub-modules and can take 10+ minutes. In scripts and pipelines, install only what you need: Install-Module Az.Accounts, Az.Resources, Az.Compute. This dramatically speeds up CI/CD agent setup when the Az module must be installed fresh.
📊 Visual Representation
⌨️ Commands / Syntax
# Install Az module (production: only needed sub-modules)
Install-Module -Name Az.Accounts, Az.Resources, Az.Compute, Az.Storage -Force -Scope CurrentUser
# Authenticate (interactive)
Connect-AzAccount
# Authenticate with Managed Identity (in Azure-hosted environments)
Connect-AzAccount -Identity
# Authenticate with Service Principal (CI/CD)
$secureSecret = ConvertTo-SecureString $env:SP_SECRET -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($env:SP_CLIENT_ID, $secureSecret)
Connect-AzAccount -ServicePrincipal -Credential $cred -TenantId $env:TENANT_ID
# Set target subscription
Set-AzContext -SubscriptionId "00000000-0000-0000-0000-000000000000"
# ===== RESOURCE GROUPS =====
New-AzResourceGroup -Name "rg-skilly-prod" -Location "uksouth" -Tag @{ team="platform"; env="prod" }
Get-AzResourceGroup | Where-Object ResourceGroupName -like "rg-skilly-*" | Select-Object ResourceGroupName, Location
Remove-AzResourceGroup -Name "rg-skilly-test" -Force -WhatIf
# ===== VIRTUAL MACHINES =====
# List VMs and their status
Get-AzVM -Status | Select-Object Name, ResourceGroupName, PowerState |
Where-Object PowerState -eq "VM running"
# Start / Stop VMs
Start-AzVM -ResourceGroupName "rg-skilly-prod" -Name "vm-worker01"
Stop-AzVM -ResourceGroupName "rg-skilly-prod" -Name "vm-worker01" -Force
# ===== STORAGE =====
New-AzStorageAccount -ResourceGroupName "rg-skilly-prod" `
-Name "stskillyartifacts" -Location "uksouth" `
-SkuName "Standard_LRS" -Kind "StorageV2"
$ctx = (Get-AzStorageAccount -ResourceGroupName "rg-skilly-prod" -Name "stskillyartifacts").Context
Set-AzStorageBlobContent -Container "artifacts" -File ".\app.zip" -Blob "releases/app-v1.zip" -Context $ctx
# ===== TAGGING =====
$vm = Get-AzVM -ResourceGroupName "rg-skilly-prod" -Name "vm-worker01"
Update-AzTag -ResourceId $vm.Id -Tag @{ "build-id" = "2024.1.42"; "owner" = "platform-team" } -Operation Merge
# ===== AZURE AUTOMATION RUNBOOK (inline) =====
# This runs inside an Azure Automation Account with Managed Identity
Connect-AzAccount -Identity
$staleVMs = Get-AzVM -Status | Where-Object PowerState -eq "VM deallocated" |
Where-Object { $_.Tags["auto-stop"] -eq "true" }
foreach ($vm in $staleVMs) {
Write-Output "Auto-removing deallocated VM: $($vm.Name)"
Remove-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force
}
💼 Example (Real-world Use Case)
A team runs an Azure Automation Runbook every weekday at 19:00 that stops all VMs tagged auto-stop=evening and restarts them at 07:00. For 40 dev/test VMs at an average cost of £0.10/hour, this saves 12 hours of compute per VM per day — over £1,700/month. The runbook uses Managed Identity so no credentials need rotating.
🧪 Hands-on
- Install
Az.AccountsandAz.Resourcesand runConnect-AzAccount. - Run
Get-AzResourceGroup | Select-Object ResourceGroupName, Location | Sort-Object ResourceGroupNameto list all your resource groups. - Create a test resource group:
New-AzResourceGroup -Name "rg-ps-test" -Location "uksouth". - List VMs in that group (if any):
Get-AzVM -ResourceGroupName "rg-ps-test" -Status. - Delete the test resource group with
-WhatIffirst, then without.
Write a script that: (1) sets a context to a subscription, (2) lists all storage accounts across all resource groups using Get-AzStorageAccount, (3) builds a [PSCustomObject] per account with Name, ResourceGroup, Location, SkuName, and an IsGRS boolean (true if SkuName contains GRS), and (4) exports to CSV. This is a real cost and compliance audit pattern for storage replication settings.
🐛 Debugging Scenario
Problem: a script runs Connect-AzAccount with a service principal but fails with "The client does not have authorization to perform action."
- Cause: the service principal is authenticated but lacks the IAM role needed for the operation (e.g., Contributor on the resource group).
- Diagnose: run
Get-AzRoleAssignment -ServicePrincipalName $sp.AppIdto see what roles are assigned. Check if the subscription context is correct withGet-AzContext. - Fix: assign the required role:
New-AzRoleAssignment -ApplicationId $sp.AppId -RoleDefinitionName "Contributor" -ResourceGroupName "rg-prod". Use the least-privilege approach: assign only the minimum required role at the minimum required scope (resource group level, not subscription level).
🎯 Interview Questions
Beginner
The Az module is Microsoft's official PowerShell module for managing Azure resources. It replaces the older AzureRM module. It provides cmdlets for every Azure service organized into sub-modules like Az.Compute, Az.Storage, and Az.Network.
Three common ways: Connect-AzAccount for interactive browser login, Connect-AzAccount -ServicePrincipal with client credentials for CI/CD pipelines, and Connect-AzAccount -Identity for Managed Identity authentication in Azure-hosted environments. Managed Identity is the most secure because it requires no credentials to manage.
Scenario-based
Check Get-AzContext to confirm the script is authenticating to the correct subscription and tenant. Run Get-AzRoleAssignment for the service principal to see what roles it has. The error message includes the specific operation and resource—map that to the required RBAC role and assign it at the appropriate scope (resource group, not subscription, for least privilege).
Tag dev VMs with auto-stop=evening. Create an Azure Automation Account with a Managed Identity that has VM Contributor role on the dev resource groups. Write a runbook using Connect-AzAccount -Identity, querying VMs with that tag, and calling Stop-AzVM. Schedule it with a daily trigger at 19:00. Create a matching start runbook at 07:00. Track cost savings in Azure Cost Management.
🌐 Real-world Usage
Platform teams use Az module scripts in Azure DevOps pipelines to provision complete environments from scratch: resource groups, App Service plans, web apps, storage accounts, Key Vaults, and RBAC assignments in sequence. Azure Automation Accounts run daily cleanup jobs that remove untagged resources, enforce tagging policies, and report on cost anomalies.
📝 Summary
The Az module connects PowerShell to every Azure service. Authentication tiers: interactive login for dev, service principal for CI/CD, Managed Identity for Azure-hosted automation (no credentials). Manage resource groups, VMs, and storage with New-, Get-, Set-, Remove- Az cmdlets. Azure Automation Runbooks run PowerShell serverlessly on schedules. Always use least-privilege RBAC roles for service principals and managed identities.