Triggering an Azure Automation Runbook from anywhere

In this post I will explain how we can trigger an Azure Automation Runbook from any device and anywhere by using webhooks and Azure Functions.

This post ties together my two previous posts on Azure Functions and Azure Automation

I often find myself on the move, having to start or stop environments for demonstrations, POCs or development while en route to work or between customer appointments.

While Azure Automation allows me to readily start and stop my environments in a controlled manner, starting runbooks on the go is not so trivial, the Azure Portal is simply not suited for mobile devices.

Adding Webhooks

To begin with you need the runbooks you will trigger using a webhook. You can view my previous post on how to create a runbook for multi-tier IaaS environments.

Once you have created the runbook you can follow these instructions on how to create a webhook. Pay attention: You cannot retrieve the webhook URL after it has been created, you would have to recreate it. Note down the URL for later.

We now have a way to trigger the runbook, however, I promised a way to do this with any device and the Azure Automation Webhook requires a POST which is not trivial. By using Azure Functions as a proxy we can achieve this using any browser by transforming the GET request to a POST request.

Post-Proxy Azure Function

Implementing this functionality in an Azure Function is fairly straightforward. In order to pass the url of the webhook to the Azure Function we are going to use a query parameter url. This means that we are going to have to escape the URL. You can do that using the encodeURIComponent("https://...") function in the console of the developer tools of your favorite browser or in PowerShell using [Uri]::EscapeDataString("https://..."). So https://s2events.azure-automation.net/webhooks?token=123 becomes https%3A%2F%2Fs2events.azure-automation.net%2Fwebhooks%3Ftoken%3D123.

The code below provides the basic functionality for converting a GET to a POST. The Function will forward the requests contents to the URL from the query parameter and returns the output of invoking the webhook, which is in the format {"JobIds":["<JobId>"]}.

public static class PostProxy
{
    [FunctionName("PostProxy")]
    public static async Task<HttpResponseMessage> Run(
        // Allow any GET Request
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestMessage req, TraceWriter log)
    {
        var queryParameters = req.RequestUri.ParseQueryString();
        using (var client = new HttpClient())
        {
            // Make a POST to the URL in the 'url' query parameter using the content from the Azure Function request
            var resp = await client.PostAsync(queryParameters["url"], req.Content);
            // Return the content from invoking the POST
            return req.CreateResponse(HttpStatusCode.OK, await resp.Content.ReadAsStringAsync());
        }
    }
}

Parameters and $WebhookData

When creating an Azure Automation Webhook you can specify the value for any Runbook parameters when it is invoked. Azure Automation Webhooks can also be dynamically invoked using $WebhookData parameters. In order to enable this functionality for our Azure Function we will take all query parameters except url and pass the as the content of the POST.

For details on how to implement this you can view the source for this function. It also demonstrates continuous integration and deployment (CI/CD) for Azure Functions as explained in my other post.

Conclusion

While this post is about a Azure Function for a very specific use case, starting Azure Automation Runbooks using webhooks, it demonstrates some of the capabilities and ease of development for Azure Functions.

I have hosted this function on a free Azure Web App. You are free to use this for yourself, though I fully understand if you do not trust me to not store your webhook keys ;). The page below helps you to build the url and is itself being served by an Azure Function Proxy as per @lindydonna!

Alexander Jebens

Alexander Jebens is a freelance consultant, software architect and engineer based in Vienna, Austria. He facilitates and drives cloud transition and adoption within organisations while ensuring performance, consistency, governance and cost control. He supports development projects in choosing their stack, securing their solution and adopting DevOps. When not conducting workshops or hacking away at his keyboard, he enjoys running and ski touring while he ponders upon the mysteries of life, the universe and everything.