Write an Azure Function to Query Active Logs

I wrote an Azure function in the last 2 days with C#, since I’m quite a beginner of both Azure and C#, I thought it’s a good chance for me to note down the process of development.

Creating an Azure Function

This is quite straightforward, after login I can simply create a Function App (where functions are grouped together) under the target resource group, and then go for ‘create function’ under the function app. Here we can also go for different options of function, I just went right for the ‘HTTP trigger’ template.

Getting Active Logs through Azure Monitor API

To get active logs of a certain resource group, we will need to go through the Azure Monitor API, to initiate a request to get Active Logs from a period of time, we will want to add following parameters:

subscriptionId: we can easily find it at the target resource group:

$filter: as the requirement is to query Active Logs from a period of time of the a resource group, we can easily follow the example given in the Azure document:

$filter=eventTimestamp ge ‘2014–07–16T04:36:37.6407898Z’ and eventTimestamp le ‘2014–07–20T04:36:37.6407898Z’ and resourceGroupName eq ‘resourceGroupName’.

As the requirement for me is to retrieve from the last 90 days, I decided to create 2 DateTime objects with one as current DateTime and another one adding 90 days back. With some other parameters such as resourceGroupName appended to the Url, our filter should be working:

$select: the select parameter allows us to select certain fields of the Active Logs, and again we can simply follow the Azure document to list attributes we want in a comma-separated format: authorization, claims, correlationId, description, eventDataId

Now we are pretty much ready to retrieve the Active Logs in our function, we can test our request again through the online editor here.

Getting Access Token For the Request

Since the access token had an expiration time, we will want to make sure every time when we make the request we always had a valid token to communicate with the endpoint.

According to the document, all requests must be authenticated with Azure Active Directory (Azure AD), and we will need to retrieve the token after creating an AD service principle so that we can use it to talk to the Azure Management API. Since I was given the credentials and tenant id, it’s easy to call “https://login.microsoftonline.com/{tenantId}/oauth2/token” to get the bearer token. We can also test it with Postman:

After getting the token, we can start using it to make our call to the Monitor API.

Handling Json in Azure Function

Most of the time I worked with JSON using PHP or Javascript, it's a bit of a headache for me to start handling it in C#. I will just document my solution down here even though it’s not very likely to be a good one : )

After getting the response and retrieve it with the ReadToEnd() function, we will get a string (serialized json). After some research I decided to go with Json.Net as it seems to be an easy option.

We can use JsonConvert.DeserializeObject() to deserialize the string, and create a JObject to hold it. Here we can make our first validation to see if the piece of data we got is empty by checking if the newly created JToken object has values in it. If there was no activity found within the time range, or in the other word the response is {value = []}, we can set the return value to null for the function.

To find the latest activity within 90 days, I iterated through the Json array and used DateTime.Compare() to compare the activity timestamp and the latestDate. The code is quite self-explanatory: when the newest timestamp is found it will be stored along with the object that comes with it.

In the end, a serialized object of the latest will be returned:

Incorrect TimeZone: Something I Haven’t Figured Out Yet

While testing I find the DateTime.Now and DateTime.UTCNow both returns datetime with incorrect timezone. I tried a couple of solutions:

  1. Add WEBSITE_TIME_ZONE setting to function app

2. Use other time zone value if one doesn’t work (none of them seems to work for me tho)

List of time zone value accepted by Azure:

https://jackstromberg.com/2017/01/list-of-time-zones-consumed-by-azure/

3. Clear Cache

4. Manually convert the time zone

None of these solutions works for me even though they seems to solve the problem for a lot of people:

I will keep researching on this issue : )