Skip to content
6 min read·Lesson 5 of 8

Managing Azure with the Az Module

The Az PowerShell module — the cross-platform replacement for AzureRM that covers every Azure service.

The Az PowerShell module is the official toolkit for Azure automation from PowerShell. It replaced AzureRM in 2019 — if you still see AzureRM.* cmdlets in older scripts, migrate (Microsoft ended support for AzureRM in 2024).

Installation

# Cross-platform install (pwsh 7+)
Install-Module Az -Scope CurrentUser -Repository PSGallery -Force

# Az is a meta-module that depends on dozens of Az.* sub-modules (Az.Compute, Az.Storage, ...).
# For lighter scripts, install only what you need:
Install-Module Az.Accounts, Az.Compute, Az.Storage -Scope CurrentUser

Update-Module Az
Get-Module Az -ListAvailable

Authenticating

Interactive (developer machine)

Connect-AzAccount

# After the browser flow, see what you got:
Get-AzContext
Get-AzSubscription
Set-AzContext -Subscription "Production"

The context is the (account, subscription, tenant) triple all subsequent cmdlets operate against.

Service Principal (CI / scripts)

# Create a service principal once (Azure CLI or via Microsoft Entra)
# Save credentials securely (Key Vault, environment variable, secret store).

$credential = New-Object PSCredential -ArgumentList $env:AZ_CLIENT_ID, (ConvertTo-SecureString $env:AZ_CLIENT_SECRET -AsPlainText -Force)

Connect-AzAccount -ServicePrincipal -Credential $credential -TenantId $env:AZ_TENANT_ID
Set-AzContext -Subscription $env:AZ_SUBSCRIPTION_ID

Managed Identity (Azure VM / Azure Functions / runbook)

Connect-AzAccount -Identity
# That's it. Az queries the IMDS endpoint for a token.

Best practice: never use a service principal where Managed Identity works. No secrets to rotate, no leaks possible.

Federated Credentials (GitHub Actions / Azure DevOps)

OIDC-based auth from GitHub Actions to Azure has no long-lived secret:

# From inside a GitHub Action with azure/login@v2:
Connect-AzAccount -ServicePrincipal -ApplicationId $env:AZURE_CLIENT_ID `
    -Tenant $env:AZURE_TENANT_ID -FederatedToken $env:ACTIONS_ID_TOKEN_REQUEST_TOKEN

The azure/login action handles this for you; just call PowerShell after it succeeds.

Working with Resources

Resource groups

New-AzResourceGroup -Name rg-web-prod -Location westeurope
Get-AzResourceGroup
Get-AzResource -ResourceGroupName rg-web-prod
Remove-AzResourceGroup -Name rg-web-prod -Force

Virtual machines

# List
Get-AzVM | Format-Table Name, ResourceGroupName, Location

# Get one and inspect
$vm = Get-AzVM -Name web01 -ResourceGroupName rg-web-prod
$vm | Get-Member
$vm.HardwareProfile.VmSize       # → Standard_D4s_v5

# Stop (deallocate to stop billing)
Stop-AzVM -Name web01 -ResourceGroupName rg-web-prod -Force

# Resize
Update-AzVM -VM ($vm | Set-AzVMSize -VMSize Standard_D2s_v5) -ResourceGroupName rg-web-prod

# Create from minimal params (auto-creates VNet, public IP, etc.)
New-AzVM -Name app01 -ResourceGroupName rg-app-prod -Location westeurope `
    -Image UbuntuLTS -Size Standard_D2s_v5 -OpenPorts 22, 443

Storage

$ctx = (Get-AzStorageAccount -Name mystorage -ResourceGroupName rg-data).Context

# List blobs
Get-AzStorageContainer -Context $ctx
Get-AzStorageBlob -Container backups -Context $ctx

# Upload / download
Set-AzStorageBlobContent -File ./data.csv -Container backups -Blob data.csv -Context $ctx
Get-AzStorageBlobContent -Container backups -Blob data.csv -Destination ./downloaded.csv -Context $ctx

