In my experience a decent Azure resource tagging strategy is one of those things that should be defined as early as possible in the life cycle of an Azure subscription.
Depending on the tag schema that’s chosen it’s possible to easily locate similar resources, identify owners and associate billing costs against specific departments.
As mentioned previously I’ve been working with a client where we’ve implemented Azure Policy to enforce certain configuration standards or audit non-compliance.
In our scenario we’ve created a custom Policy definition which audits any resource groups which are missing the following tags -
- Cost Centre
This works as expected, however over 100 policies are also assigned to each of the subscriptions. This means that drilling down into the compliance report within the Azure Portal to identify the resource groups that are missing tags becomes a bit of a chore.
To help alleviate this I’m using the alerting capabilities of Log Analytics to automatically send a notification email when a non-tagged resource group is identified.
Read on to find out how to integrate Azure Policy with Log Analytics alerting.
The implementation of this solution requires several steps. These are -
- Defining and creating the custom tagging Policy
- Connecting the subscription Activity Log to Log Analytics
- Identifying the required Log Analytics query
- Configure Log Analytics alerts
- Testing the Alert Rule
Create custom tagging Policy
There are several built in Azure policies that relate to tagging resources. But there isn’t specifically one for auditing tags on resource groups.
However, with Azure Policy it’s possible to create custom definitions. Being Azure you’ve probably guessed this is via a JSON template. Handily, over on GitHub there’s a custom definition which audits resource groups for missing tags.
There’s a good step-by-step guide here on how to import the policy definition into Azure.
Once we’ve added the custom definition we then assign it to the subscription and specify the tag we want to check for i.e. CostCentre
It’s possible to apply policies at the resource group level but as we want to check for missing tags across all resource groups we apply it at the subscription level.
Each policy assignment only targets one tag and one subscription. So we have to repeat the process and add another policy assignment for the Owner tag and the other subscriptions.
Under the Policy — Assignments blade and filtering for policies containing “tag” we end up with the following —
We have three subscriptions so we end up with a total of 6 assignments (2 per subscription).
If you’re assigning multiple similar policies you can also create initiatives which allows you to easily group and assign policies together.
Okay, let’s check these policies for compliance. We can immediately see that within one of our subscriptions we have a non-compliant resource group —
Clicking on the policy drills down and shows us the resource group that is non-compliant. In this example it’s called dbtest-rg —
By looking at the resource group directly we confirm that it’s missing the tags —
This all works as expected but if you have several resource groups missing tags across multiple subscriptions it’s quite difficult to easily identify the offending resource groups.
Let’s see how to create an email alert that notifies us when non-compliant resource groups are identified.
Connecting the Activity Log to Log Analytics
As part of the Azure Policy evaluation cycle compliance results are recorded within the Azure Activity Log for that subscription.
By connecting the Activity Log to a Log Analytics workspace we can generate alerts when non-compliant resources are identified.
This is straightforward to configure within the Azure Activity log blade for our Log Analytics workspace —
Now all of the Activity Log events will also be pushed through to the Log Analytics workspace.
Identifying the required Log Analytics query
We now have to write a Log Analytics query that will return the resource groups that are missing tags.
This took a bit of experimentation on my behalf to find the exact query. Essentially, the query I ended up with was -
AzureActivity | where OperationName contains “policies” and Properties contains “audit-resourceGroup-tags” and Properties contains “True”
Note: we’re looking for events which contain “audit-resourceGroup-tags” as defined in the policy definition ID. You can check this from the policy definitions blade.
Running the query confirms that we have one resource group that is missing at least one of the required tags. You can ignore the ActivityStatus = Succeeded. This is simply telling us that the policy compliance check was successful, not that the resource was compliant.
Configure Log Analytics alerts
Now that we have a working query we can generate an alert whenever a non-compliance event is logged.
Within Log Analytics we select New alert rule. This displays the following configuration page which we’ll step through —
Clicking on the condition rule allows us to configure the signal logic —
The Log Analytics search query is already pre-populated. The remaining settings we need to configure are -
- Threshold — set this to 0 as we want to alert on any non-compliance events
- Period — how far back in Log Analytics do we want to check for missing tags i.e. 1440 minutes = 24 hours
- Frequency — how often do we want to check for new non-compliance events?
After a policy is applied it’s typically re-evaluated every 24 hours. If a non-compliant policy is still found it will log that same event again. Therefore there’s little benefit in setting the period to more than 24 hours. It’s also possible to reduce the frequency but this will mean you’re getting multiple emails throughout the day reporting the same non-compliant policies.
These are your standard Azure alerting action groups. You can either select an existing one or create a new one.
In this example I’m keeping it simple by creating a new action group to just send myself an email. However, action groups are hugely flexible and can also call webhooks, functions, logic apps etc. —
We now complete the alert details -
Clicking Create alert rule completes the configuration.
The time you create the rule will determine when any alerts will first be sent. For example, as we’ve set the frequency to 24hrs, if we create the rule at 3pm any notification emails will be sent once at 3pm every day.
Testing the Alert Rule
As soon as we create the rule it will run for the first time. If there are untagged resource groups captured in Log Analytics we’ll receive a notification email.
In our example we have an existing resource group, dbtest-rg, that is missing Owner and CostCentre tags. In the email that is received a few minutes later there’s two sections we need to pay attention to.
The first part of the email tells us about the alert that was triggered —
Within the second section of the email are the actual search results i.e. the resource groups with the missing tags —
That’s it! The rule will continue to check Log Analytics every 24 hours for any non-compliant resource groups. In the meantime we can identify the owners of the resource group and correctly tag it. Once complete we’ll no longer receive non-compliance alerts for it.
The good thing about this approach is that we’re using Azure’s native functionality. There’s no need to write scripts or automation runbooks to identify non-compliant resource groups.
We’ve used the example of alerting on untagged resource groups. But this same approach can be used for other audit policies i.e. alerting on when Azure SQL Databases don’t have Transparent Data Encryption (TDE) enabled etc.