DEV Community

Anthony Buhnerkemper
Anthony Buhnerkemper

Posted on

Azure Governance with PowerShell 7: Tags, Leftovers, Access and Policy in One Toolkit

Azure subscriptions get messy fast.

A VM is deleted, but its disk stays. Nobody knows who owns a resource group. A former employee still shows up in the access list as "Identity not found".

None of this breaks anything today. But it costs money, and it makes audits painful.

So I cleaned up the checks I use and shared them on GitHub. This toolkit uses PowerShell 7 and the Az modules.

Repo: azure-governance-powershell-toolkit

The problem it solves

Resources have no tags, so nobody knows who to ask.

Unattached disks and idle public IPs add up on the bill.

Role assignments pile up. Some point to accounts that no longer exist.

Policy shows red, but nobody knows where to start.

These scripts make those checks quick and repeatable.

Highlight scripts

Get-AzMissingTagReport.ps1

Checks every resource group for your required tags. Add -IncludeResources to check every resource too. Then fix them in bulk with Set-AzTagFromCsv.ps1.

./Get-AzMissingTagReport.ps1 -RequiredTag Owner, CostCenter, Environment
Enter fullscreen mode Exit fullscreen mode

Get-AzOrphanedResourceReport.ps1

Lists unattached disks, old snapshots, unused NICs, unused public IPs and empty resource groups. Anything tagged Keep = true is marked so you can skip it.

./Get-AzOrphanedResourceReport.ps1 -SnapshotAgeDays 30
Enter fullscreen mode Exit fullscreen mode

Remove-AzUnattachedDisk.ps1

Deletes old unattached disks. With -SnapshotFirst it takes a cheap snapshot first, just in case. It asks before every disk.

./Remove-AzUnattachedDisk.ps1 -MinAgeDays 60 -SnapshotFirst -WhatIf
Enter fullscreen mode Exit fullscreen mode

Get-AzRoleAssignmentReport.ps1

Lists every role assignment and flags privileged roles, direct user assignments, guests and orphaned entries.

./Get-AzRoleAssignmentReport.ps1 -PrivilegedOnly
Enter fullscreen mode Exit fullscreen mode

Other scripts cover a full resource inventory, removing orphaned role assignments, Azure Policy compliance and Azure Advisor recommendations.

How the scripts are built

  • PowerShell 7.4 or later.
  • Comment-based help on every script. Run Get-Help ./script.ps1 -Full.
  • Reports export to CSV.
  • Change scripts support -WhatIf and -Confirm.
  • Certificate (app-only) or interactive sign-in for Azure.
  • No secrets in the repo. Examples use contoso.com and placeholder GUIDs.

Please test in a test subscription first. Read each script before you run it.

My usual workflow

Once a month, I run the inventory, the missing tag report and the leftover report.

I send the leftover list to the owners and wait a week. Then I clean up what nobody claims.

Every quarter, I run the access review and keep the CSV for audits.

One tip. Start Azure Policy in Audit mode. Switch to Deny only when the report is clean.

Getting started

Clone the repo:

git clone https://github.com/anthonybuhnerkemper/azure-governance-powershell-toolkit.git
cd azure-governance-powershell-toolkit
Enter fullscreen mode Exit fullscreen mode

Every toolkit ships the same Connect-M365Admin script. Dot-source it, then connect.

# Interactive sign-in
. ./scripts/Connect/Connect-M365Admin.ps1
Connect-M365Admin -Service Azure -Interactive -SubscriptionId 00000000-0000-0000-0000-000000000000

# Or app-only with a certificate
$env:M365_TENANT_ID       = '00000000-0000-0000-0000-000000000000'
$env:M365_CLIENT_ID       = '00000000-0000-0000-0000-000000000000'
$env:M365_CERT_THUMBPRINT = '0000000000000000000000000000000000000000'
$env:AZ_SUBSCRIPTION_ID   = '00000000-0000-0000-0000-000000000000'
Connect-M365Admin -Service Azure
Enter fullscreen mode Exit fullscreen mode

Run a report, check the CSV, then call Disconnect-M365Admin when you are done. The README lists the modules and roles each script needs.

More toolkits

I have more free toolkits that use the same pattern, including azure-backup-dr-powershell-toolkit, entra-id-powershell-toolkit and graph-powershell7-admin-toolkit.

You can find them all on my GitHub profile.

Feedback welcome

Issues, ideas and pull requests are welcome. What would you add? Tell me in the comments.

Top comments (0)