Networking

# NSG management
$nsg = Get-AzNetworkSecurityGroup -Name nsg-web -ResourceGroupName rg-web-prod
$nsg | Add-AzNetworkSecurityRuleConfig -Name AllowHTTPS `
    -Access Allow -Direction Inbound -Priority 100 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange 443 -Protocol Tcp |
    Set-AzNetworkSecurityGroup

Role assignments

New-AzRoleAssignment -ObjectId $userId -RoleDefinitionName Reader -Scope (Get-AzResourceGroup rg-prod).ResourceId

Get-AzRoleAssignment -ResourceGroupName rg-prod
Get-AzRoleDefinition | Where-Object Name -like "*Storage*"

Common Patterns

Tag everything

$tags = @{
    Environment = "Production"
    CostCenter  = "cc-1234"
    Team        = "payments"
    Owner       = "platform@acme.io"
}

# Apply to a resource group
Set-AzResourceGroup -Name rg-payments-prod -Tag $tags

# Apply to a single resource
$rg = Get-AzResourceGroup rg-payments-prod
Get-AzResource -ResourceGroupName $rg.ResourceGroupName | ForEach-Object {
    Set-AzResource -ResourceId $_.Id -Tag $tags -Force
}

Bulk operations with parallel pipeline

$vms = Get-AzVM
$vms | ForEach-Object -Parallel {
    Import-Module Az.Compute
    Stop-AzVM -Name $_.Name -ResourceGroupName $_.ResourceGroupName -Force
} -ThrottleLimit 10

Important caveat: -Parallel spawns separate runspaces; you must re-import modules and re-establish Az context inside the block, or share state with $using:.

Querying with Resource Graph

Az PowerShell can query Azure Resource Graph with KQL — fast across the entire estate:

Install-Module Az.ResourceGraph -Scope CurrentUser
Search-AzGraph -Query "
Resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| where properties.hardwareProfile.vmSize startswith 'Standard_D'
| project name, resourceGroup, vmSize=properties.hardwareProfile.vmSize, location
"

Far faster than enumerating with Get-AzVM across subscriptions.

Az CLI vs Az PowerShell

Microsoft maintains two equivalent tooling stacks:

Az CLI (az)Az PowerShell (Az)
Bash-friendly; works well with jqObject pipeline; integrates with PowerShell ecosystem
JSON output by defaultNative objects; ConvertTo-Json when needed
One executable, faster startupPowerShell module; slightly slower load
Identical underlying API coverageIdentical underlying API coverage

Use what your team prefers. Many shops use both — Az CLI in Bash CI pipelines, Az PowerShell in Windows / runbook scenarios.

Best Practices

  1. Pin module versions in production scripts (#Requires -Modules @{ ModuleName="Az"; ModuleVersion="11.0" }).
  2. Use Managed Identity wherever possible.
  3. Set the context explicitly at the top — never assume the right subscription is active.
  4. Wrap destructive operations in -WhatIf support so callers can dry-run.
  5. Use Resource Graph for cross-subscription queries — orders of magnitude faster.
  6. Keep up with monthly Az releases — new resources land in preview versions first.

Az covers Azure resources. The Microsoft 365 side — users, groups, mailboxes, Teams, SharePoint — is the territory of Microsoft Graph, the next lesson.

Key Takeaways

  • Az is the modern, cross-platform Azure PowerShell module; AzureRM is deprecated.
  • Connect-AzAccount → Set-AzContext → run cmdlets — that is the workflow.
  • Cmdlets follow Verb-AzNoun: Get-AzVM, New-AzStorageAccount, Set-AzRoleAssignment.
  • Use service principals or Managed Identity for non-interactive (CI / runbook) auth.
  • Az CLI vs Az PowerShell — both work; pick by team familiarity.

Test your knowledge

Try exam-style practice questions to reinforce what you've learned.

Practice Questions →