Azure cost & security
AzClean: Azure Cost & Security Toolkit
Ten read-only PowerShell scripts that find wasted Azure spend and security misconfigurations — and price the waste the way Azure actually bills it.
PowerShell 5.1 or 7+ · Reader covers most of it · nothing is deleted or modified · see why the numbers differ
__ _ ______ ___| | ___ __ _ _ __ / _` |_ / __/ __| |/ _ \/ _` | '_ \ | (_| |/ / (__\__ \ | __/ (_| | | | | \__,_/___\___|___/_|\___|\__,_|_| |_| AzClean v1.0.0 // Orphaned Resource Finder by ACloud.Solutions ------------------------------------ [*] Scope: all enabled subscriptions - 2 subscription(s) [*] (1/2) Scanning Contoso-Production [!] Found 8 orphaned resource(s) - est. 137.26 USD/month wasted Priced using: Azure Retail Prices API (USD) ResourceType Name Est USD/mo ---------------------------------- ------------------- ---------- Managed Disk (unattached) disk-sqlbackup-temp 88.59 Load Balancer (empty backend pool) lb-staging-old 18.25 Managed Disk (unattached) disk-web01-old 23.85 Public IP (unassociated) pip-old-appgw 3.65 Load Balancer (empty backend pool) lb-dev-legacy 0.00 Basic SKU is free Managed Disk (unattached) disk-scratch-01 n/a PremiumV2
Real output. Contoso-Production is a fictional example tenant.
Most cleanup scripts guess. This one doesn't.
Nearly every orphaned-resource script multiplies disk size by a flat per-GB rate. Azure doesn't bill that way. Managed disks bill by provisioned tier, so a 128 GB Premium SSD is one P10 whatever it contains — and a 100 GB disk costs exactly the same as that 128 GB one.
| Disk | Azure bills | Flat per-GB guess | Understated by |
|---|---|---|---|
| 128 GB Premium SSD | $23.85 P10 | $6.40 | 3.7× |
| 512 GB Premium SSD | $88.59 P20 | $25.60 | 3.5× |
| 100 GB Premium SSD | $23.85 still P10 | $5.00 | 4.8× |
Priced per region
Live figures from the public Azure Retail Prices API, for each resource's own region, in your billing currency.
Basic load balancers are free
So they're costed at zero, not billed at Standard rates to inflate a total.
No invented numbers
Premium SSD v2 and Ultra show n/a, because they bill IOPS and throughput separately.
UK South list price. Estimates ignore reservations, savings plans and negotiated discounts — they're for prioritising work, not billing.
Ten scripts. Point them at a subscription.
Cost
-
Get-OrphanedResources
Unattached disks, unused NICs, idle public IPs, empty load balancers -
Get-IdleVMs
Running VMs sitting at near-zero average CPU -
Get-OrphanedSnapshots
Disk snapshots nobody deleted, with incremental ones flagged -
Get-CostByTag
Month-to-date spend broken down by any tag key -
Test-TagCompliance
Resources missing your required governance tags
Security & access
-
Test-NSGRules
Rules open to the internet on sensitive ports, including port ranges -
Find-PublicStorageAccounts
Accounts and containers with public blob access -
Get-StaleRBAC
Assignments for disabled or deleted users, high-privilege guests -
Get-UnusedServicePrincipals
Expired credentials, SPs with no role assignments anywhere in scope -
Get-ExpiringCredentials
Key Vault secrets and certificates, app registration credentials
It only reads
Every Azure call is a Get-. Nothing is created, modified or deleted. What you do with the findings is your call.
It won't lie to you
Expired session or an unreadable scope? It says so and exits non-zero. It will never report a clean estate because it failed to reach Azure.
One, several, or all subs
Name a subscription that doesn't resolve and it stops rather than quietly scanning less. Your original context is always restored.
Two editions. Both in every purchase.
Single File Pack
Every script completely self-contained. Paste one into an Azure Automation runbook or drop it on a jump box and it runs — no shared module, no folder layout to preserve.
All-in-One Bundle
Shared code in the AzClean module with thin scripts. About a third less code to read when you customise, and the helpers are importable and testable on their own.
Same parameters, same exit codes, same output. Both generated from one source, so they can't drift apart.
Pick your licence
Same code in every tier. What changes is what you're allowed to do with it. Lifetime updates on all three, with no subscription and no renewal.
Single Organisation
For your own estate
$29
one-time · lifetime updates
- All ten scripts, both editions
- Your own tenants and subsidiaries
- Modify it freely, commercial use included
- Lifetime updates
Consultant
For client engagements
$149
one-time · lifetime updates
- Everything in Single Organisation
- Run it against client tenants
- Hand clients the reports and CSVs
- Leave a copy in their environment
One hour of your time usually costs more than this.
Get ConsultantRedistribution
For building on
$749
one-time · lifetime updates
- Everything in Consultant
- Embed it in products you sell
- Ship to any number of your customers
- Full source and build system included
A licence to build on, not to resell as-is.
Get RedistributionWhat each licence allows
| I want to… | Single | Consultant | Redist. |
|---|
No tier permits publishing it publicly or reselling it as a standalone script pack. Full terms ship in every download.
Get AzCleanQuestions
Will it delete anything?
No. Every Azure call is a read. There is no code path that creates, modifies or deletes a resource — the only writes are switching your local subscription context, which is restored when the run finishes.
What permissions do I need?
Reader covers most of it. The RBAC, service principal and credential scripts need Entra ID directory read, which is a separate permission plane; the storage scanner wants Storage Blob Data Reader to enumerate containers. The readme lists exactly which script needs what, and any script that can't read a scope tells you the scan was incomplete rather than reporting it clean.
Can I run it on a schedule?
Yes. Every script takes -ExportCsv and returns 0 for nothing found, 1 if it couldn't run, and 2 when there are findings to review. The single-file edition exists precisely so one script can be pasted into an Azure Automation runbook.
Isn't Azure Advisor free?
It is, and it's worth using. AzClean does things it doesn't: accurate provisioned-tier pricing rather than raw size, security findings alongside cost, one run across every subscription, CSV output you can hand to a client, and source you can change. Take the free script, run it against an estate you know, and see whether the numbers match what you already had.
What does "lifetime updates" cover?
Fixes and Azure/Az compatibility for the tools included, for as long as AzClean is published, on every tier. Azure prices move and the Az modules ship breaking changes regularly, so this is the part that matters. No renewal and no subscription.
Does it work on Windows PowerShell 5.1?
Yes. There's no PowerShell 7-only syntax anywhere, the files are pure ASCII so nothing mangles on 5.1, and the pricing lookup raises TLS to 1.2 explicitly, because 5.1 otherwise negotiates a version the pricing API refuses.
The rest of the family
Built by the same person, on the same terminal, with the same read-only-by-default rule.
AzClean Detections
View →Sentinel drift & escalation
Twelve validated Sentinel rules for the misconfigurations AzClean finds at rest, caught as they happen.
AzClean Baselines
View →Intune config & drift
Export Intune policy to JSON, commit it, and get told exactly which property drifted.
AzClean Reporting
View →Client-ready output
Turn AzClean CSV exports into an HTML report, a Markdown summary and a Teams or Slack digest.
Orphaned Resource Finder
View →Free edition
One script, free for internal use. Finds the disks, NICs, IPs and load balancers nobody deleted.
Find out what you're paying for nothing
Ten scripts, both editions, lifetime updates.