Dispatch Azure alerts to Slack with webtask.io

(this article originally appeared on Medium)

A customer recently asked me to improve the integration between his Microsoft Azure account and Slack by adding the ability to dispatch Azure alerts directly to a specific Slack channel.

The origin: Azure alerts

From the Azure portal you can define, for most of Azure’s services, monitoring rules that help you keep a close eye on your application’s health. If you’re using Application Insights, you can also benefit from the Smart Detection’s proactive monitoring rules. By default, the alerts triggered by those rules are dispatched as emails to the Azure account’s administrators. But it’s also possible to make them call webhooks that you specify:

alert configuration in Azure

When triggered, the webhook receives a JSON payload that describes the details of the alert.

The destination: Slack’s webhooks

As described in the documentation of the Slack API, it’s fairly easy to inject messages in a Slack channel by POST’ing, guess what… another JSON payload. Powerful formatting options let you control the design of those messages.

The only thing to do is to set up a webhook integration (following this link), which will give you the URL where the payload shall be posted. All authentication information is embedded within that URL.

The bridge: webtask.io

So all I needed was the ability to forward a POST request to the URL generated by Slack and perform some basic JSON transformation in the middle. This seemed to be the perfect opportunity to play with some serverless technology!

I’ve been following the serverless trend for quite some time and it seems clear by now that it’s much more than a gimmick — although the community has, once again, chosen a poor name to describe what it is (NoSQL anyone?). The ability to deploy and run functions without having to care about server provisioning and capacity planning, and only paying for the time/CPU/memory used by the actual execution of those functions, is really great in a number of situations. And our little webhook project is a perfect use-case.

There are already plenty of serverless solutions available: AWS pioneered the concept with Lambda, Microsoft followed with Azure Functions, IBM is investing heavily in OpenWhisk… But the one I really wanted to try was webtask.io, from the Auth0 guys.

webtask.io is running on Node.js and makes it super easy to write a piece of Javascript and put it behind a URL. Browsing through the documentation, I was surprised to see that it already provides a wealth of useful features: storage, secrets, CRON tasks etc. webtask.io provides a Node.js-based CLI that facilitates the setup of a task, but I took an even easiest path by using their online editor.

Up and running in minutes

The first step was to store the end of the Slack webhook URL in a secret — as it contains authentication information, you don’t want to have it in clear text in your code. Anything you store as a secret can be conveniently retrieved through the context.secrets dictionary.

From there, it was pretty straightforward to construct the payload requested by Slack and post it to the Slack webhook URL:

var request = require('request');

module.exports = function(context, cb) {
  var attachment = {
    fallback: "Microsoft Azure Alert " + context.body.status,
    color: context.body.status == 'Activated' ? "danger" : "good",
    title: "Microsoft Azure Alert " + context.body.status,
    title_link: context.body.portalLink,
    fields: [
        {
            title: "Resource",
            value: context.body.context.resourceName,
            short: false
        },
        {
            title: "Name",
            value: context.body.context.name,
            short: false
        },
        {
            title: "Description",
            value: context.body.context.description,
            short: false
        }
    ],
    ts: Math.floor(new Date(context.body.context.timestamp).getTime() / 1000)
  };
  
  var url = 'https://hooks.slack.com/services/' + context.secrets.url_suffix;
  request({
    method: 'POST',
    url: url,
    json: true,
    body: {
      attachments: [attachment]
    }
  }, function (error, res, body) {
      cb(error, body);
  });
};

Before registering this function in Azure, I quickly tested it by posting a request to this URL and passing the kind of payload that Azure would send. And sure enough, the thing instantly showed up in Slack:

a test alert appearing in a Slack channel

And so all that was left was to register the webhook’s URL in the Azure portal to get those instant alerts… hoping that they won’t show up too often!

Comments