Ruling Your Resource Groups with an Iron Fist

23 Aug

If it is not obvious by now, we deploy a lot of resources to Azure.  The rather expensive issue we encounter is that people rarely remember to clean up after themselves; it goes without saying we have encountered some staggeringly large bills.  To remedy this, we enforced a simple, yet draconian policy around persisting Resource Groups.  If your Resource Group does not possess values for our required tag set (Owner and Solution), it can be deleted at any time.

At the time the tagging edict went out we had well over 1000 resource groups.  As our lab manager began to script the removal using the Azure Cmdlets we encountered a new issue, the synchronous operations of the Cmdlets just took too long.  We now use a little script we call “The Reaper” to “fire and forget”.

If you read my previous post about Azure AD and Powershell, you may have noticed my predilection for doing things via the REST API.  “The Reaper” simply uses the module from that post to obtain an authorization token and uses the REST API to evaluate Resource Groups for tag compliance and delete the offenders asynchronously. There are a few caveats to note; it will only work with organizational accounts and it will not delete any resources which have a lock.

It is published on the PowerShell gallery, so if you can obtain it like so:

#Just download it
Save-Script -Name thereaper -Path "C:\myscripts"
#Install the script (with the module dependency)
Install-Script -Name thereaper

The required parameters are a PSCredential and an array of strings for the tags to inspect.
Notable Switch parameters are AllowEmptyTags (only checks for presence of the required tags) and DeleteEmpty (removes Resource Groups with no Resources even if tagged properly).
There is also a SubscriptionFilters parameter taking an array of Subscription id’s to limit the scope, otherwise all Subscriptions your account has access to will be evaluated.
If you would simply like to see what the results would be, use the WhatIf Switch.
Usage is as follows:

$Credential=New-Object PSCredential("username@tenant.com",("YourPassword"|ConvertTo-SecureString -AsPlainText -Force))
$results=.\thereaper.ps1 -Credential $Credential `
    -RequiredTags "Owner","Solution" -DeleteEmpty `
    -SubscriptionFilters "49f4ba3e-72ec-4621-8e9e-89d312eafd1f","554503f6-a3aa-4b7a-a5a9-641ac65bf746"

A standard liability waiver applies; I hold no responsibility for the Resource Groups you destroy.

Chris Speers

Systems Engineer Par Excellence within Avanade’s Azure Cloud Enablement Group.

LinkedIn