Skip to content

Access restriction HttpHeaders

Mads Damgård edited this page Oct 13, 2020 · 6 revisions

Overview

Access restrictions for App Service have existed for a while and supports scenarios where you want to limit traffic to a web app or scm instance to a specific IP range or subnet using service endpoints. An upcoming changes, currently in preview, is the ability to specify Http Headers in addition to IP filters and Service Tags. A scenario could be a cloud based reverse proxy, that originates from a specific IP range, but in addition needs an http header to identify, that the request if from a requested host address or customer account.

This feature is currently in preview. You are welcome to use the feature and provide feedback to madsd<at>microsoft<dot>com.

Behavior

There is currently support for four headers. All headers are arrays of string. If more than one value is specified per header, only one needs to match. But if multiple headers are specified, all headers would need to have at least one match. Header keys and values are case insensitive. The four headers are:

  • X-Forwarded-Host: identifying the hostname of the originating request
  • X-Forwarded-For: Identifying the (chain of) IPs that was visited prior to reaching the backend.
  • X-Azure-FDID: An unique ID identifying the customer instance or account. In Azure Front Door this is a Guid, but front doors/reverse proxies from other vendors could choose another scheme for the ID.
  • X-FD-HealthProbe: A 0/1 boolean identifying if the request was a backend probe request, in which case XFF and XFD is not included.

Use cases

A valid use case for this would be isolation of traffic between Azure Front Door and an App Service instance. In that case, you would use the "AzureFrontDoor.backend" Service Tag. To isolate it to your specific instance, you would need to add an additional header check. Front Door will send a header called X-Azure-FDID with the unique ID of the Front Door instance. With this header set in addition to the Front Door Service Tag, only traffic from that particular instance will be allowed.

Another use case could be to lock down access from a specific host name coming from Front Door - e.g. app.contoso.com. Front Door will forward with header in the X-Forwarded-Host header. If you use this header, you will need to have an additional rule to allow probe traffic from Front Door, as these requests do not have an originating host. You can combine the X-Azure-FDID with X-FD-HealthProbe=1 to ensure probe traffic will be allowed as well.

Usage

Test setup

Setup an Azure App Service web app [webapp-name]. Verify you can access the site using either a browser or curl

curl https://[webapp-name].azurewebsites.net

Adding access restrictions, as they are today, can be done using REST, ARM, portal, CLI and PowerShell. In the portal, you can find the access restriction settings under Networking:

Access restriction UX

In access restrictions you can add and remove individual restrictions as well as manage scm site restrictions and inheritance to scm site.

Add restriction UX

Debugging

It can be useful to see what values are actually sent to the web app. Using Kudo, you can add a .cshtml files, that can output relevant info. Create a file called default.cshtml and add the following content:

@using System.Web.Configuration

<h3>Debug information</h3>
<ul>
    <li><strong>Request Url</strong><span>: @Request.Url</span></li>
    <li><strong>Remote IP</strong><span>: @Request.ServerVariables["REMOTE_ADDR"]</span></li>
</ul>
<strong>Headers</strong>
<ul>
    @foreach (var h in Request.Headers)
        {<li><strong>@h</strong><span>: @Request.Headers[h.ToString()]</span></li>}
</ul>
  • Open the Kudu console at https://[webapp-name].scm.azurewebsites.net and go to Debug console > CMD
  • Browse to site > wwwroot and drag the default.cshtml to the folder.

You should now see an output like this:

Debug output

Simple test with REST

Portal support for the new functionality is still pending, so you will need to use the REST apis to continue. To call REST you need to have ARMClient.exe installed. Follow this guide, if you do not have it installed already.

Test ARMClient.exe by getting the config section of the web site. If you are calling ARMClient.exe for the first time, you need to authenticate using ARMClient.exe login or ARMClient.exe azlogin. You can find Subscription ID and Resource group name in Azure portal in the Overview section of the web app. Site is your webapp-name (without .azurewebsites.net).

ARMClient.exe GET "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{site}/config/web?api-version=2020-06-01

