Azure Alerts -> Secure Webhook -> Azure Functions with Authentication
Tags: azure, azuread, azurealerts, azuremonitor
Published: 2020-11-14 19:26:21

---
title: Azure Alerts -> Secure Webhook -> Azure Functions with Authentication
published: true
description: 
tags: Azure, AzureAD, AzureAlerts, AzureMonitor
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/eq162f8bi9gdn90p9lem.png
---

# Azure Alerts -> Secure Webhook -> Az Functions with Auth

I have been trying to implement Security in Azure Functions a lot recently and in the past but unfortunately, I can never accomplish it based on Microsoft documentation alone.

So, I am creating this article to help anyone trying to do the same with a nice rundown of how to set up a secure webhook between Azure Monitoring Alerts and an Azure Function HTTP endpoint.

## 1. Create an Azure function in your Subscription. I am calling my functions **Alert-Action-Function**. Any plan should work to accomplish this as we will only be creating 1 HTTP trigger function and enabling Authentication/Authorization

* Run time .NET Core 3.1
* Consumptions plan
* Windows OS

## **2. Enable** function **Authentication/Authorization**

1. Open your function resource and go to the section Settings and open Authentication/Authorization. Than turn **App Service Authentication to On**

    ![Enable function Authentication/Authorization](https://dev-to-uploads.s3.amazonaws.com/i/pcb35nf11rhgsn62mxvz.png "Enable function Authentication/Authorization")

2. Set **Action to take when the request is not authenticated** to **Log in with Azure Active Directory**

    ![App Service Athentication config Part 1](https://dev-to-uploads.s3.amazonaws.com/i/xr7by81ahw1a1kcdb3di.png "App Service Athentication config Part 1")

3. Under  Authentication Providers click the **Azure Active Directory Not Configured**

    ![App Service Athentication config Part 2](https://dev-to-uploads.s3.amazonaws.com/i/23thxzzqbnqup6fkwy1i.png "App Service Athentication config Part 2")

4. Under **Management Mode** select **Express.** Notice the **Create App** field, this will provide you with an auto-generated App Registry name (I will be adding “AD-App” on the end to make it more clear).

    ![Active Directory App Authentication config](https://dev-to-uploads.s3.amazonaws.com/i/tioc1whueqvmw2jwrzmk.png "Active Directory App Authentication config")

5. Now click ok and save. Now we have enabled the Authentication part of our function

## 3. Add a HTTP Trigger function

... to do tests on your setup. I like to write to blob storage so I can view the request body if needed, also b/c you can use this to see if the request is finished in real-time.

**Why I do this:** Azure Monitoring with Application Insights and diagnostic settings setup properly will take around 5 mins to let you see logs and around 2 mins for metrics...  and that is on a good day for Azure.

GitHub repo page for this code [here](https://github.com/Mexicoder/AzureFunctionRequestToBlob)

```
    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Azure.WebJobs.Extensions.Storage;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using Microsoft.Azure.Storage.Blob;
    /*
    ************************************************
    NOTE:
        make sure you have your AzureWebJobsStorage Environmental Variable is set when trying to run
        AND
        make sure you add this package

        dotnet add package Microsoft.Azure.WebJobs.Extensions.Storage

    ************************************************
    */

    namespace Company.Function
    {
        public static class HttpTrigger_test_blob_store
        {
            [FunctionName("HttpTrigger_test_blob_store")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
                [Blob("blobverifycontainer")] CloudBlobContainer outputContainer,
                ILogger log)
            {
                log.LogInformation("C# HTTP trigger function processed a request.");

                string requestBody = await new StreamReader(req.Body).ReadToEndAsync();

                /// write to the blob storage
                await outputContainer.CreateIfNotExistsAsync();
                var blobName = Guid.NewGuid().ToString();
                var cloudBlockBlob = outputContainer.GetBlockBlobReference(blobName);
                await cloudBlockBlob.UploadTextAsync(requestBody);

                // return blob name for easy lookup
                return new OkObjectResult(blobName);
            }
        }
    }
```

## 4. Configure your AD App registration.

1. In **Azure Active Directory -> App registrations** find and open the name from step 2.4 (the express auto-generated name if you didn’t change it) 

    ![Azure AD App Registration](https://dev-to-uploads.s3.amazonaws.com/i/ropykumtprch9208gbkr.png "Azure AD App Registration") 

2. Maker sure to add yourself as the Owner

    ![Ensure Azure AD Service principle Ownership](https://dev-to-uploads.s3.amazonaws.com/i/iuep5mrqhavzlx3iki71.png "Ensure Azure AD Service principle Ownership") 

3. Now go to **Manifest** and you will be adding to the App Roles array in the JSON editor

    ![Azure Sercive Principle Manifest Edit](https://dev-to-uploads.s3.amazonaws.com/i/tzxg6bvasguajqhqst41.png "Azure Sercive Principle Manifest Edit") 

4. Replace with provided JSON.
  
    ```
    "appRoles": [
        {
            "allowedMemberTypes": [
                "Application"
            ],
            "description": "This is a role for Action Groups to join",
            "displayName": "ActionGroupsSecureWebhook",
            "id": "e14442ab-8bd5-47be-90af-695c413d9761 REPLACE WITH NEW GUID",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "ServiceClient"
        }
    ],
    ```

    **BUT make sure to replace the id with a new GUID. If you don’t you will get this error!**

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/ebqgmo23yqj4rb9n65y8.png "image_tooltip")
    
### **Things to Note!!!**

* don’t worry about the tab formatting, after save and you come back it will be done for you. Just make sure your JSON is valid)
*  **IMPORTANT: if you mess up the **appRoles** and try to edit it later you may need to first set IsEnabled to “false”, save and then make your changes. This is something I found out the hard way.**

## 5. ALSO, ensure this (Integrity Check)

Make sure that the **Application ID URL** has been assigned to the base URL of your Azure Function.

**If it has not** this will an error when linking this AD App Registration to the Secure Webhook (you will get an azure notification that doesn’t give you a useful message and just says `“undefined” error`. (I was only able to see the real error was when I when into chrome devtools to investigate the corresponding Network call.)

![Azure App Service Integrity Check](https://dev-to-uploads.s3.amazonaws.com/i/hhznyaliizx8tvdb31u7.png "Azure App Service Integrity Check")

## 6. Create Azure Function to Alert on

* I created a little NoiseMaker project to be an easy way to test Azure Monitor Alerts in general. 
* **Link this to Application Insights**. I named mine NoiseMaker as well.
* If nothing is passed to the query string it will return a 418 (“I’m a teapot”. Look it up, it’s real)
* Github code is [here](https://github.com/Mexicoder/AzureFunctionNoiseMaker)

```
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Company.Function
{
    public static class HTTP_Noise_Maker
    {
        [FunctionName("HTTP_Noise_Maker")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function *NoiseMaker* processed a request.");

            string pass = req.Query["pass"];
            string notfound = req.Query["notfound"];

            if (pass == "true")
            {
                var result = new ObjectResult("I'M OK 😁");
                result.StatusCode = StatusCodes.Status200OK;
                return result;
            }
            else if (notfound == "true")
            {
                var result = new ObjectResult("I'M NOT FOUND 😲");
                result.StatusCode = StatusCodes.Status404NotFound;
                return result;
            }
            else
            {
                var result = new ObjectResult("I'M A TEA POT 🍵");
                result.StatusCode = StatusCodes.Status418ImATeapot;
                return result;
            }
        }
    }
}
```

## 7. Create your alert
Go to Azure Monitor

![Create new Alert Rule](https://dev-to-uploads.s3.amazonaws.com/i/tufp5uuapujtr5k4z4vk.png "Create new Alert Rule")

Select Resource. I am using the NoiseMaker

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/dvt8mfq5tx6g9s235cpl.png "image_tooltip")

Select the Condition. Server Requests are what we want to catch when a 418 happens. (You can do the same for other HTTP response codes as well)

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/dvblf2tp6b08g221o6gf.png "image_tooltip")

Then...

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/uvz5zfwklkhh0wrdefv2.png "image_tooltip")

Now Create the Action Group

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/vr2v7gzs5mzwq5be96kd.png "image_tooltip")

Give it a name and add the Secure Webhook Action and Create

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/mwgsetsq5lw9hkwohkuw.png "image_tooltip")

Now just finish the Alert Creation form with a Name, Description, Severity and make sure Enabled is checked. Should look like this.

![alt_text](https://dev-to-uploads.s3.amazonaws.com/i/v0cqn1s8k20bjt0t6vy4.png "image_tooltip")

## 8. Finally, test it

Trigger the NoiseMaker API endpoint a couple of times (either with a browser or Postman), wait a couple of minutes for the alert to show up on the Monitoring Alert page. Then go to the Storage Account linked to your “Alert-Action-Function” you created before and you should see a new blob in “blobverifycontainer” Container.

Let me know this tutorial worked out for you in the comments below. This is my first Dev.to article and I hope it helps but If improvements need to be made (or I just used too many pictures haha) let me know.

Happy Monitoring