Ken MuseALM | DevOps Ranger & Azure MVP

Restricting Azure App Services to Azure Front Door


Securing an Azure App Service is a common requirement. If you're not familiar with Front Door, it combines a web application firewall (WAF), content distribution network (CDN), traffic manager, and routing rules into a single service. This makes it a perfect choice for protecting a web site. In using this, we want to ensure that traffic only arrives from Front Door rather than directly accessing the App Service. While most parts of setting up Front Door are deliberately easy, limiting the network traffic currently requires manual effort.

Microsoft outlines the detailed process for restricting traffic in the Front Door FAQ. Originally, this simply required allowing a handful of specific IPs and restricting all others. However, as the service has evolved, the requirements have grown. Today there are two options: either filter on the request header X-Azure-FDID or allow all of the Azure IP address ranges that support the Front Door service. For this post, we'll focus on how to limit the service to specific IP addresses.

The IP addresses in our allow list are in three broad groups:

  • The AzureFrontDoor.Backend IPv4 address range
  • The AzureFrontDoor.Backend IPv6 address range
  • The Azure infrastructure service IPs: 168.63.129.16 and 169.254.169.254

While the infrastructure addresses are static, the backend IP space is not. Microsoft publishes an updated list of the current IP Ranges and Service tags every Monday in JSON format. Because of the frequent updates, our best course of action is to automate using these published IP addresses. To simplify this process, we can use Az PowerShell module cmdlet for retrieving the current list of addresses, Get-AzNetworkServiceTag. We can use this cmdlet to automate the process of updating our App Service's network access restriction list.

First, we retrieve a filtered list of the IPv4 and IPv6 IP addresses used by Front Door:

$addresses = (Get-AzNetworkServiceTag 
                -Location eastus2).
              Values.
              Where({$_.Name -eq 'AzureFrontDoor.Backend'}).
              Properties.
              AddressPrefixes

Next, request the current site's configuration settings, which includes the IP Security Restrictions using Get-AzResource:

$config = Get-AzResource
    -ResourceName $appServiceName 
    -ResourceType Microsoft.Web/sites/config
    -ResourceGroupName $resourceGroupName
    -ApiVersion '2019-08-01'

Since these priorities will be created and updated automatically, we need to remove any existing entries in this range. To support that, we create the priorities in a specific range. This makes it easier to update the addresses. The code just needs to filter out that range to preserve any user-defined rules. For this example, I'm using the range 1000 to 1999. 

$rules = $config.
    Properties.
    ipSecurityRestrictions.
    Where({ -not ($_.priority -ge 1000 -and $_.priority -le 1999)})

After that, we can create custom rules for all of the IP addresses, beginning with the two infrastructure IPs and then appending the Front Door IP addresses.

$priority = 1000;

$rules += New-Object PSObject -Property @{
    ipAddress = '168.63.129.16/32'
    action = "Allow"
    priority = $priority
    name = "Azure Infrastructure $priority"
    description = "Automatically added address"
  }
  
$priority++;

$rules += New-Object PSObject -Property @{
    ipAddress = '169.254.169.254/32'
    action = "Allow"
    priority = $priority
    name = "Azure Infrastructure $priority"
    description = "Automatically added address"
  }
  
$priority++;

foreach ($address in $addresses){
  $rules += New-Object PSObject -Property @{
    ipAddress = $address
    action = "Allow"
    priority = $priority
    name = "FrontDoor.Backend $priority"
    description = "Automatically added address"
  }
  
  $priority++;
}

Finally, the updated App Service configuration must be published to Azure. The Force switch prevents PowerShell from prompting for approval.

$config.Properties.ipSecurityRestrictions= $rules

Set-AzResource 
    -ResourceId $config.ResourceId
    -Properties $config.Properties
    -ApiVersion '2019-08-01'
    -Force

And that's all there is to the process. The completed script can be run each week as part of a scheduled process. This ensures that the App Service is always limited to requests originating from Azure infrastructure services or Azure Front Door.

The complete script is available on GitHub.

Happy DevOp'ing!