Adding access restrictions uses the PATCH verb and need a payload in the form of a .json file. Create an clear.json file with an empty ipSecurityRestriction property:

{
  "properties": {
    "ipSecurityRestrictions": [
    ]
  }
}

Call ARMClient.exe with the payload (if you are calling from PowerShell, remember to back tick the @ sign).

ARMClient.exe PATCH "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{site}/config/web?api-version=2020-06-01 @empty.json

You should still be able to access the site.

Random Service Tag test

Add a random Service Tag restriction to verify you can block traffic - e.g. EventGrid in a file called random-tag.json and apply it using another call with ARMClient.exe

{
  "properties": {
    "ipSecurityRestrictions": [
      {
        "action": "Allow",
        "ipAddress": "EventGrid",
        "priority": 200,
        "tag": "ServiceTag"
      }
    ]
  }
}
ARMClient.exe PATCH "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{site}/config/web?api-version=2020-06-01 @random-tag.json

You should now receive a 403 error.

Azure Front Door test

Now lets setup the access restriction for traffic coming from AFD. First setup an AFD instance called [afd-name] and configure the traffic to point to your web app. Here is a guide to setup Azure Front Door with App Service. Clear the previous access restrictions by applying the empty json payload. Test that you can access the site from the Front Door address.

Create a payload file named afd.json with this content, and apply it using ARMClient.exe

{
  "properties": {
    "ipSecurityRestrictions": [
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag"
      }
    ]
  }
}

You should now still be able to access the site through Azure Front Door, but you cannot access the site directly on the [webapp-name].azurewebsites.net address.

Azure Front Door extended tests 1

Currently it only locks down the site to the Front Door service and not your particular instance. To lock down the site to the particular AFD instance, you can apply the template below. You need to go to your Front Door instance to get the id. You can use the ARMClient for that:

ARMClient.exe GET "/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/frontdoors/{front-door-name}?api-version=2020-01-01"

You will see something like this, where the frontdoorId is at the end. Front Door ID

{
  "properties": {
    "ipSecurityRestrictions": [
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag",
        "headers": {
          "x-azure-fdid": [
            "220370e9-1d6d-4781-82cc-36b1d82c64ca"
          ]
        }
      }
    ]
  }
}

Azure Front Door extended tests 2

Extending the existing example to lock it down to only accepting traffic from a specific host name - e.g. app.contoso.com - would look like this.

{
  "properties": {
    "ipSecurityRestrictions": [
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag",
        "headers": {
          "x-azure-fdid": [
            "220370e9-1d6d-4781-82cc-36b1d82c64ca"
          ],
          "x-forwarded-host": [
            "app.contoso.com"
          ]
        }
      }
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag",
        "headers": {
          "x-azure-fdid": [
            "220370e9-1d6d-4781-82cc-36b1d82c64ca"
          ],
          "x-fd-healthprobe": [
            "1"
          ]
        }
      }
    ]
  }
}

Azure Front Door extended tests 3

Extending even further to allow 2 out of xx hosts (app.contoso.com and www.contoso.com); and only requests coming from 10.10.10.10.

{
  "properties": {
    "ipSecurityRestrictions": [
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag",
        "headers": {
          "x-azure-fdid": [
            "220370e9-1d6d-4781-82cc-36b1d82c64ca"
          ],
          "x-forwarded-host": [
            "app.contoso.com",
            "www.contoso.com"
          ],
          "x-forwarded-for": [
            "10.10.10.10"
          ],
          "x-fd-healthprobe": [
            "0"
          ]
        }
      },
      {
        "action": "Allow",
        "ipAddress": "AzureFrontDoor.backend",
        "priority": 200,
        "tag": "ServiceTag",
        "headers": {
          "x-azure-fdid": [
            "220370e9-1d6d-4781-82cc-36b1d82c64ca"
          ],
          "x-fd-healthprobe": [
            "1"
          ]
        }
      }
    ]
  }
}

That's it. Happy acl'ing.