AzClean Toolkit: ten read-only Azure audit scripts
Ten scripts for the checks that account for most avoidable spend and most quiet risk in a small Azure estate. They read, they never write, and they exit non-zero when they cannot reach Azure.
What it covers
Each script answers one question and prices the answer where a price makes sense.
- Orphaned resources. Unattached disks, NICs with no VM, unassociated public IPs, load balancers with an empty backend pool.
- Idle VMs. Machines with no meaningful CPU, network or disk activity over a window you choose, separated from ones that are merely quiet.
- Stale snapshots. Snapshots older than a threshold, including the ones left behind by backup tooling and finished migrations.
- NSG rules. Inbound rules from any source on management ports, rules with no description, and priority collisions.
- Public storage. Accounts and containers permitting anonymous access, and shared access signatures with implausible expiry dates.
- Stale RBAC. Assignments to deleted identities, Owner at subscription scope, and guests with standing access.
- Expiring credentials. App registration secrets and certificates due to expire, with the ones that already have.
- Tag compliance. Resources missing the tags you have decided matter.
- Spend by tag. What each cost centre or environment is actually costing.
- Inventory. What exists, where, and at what SKU.
Sample output
__ _ ______ ___| | ___ __ _ _ __
/ _` |_ / __/ __| |/ _ \/ _` | '_ \
| (_| |/ / (__\__ \ | __/ (_| | | | |
\__,_/___\___|___/_|\___|\__,_|_| |_|
AzClean v1.0.0 // Orphaned Resource Finder
by ACloud.Solutions
--------------------------------------------------------------
Type Name USD/month
Managed Disk (unattached) disk-sqlbackup-temp 88.59
Managed Disk (unattached) disk-web01-old 23.85
Managed Disk (unattached) disk-scratch-2021 9.86
Public IP (unassociated) pip-legacy-vpn 3.65
Public IP (unassociated) pip-buildagent-old 3.65
Network Interface (no VM) nic-web01-old 0.00
Load Balancer (no backend) lb-internal-basic 0.00
Snapshot (>365 days) snap-migration-final 7.66
--------------------------------------------------------------
8 findings 137.26
Figures are for prioritising work, not for billing.
Costs come from the Azure Retail Prices API per region rather than a hardcoded table. Managed disks are priced by provisioned tier, which is the detail that makes the difference: a 128 GB Premium SSD bills as a P10 whatever is on it, and a flat per-GB estimate understates it by roughly 3.7x. The note on disk tier pricing works through the arithmetic.
Scope
Scope is a parameter, not an assumption. Point it at one subscription, a named list, or every subscription your account can see. The output is one CSV per check plus a combined summary, which is what AzClean Reporting turns into something you can send to somebody.
Permissions
Reader at the scopes you want covered, plus directory read for the credential and RBAC checks. Nothing needs Contributor. If a script asks you for write access, it is not one of ours. Microsoft's Azure built-in roles reference lists what Reader actually permits.
Questions
Will it change anything in my subscriptions?
No. Every script is read-only by design, not by configuration, so there is no flag to set and nothing to get wrong. It cannot delete, resize, stop or reconfigure anything.
What happens if it cannot authenticate?
It exits non-zero and says so. This matters more than it sounds: a cost tool that loses its token and reports "no findings" has produced a clean bill of health from an empty search, which looks like good news. "Found nothing" and "could not look" are different outcomes here.
Do I need the Az PowerShell module?
Yes, and PowerShell 5.1 or later. The scripts check for what they need and tell you what is missing rather than failing halfway through a subscription.
Can I run this against a client estate?
That depends on your licence tier. Consultant redistribution is covered explicitly, and the tiers differ on whether you may run the tools against client estates and hand the deliverables to those clients. The full terms ship inside the download.
How is this different from Azure Cost Management?
Cost Management tells you what you were charged last month. This tells you what you are still being charged for and why, which is the question you need answered in order to decide what to delete. Use both: this to build the list, Cost Management to confirm the effect.
Further reading
The reasoning behind several of these checks, in more detail than a product page should carry:
- Azure managed disk pricing: you are paying for the tier
- Orphaned Azure resources: an inventory of the forgotten
- Idle Azure VMs: the servers thinking about it since 2021
- Azure snapshot cost: a museum of disks nobody visits
- An Azure tagging strategy people will actually follow
- NSG rules: the any-any that was definitely temporary
- Azure storage account public access
- Azure RBAC review: the Owners who left in 2022
- App registration secrets expire at 3am on a Saturday