Unused Azure Resource cleanup

When using Azure as your development platform, or to play with.. you eventually find yourself deleting resources 1 by 1 or entire resource groups.. cause when you delete a VM in ARM (the new portal), it deletes only the VM, but leaves the VHD, the NIC, the public IP, and NGS’s… so what if you could run a script that looks at the unused resources and deletes them for you?

well, look no further.. (but develop with me, based on) the initial script I wrote.. AzureCleanUp.ps1

<Last update April 2017>

The script is available -> AzureCleanup-v3 <-and requires Azure CMD’lets version 1.5.x (although earlier or later versions may also work) which are available here (latest version updated April-19-2017 includes logging -log $true and searches in http and https format for VM data disks and now actually deleted the blob without specifying the container again, skips containers used for Network Watcher.. and some minor bug fixes)

For your safety the script has some features built in that ensure that you don’t delete everything at once in fact, the default mode is to scan only.. and not delete

How do I use it?

The script has 3 parameters (1 mandatory):

     -Mode [mandatory]

Network : will run on network components only (see below)
Storage : will run on storage accounts only  (see below)
Full : Network + Storage  (see below)

-ProductionRun [optional] [default = $false]

$false : runs the script in test mode, will not delete anything, but will provide you with an overview of what WOULD HAVE been deleted or marked for deletion
$true : runs the script in delete mode, items not used will be deleted. For some items additional verification will be required (such as Storage Accounts, Containers, Virtual Networks etc..)

     -Login [optional] [default = $false]

$false : will ask for login credentials upon start (if you have not logged on using Add-AzureRMAccount)
$true : skips the authentication (if you already logged in to Add-AzureRMAccount)

     -Log [optional] [default = $false]

$false : will not create a log file
$true : creates a logfile in form of: AzureCleanLog-19-4-17-10.48.27.log in the current directory

So your initial command is:

AzureCleanup.ps1 -mode full -productionRun $false -log $true

if you are ready to delete

-productionRun $true

What does it do?

The script validates the Azure CMD’lets, and if ok, it will ask for login (unless bypassed). You can login using your credentials after which the script will scan for all subscriptions you have access to.

For each subscription found, you can answer if you want to add it to the scan or not. So you can completely leave out particular subscriptions or add all of them into the scan.

Then per subscription (you selected to be added), it scans the virtual machines and stores some configuration items of these VM’s in arrays in the script. Then the script goes over the resources (based on the mode selected).

Storage: It gathers all storage accounts and

  • Scans if the storage account URL is being used by VM’s
  • Connects to the storage account to go into the account
  • it validates the existence of Tables/Queues
  • if containers are found, it asks for each file in the container if it needs to stay
  • if empty containers are found, it marks them for deletion
  • if used VHD files are found, it will skip (not ask for deletion and block deletion of the storage account)
  • it will also scan for .status files for used VM’s


  • Marked files will be deleted (no confirmation)
  • If empty containers are found they will be deleted (no confirmation)
  • If storage accounts are empty (or everything marked for deletion) it will ask for confirmation for delete


  • Scans (un)assigned Public IP addresses (unused are deleted)
  • Scans unused Network Interfaces (are deleted)
  • Public IP addresses used by Azure Gateway are maintained
  • Used Public IP addresses by unused NIC’s are deleted
  • Scans Network Security Groups
  • Unused Network Security Groups (or used by marked for deletion NICs) are deleted
  • Scans VNETs
  • Validates unused subnets in VNET’s by matching to used VM’s and/or Gateway subnets
  • Unused Subnets are deleted (or matched to deleted NICs)
  • If a VNET is not used or all subnets marked for deletion, it will ask for deletion of the VNET
  • NSG’s connected to deleted subnets are deleted


  • runs Storage first, then Network


When running in test mode (-productionRun $false), the script will at the end of every subscription, show you the output of what would have been deleted, if you want to manually delete it


I want to contribute / I have a problem with the script

The script is available on github so you can make any modifications that you want.. if you have feedback, well.. euh .. I kinda have a mail address.. check the about page.. it has some hints and tips on how to reach me..

just make sure that you are controlling the subscription/resourcegroups with full permissions (or at least read/delete) and that you have the right versions of the CMD’lets installed.