Let’s monitor that cloud!

It can’t be just a coincidence that recently many of my friends expressed interest in monitoring how their teams are using their cloud subscription. And yet, all of them have a valid problem to worry about! Let’s talk about this problem, scenario, and solution in this last blog post of 2018 :)


A subscription is shared with the team or each member has a separate subscription. Anyone can create any kind of resources (e.g. Virtual Machines, Storage Accounts, Network Security Groups, Web or Application Services, etc…). Even though there are policies and access restrictions which can be forced in Azure Portal, sometimes Administrators or Support engineers require (or literally they ask for) ‘God Mode’ with full access to play around, explore services or fix some things. In this case, monitoring these activities happened in ‘god mode’ & quick remediation or reversal is important before any damage happens.


Sometimes, developers often need to create resources to try out things. For example, they may want to create a Storage Account. Now, we want to enforce rules around Storage Account and make sure that the created Storage Account is accessible only via HTTPs protocol. Or let’s say Network Admin creates a Network Security Group (NSG) and in that case, the policy is to disable or enable specific ports or protocols (UDP/TCP/etc).


I consider Azure Services as Lego blocks. You can mix and match and use them together as and when required. In this case, there are multiple ways to handle this scenario and possibly many more. There could be operations team managing this infrastructure using their custom tools. However, being a developer, I’ll focus on two solutions from a developer’s point of view. And I can see there are two easy solutions:

(1) Whenever a resource is created (or executed like Logic App trigger) or modified or deleted within a subscription, a record is maintained at subscription level and resource group level. This log can be further exported to different Azure services to take action. For example, it can be exported (or streamed) to Event Hub for event publishing.

(2) Using Azure Monitor set up a trigger to such records (create, update, delete resources) and take action (Notify by Email/Text, call Logic App, Functions, etc…)

Once these pipelines are set up, these services (Event Hub/Activity Log) will send data in JSON format which can be used to track down what has happened.

