CreatorTagger – A Whodunnit

“Be careful which rocks you look under…”

I had a thought the other day. Probably not a very good one, but it led to some tinkering. I wondered if it would be possible to leverage Azure Policy to add a tag to a resource denoting who built it. There are some limitations to both Activity Log and Log Analytics Workspace (for sending logs), and while the resource group deployment events are available, the “who did it” seems lacking.

As it turns out, no. You can’t use Azure Policy yet to do this specific task. But Anthony Watherston wrote a unique solution to this leveraging an Event Grid Subscription, sending Write events to an Azure Function, which will tag the resource. See his full blog post titled “Tagging Azure Resources with a Creator” – it’s quite good, and he has some code available for deploying the solution.

What I wanted to do though was manually build the bits. I’ve supported other people’s Azure Functions, but haven’t deployed my own. I’ve looked at Event Grid, but never Subscriptions. So rather than take Anthony’s code and just deploy it, I poked at things to recreate it manually. This ultimately helped me understand all the parts and pieces, which then helped me understand his code more easily.

Note: I’ve paired this blog post with a YouTube video demonstrating the process. It should be worth noting I’m still learning about video editing, so judge accordingly!

Creating the Function App, we’re leveraging PowerShell Core as the runtime.

Function Apps want a storage account for storing function code and other configuration files. As with nearly everything Azure-related, Microsoft has a good set of documentation around considerations for the storage account. I’ve opted to create a new storage account for this. Mostly because my lab doesn’t have any shared accounts, but also because I prefer the isolation. Microsoft even recommends a single storage account for each function app in production for performance reasons (though I’m sure there are security benefits as well).

The rest of the settings were kept as default and then deployed.

Once deployed, the first thing to do is enable a System assigned managed identity on the Function App. This managed identity will be the account under which tag actions take place.

In order to actually do that work, it’s going to need permissions. I’ve scoped the permissions at the subscription level by creating two new role assignments for Read and Tag Contributor

With the permissions established, the next step is to actually create the function. I stumbled a few times with this, but on the Overview page of the function you can add it here

The function will be triggered by an Event Grid action, and as you can see I just used the default name for the actual function itself.

One of the things that tripped me up a little bit was the requirement for the Az module for PowerShell. It tripped me up because I didn’t quite understand where that import needed to take place until I poked around and found the requirements.psd1 file located in the App Files section.

The entire Az module is massive, and it’s good practice to import only what you need. From line 5 of the code they point you to https://www.powershellgallery.com/packages/Az, where we can locate the latest major version of the two modules needed.

The last thing to do with the Azure Function is to plop in the code to do the tagging work. I’m not going to replicate the code here, as the kudos need to go to Anthony for coming up with a workable script (you can find all this code on his page). I simply copy/paste the code into the function and made a single change. I preferred the output in the commented-out line 3 to the uncommented line 4.

So, swapping those two lines, I saved the function.

The last thing to do is set up the Event Grid Subscription which will send notifications to the Function App.

In the screen above, the Topic describes where we’re going to get events from. For my example I want subscription-wide events. By default, there are 9 event types that can be collected. Remove all but “Resource Write Success”, which is all we care about. If someone successfully deploys a resource, that’s when it’ll need a tag.

Finally, the endpoint type is the Azure Function, and when you click the “Configure an endpoint”, it’s simply a matter of targeting the Azure Function we built. And that’s…..all it took!

Oh bugger.

If you run into the above – don’t panic. Turns out, the Microsoft.EventGrid resource provider in my subscription was not enabled. If this happens to you, browse to your subscription, click the Resource Providers blade, and filter for the Event Grid. Here’s what mine looked like at the time of the above error:

Highlight the Microsoft.EventGrid, click Register above, and it takes about a minute or so to enable.

Lastly, the test. I built a plain old Virtual Network

The above view is immediately after creation – the Virtual Network has a costcenter tag, which it had inherited from the Resource Group. After another minute or so (probably less, actually), the new tag appeared with my name as the creator:

I like this for a number of reasons. In Azure, tags are case-sensitive. So if you allow people to edit/update tags manually, you’ll find “John Doe”, “john doe”, “doe, john”, or even “JohnDoe” all as separate unique tag values. This takes that inconsistency out of it (in fact, the tag name and value could be sent through a string ToLower() function just to force some consistency in formatting).

This was a fun exercise and got me thinking a bit about Function Apps a little more – and a pretty inexpensive solutions as well!

Leave a Reply

Your email address will not be published. Required fields are marked *