"schemaId": "Microsoft.Insights/activityLogs",
"data": {
"status": "Activated",
"context": {
"activityLog": {
"authorization": {
"action": "Microsoft.Storage/storageAccounts/write",
"scope": "/subscriptions/<subcription-id-hidden>/resourceGroups/SubscriptionMonitoring/providers/Microsoft.Storage/storageAccounts/submonstore"
"channels": "Operation",
"claims": "<removing-details-for-brevity>",
"caller": "<email-id-hidden>",
"correlationId": "ca9bcd00-ecd2-42f3-9bfe-8aafe7ef9b21",
"description": "",
"eventSource": "Administrative",
"eventTimestamp": "2018-12-25T03:27:00.3969244+00:00",
"httpRequest": "{\"clientRequestId\":\"6a543b9d-601d-48d2-b4a5-295c95f67003\",\"clientIpAddress\":\"\",\"method\":\"PUT\"}",
"eventDataId": "72b33715-169f-483a-af00-0f06d47ddc12",
"level": "Informational",
"operationName": "Microsoft.Storage/storageAccounts/write",
"operationId": "ca9bcd00-ecd2-42f3-9bfe-8aafe7ef9b21",
"properties": {
"statusCode": "OK",
"serviceRequestId": "f833dc6e-4a65-4c74-a923-4bf896b1e53f",
"resourceId": "/subscriptions/<subcription-id-hidden>/resourceGroups/SubscriptionMonitoring/providers/Microsoft.Storage/storageAccounts/submonstore",
"resourceGroupName": "SubscriptionMonitoring",
"resourceProviderName": "Microsoft.Storage",
"status": "Succeeded",
"subStatus": "OK",
"subscriptionId": "<subcription-id-hidden>",
"submissionTimestamp": "2018-12-25T03:27:22.0940445+00:00",
"resourceType": "Microsoft.Storage/storageAccounts"
"properties": {}

This JSON has required information like resource id and resource type. In this case, I’m using Logic App to parse this JSON and accordingly call respective Azure Function which will take the action (by calling Azure Functions). I’m considering two scenarios here. (A) when new Storage Account is created and (B) when new Network Security Group is created/modified with Rules. But there can be many such scenarios!

Now according to the case (NSG/Storage Account), it will call the Azure Function. To modify the resources in subscription, I’m using Fluent APIs which makes life much easier. For example the following code creates a VM using Fluent APIs in US East Region within rgName provided:

var windowsVM = azure.VirtualMachines.Define("myWindowsVM")
view raw CreateVM.cs hosted with ❤ by GitHub

Using these Fluent APIs, let’s write Azure Function which will monitor newly created Storage Account and make sure that it is accessible only with HTTPs protocol.

using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.Management.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Microsoft.Azure.Management.ResourceManager.Fluent.Core;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Logging;
using Microsoft.Rest;
using Newtonsoft.Json;
namespace SubscriptionMonitoringFunctions
public static class StorageHttpsPolicyFunction
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
string requestData = string.Empty;
Rootobject rootData = null;
string subscriptionId = string.Empty;
string storageAccountName = string.Empty;
string resourceId = string.Empty;
string outputStatus = string.Empty;
log.LogInformation("StorageHttpsPolicy: Begin to read activity log");
outputStatus += $"\n StorageHttpsPolicy: Begin to read activity log";
requestData = await new StreamReader(req.Body).ReadToEndAsync();
rootData = JsonConvert.DeserializeObject<Rootobject>(requestData);
if (rootData.data.context.activityLog.resourceType.Contains("storageAccounts"))
subscriptionId = rootData.data.context.activityLog.subscriptionId;
log.LogInformation($"StorageHttpsPolicy: Found Subscription Id {subscriptionId}");
outputStatus += $"\n StorageHttpsPolicy: Found Subscription Id {subscriptionId}";
resourceId = rootData.data.context.activityLog.resourceId;
log.LogInformation($"StorageHttpsPolicy: Found Resource Id {resourceId}");
outputStatus += $"\n StorageHttpsPolicy: Found Resource Id {resourceId}";
storageAccountName = rootData.data.context.activityLog.resourceId.Substring(resourceId.LastIndexOf("storageAccounts") + 16).Split("/")[0];
log.LogInformation($"StorageHttpsPolicy: Found Storage Account: {storageAccountName}");
outputStatus += $"\n StorageHttpsPolicy: Found Storage Account: {storageAccountName}";
var token = Authenticate().Result;
var credentials = new AzureCredentials(new TokenCredentials(token), new TokenCredentials(token), string.Empty, AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Configure().WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic).Authenticate(credentials).WithSubscription(subscriptionId);
var storageAccounts = azure.StorageAccounts.List();
var storageAccount = storageAccounts.FirstOrDefault(x => x.Name == storageAccountName);
log.LogInformation("StorageHttpsPolicy: Policy application successful");
outputStatus += $"\n StorageHttpsPolicy: Policy application successful";
outputStatus += $"\n StorageHttpsPolicy: Couldn't find Storage Account";
catch (Exception x)
log.LogInformation("StorageHttpsPolicy: Policy application failed");
outputStatus += $"\n StorageHttpsPolicy: Policy application failed with {x.Message}";
return outputStatus != null
? (ActionResult)new OkObjectResult(outputStatus)
: new BadRequestObjectResult("Error in execution of this policy");
public static async Task<string> Authenticate()
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com").ConfigureAwait(false);
return accessToken;

In the above code


makes sure that Storage Account is accessible with HTTPs protocol only.

One last thing before executing this function or enabling Logic App, give permission to this Azure Function to modify resources. It can be done by creating and passing service principal or by using Managed Identity option. More details are here on this blog post.  Managed Identity helps to avoid storing credentials in code.

Once this setup is complete, whenever Storage Account or Network Security Group is created, modified & updated, the Logic App will execute and call the respective Azure Function.


Using these various Azure Services, it is possible to monitor the subscription and perform actions on resources as per the rules. This makes governance easier. The sample and code used for Azure Functions in this blog post is available on GitHub here. Clone it and follow the steps there to deploy and run it in Azure subscription.

The Case of Custom Ouf Of Office

In 2006-07, when I was writing Windows Mobile apps, I really enjoyed using MessageInterceptor type. Using that, we could build our own workflows based on Text Messaging. For example, send an SMS to the device and if SMS contains “Play”, play a song. If SMS contains “Stop”, stop playing the song. And what not. Oh, and I could say if the message is from my parents, reply “I’m in college” and if from friends reply as “I’m waiting outside the movie theater”.

However, I missed this functionality for a long time with different devices (lack of message intercepting API on some platforms). And recently I eagerly wanted to have it for the email, considering the heavy influx of emails in my new role. I got to know about Azure Logic App Service and thought, perhaps let’s go ahead and build something similar. And for me, this is a fantastic way to learn something new.

Scenario: Let’s build a solution which will read incoming email messages and if the message is from one particularly annoying friend, let’s reply with an equally annoying message. If it is from my manager, let’s reply with some positive update and if from a customer we’ll reply with actual OOF. Well, a lot of email service providers allow you to setup OOF, but it is not customizable for different emails. Outlook in Office 365 allows 2 separate OOF messages, one for members within your organization and one for outside organization. Our solution will provide more customizations.

Step 1: Create Azure Logic App Service

Navigate to Azure Portal and Create a resource. Search for Logic App and click on ‘Create’. Give it a name, select the subscription, create Resource Group and finally select a location near to you.

01. Create Logic App

Once Logic App is created, scroll down the next screen and click on ‘Blank Logic App’. This will allow you to add the logical functionality to the just created app.

02. Blank Logic App

Step 2: Design Logic App – Use Connector & Trigger

Connectors allow you to connect your logic app with the desired service. In our case, we’ll use Office 365 Outlook connector to connect to the mail service. And once you connect to the service, there will be a Trigger to activate the logic app. Again, in our case, it will be an email arriving in our inbox.

03. Logic App Connector &amp; Trigger Webhook

Once you select the connector and trigger, sign in with your credentials and connect the email service with your logic app.

Step 3: Setup the Rule and Switch Case

On this screen select the folder in your mailbox to monitor and other aspects of the email. Click on ‘+ Next step’ and write define your logic.

04. Logic App Switch Case

Depending on the connector selected, you’ll see different options for the switch case. For example, in case of Outlook connector and Email trigger, there can be conditions to check for who has sent the email, if it has attachments, if it has importance set or if it has been sent directly to me or to any distribution list to which I’m subscribed.  These conditions will vary depending on trigger and connector.

05. Logic App Switch Options

Once the Switch is set, let’s set up the cases. Here, I’m checking if the email is from Vikram (Oh, he isn’t the annoying friend :) ) and setting up a reply for him. I can also repeat this for many more senders.

06. Logic App Case Vikram

The next one is for my manager Joao,

06. Logic App Case Joao

You can add as many cases as you want and ultimately add a default case. At the end, the logic app designer will look something like this:

06. Logic App Entire Logic

Finally, once this step is done, Run the logic app and wait for the magic to happen :)

07. Logic App Run

In this situation, if a user sends you an email and if the user falls under the cases, the user will receive the response accordingly and if not, user will receive the default response.


Logic Apps Service makes it easy to write workflows and automate tasks. And even though we used Logic Apps for email workflow, there are connectors available for different services which you can find here. If this list doesn’t cover your service, you can write one on your own connector and documentation for the same is available here.
Don’t forget to ‘nuke’ the resource group once done with it or you’ll keep replying to all your emails – automagically. :)

Happy coding (or designing workflows :) ).
Mayur Tendulkar








Xamarin.Forms And The Case of Failed NuGet Packages – Part 2

Most enterprise mobile apps require enterprise-level authentication mechanism. In that case, people use tried and tested Active Directory Authentication Library (ADAL) or Microsoft Authentication Library (MSAL). ADAL is in GA and it works fine with cross-platform mobile apps built using Xamarin. However, MSAL is in ‘preview’ and it offers nightly builds to try out. I wanted to try the latest nightly build (ver: 1.1.1-alpha0417) as it uses updated Android Support Package and old preview bits of MSAL (ver: 1.1.0-preview) were not compatible with latest  Xamarin.Forms anymore. Here, I was trying to build one app over holidays and I got stuck on one interesting issue. Let’s discuss it in this blog post.

The Problem:

When you create a blank Xamarin.Forms app, it automatically references Xamarin.Forms NuGet along with all the required dependencies.

At this time, when you’ll try to install MSAL, you may get stuck at this issue of versioning.

The reason being Xamarin.Forms NuGet requires a specific version of Android Support Packages whereas Microsoft Authentication Library requires anything above Ver. 25.3.1.

The Solution:

Sometimes, things are very simpler than it looks. I spent a lot of time on solving this issue but was unable to fix it. Thanks to my friend Nish, who helped me with his ‘ problem-solving skills’ and we got this working.

The solution is simple:

  1. Remove all NuGet packages from Android project. For the sake of it, close and restart Visual Studio.
  2. Open the solution and Install MSAL NuGet package first.
  3. After installing MSAL NuGet, install Xamarin.Forms NuGet package.


Now you can build Xamarin.Forms apps with Microsoft Authentication Library. If you want to know more about how to use the SDK, follow the blog post here on Xamarin blog.

Even though I’m talking about Xamarin.Forms and MSAL here, this blog post is very much applicable wherever you’re trying to use any NuGet package which has updated dependency on Android Support Package.

Setup info:
Visual Studio Enterprise 2017 Preview (15.5.2)
Xamarin (
Xamarin.Forms (
Microsoft Authentication Library (1.1.1-alpha0417)

Mayur Tendulkar