Advanced access restriction scenarios in Azure App Service

15 minute read • By Błażej Miśkiewicz • November 24, 2022

Introduction

Currently, you can use two options when configuring Azure App Service access restrictions. The preview feature provides some new scenarios that you should know.

This article will walk you through building a demo environment where you will test advanced access restriction scenarios in Azure App Service.

Access restriction

Access restriction advanced scenarios:

  1. Filter by http header
  2. Multi-source rules
  3. Block a single IP address
  4. Restrict access to the SCM site

For more information about App Service access restrictions, visit this page

Requirements:

Access to an Azure subscription.

Decide where you will execute commands

The best option to walk through this guide and execute commands would be using Azure Cloud Shell with Bash environment. Azure Cloud Shell is an interactive, authenticated, browser-accessible shell for managing Azure resources. It provides the flexibility of choosing the shell experience that best suits the way you work, either Bash or PowerShell. For information on how to use Azure Cloud Shell, visit Azure Cloud Shell. You can also install Azure CLI on your machine. The Azure CLI is available to install in Windows, macOS and Linux environments. It can also be run in a Docker container and Azure Cloud Shell. For information on how to install the Azure CLI, please visit Azure CLI installation.

If you decide to use Azure Cloud Shell, please use Bash environment.

Getting Started

Create folder for your data

You can use the name below for your folder. You just need to replace ardemo with your environment name.

mkdir ardemo
cd ardemo

Choosing the right subscription

If you have many subscriptions, you must select the subscription to which you want to deploy the resources.

Using this command you can find and copy the SubscriptionId on which you want to create resources for this scenario.

az account list -o table

Using this command you can set a subscription to be the current active subscription.

az account set -s YourSubscriptionID

You can find more information about az account command on this site az account.

Prepare parameters

When you construct your naming convention, identify the key pieces of information that you want to reflect in the resource names. Different information is relevant for different resource types. The following sites are useful when you construct resource names - Define your naming convention and Recommended abbreviations for Azure resource types.

You can use the names below. You just need to replace ardemo with your environment name and change LocationRegion parameter.

Please copy and paste your parameters to your shell.

LocationRegion=westeurope
ResourceGroupName=rg-ardemo
WebAppName=app-ardemo-prod-01
AppServicePlanName=asp-ardemo-linux-prod-01
VirtualNetworkName=vnet-ardemo-prod-westeurope-01
SubnetNameVnet=snet-ardemo-prod-westeurope-01
VnetPrefix=192.168.10.0/24
SubnetVnetPrefix=192.168.10.0/25
PrivateEndpointName=pep-ardemo-prod-01
PrivateEndpointConnectionName=con-pep-ardemo-prod-01
FDName=fd-ardemo-01
OriginGroup=origin-group-ardemo
OriginNamePrimary=primary
LogAnalyticsName=log-ardemo-01
ApplicationInsightsName=appi-ardemo-01
ApplicationInsightsWebTestName=WebsiteTest-$WebAppName

Create basic infrastructure

Create Resource Groups

The demo environment will be organized using one resource group.

az group create -l $LocationRegion -n $ResourceGroupName

Create virtual network with subnet for App Service Private Endpoint

A virtual network will be required for Azure App Service Private Endpoint. This command will create a virtual network with a subnet.

az network vnet create -g $ResourceGroupName -n $VirtualNetworkName --address-prefix $VnetPrefix --subnet-name $SubnetNameVnet --subnet-prefix $SubnetVnetPrefix

Create an App Service Plan

An App Service plan defines a set of compute resources for a web app to run.

For more information about Azure App Service plan, visit this page.

az appservice plan create -n $AppServicePlanName -g $ResourceGroupName --location $LocationRegion --sku P1V2 --is-linux --number-of-workers 1

Create a Web App

To create a PHP app in your App Service plan please use this command.

az webapp create -n $WebAppName -g $ResourceGroupName --plan $AppServicePlanName --runtime "PHP:8.0"

Create a variable with the URL of your website. You will use this variable later with curl command to check if your webapp is working correctly.

URLofYourWebsite=$(az webapp show --name $WebAppName --resource-group $ResourceGroupName --query defaultHostName -o tsv)

Create index.php file for your web app

Sample code for your web app:

echo '<?php
 echo "Azure App Service access restrictions demo";
?>' > index.php

Create zip file for your web app code

In the next step you will use ZIP Deploy to deploy the application. You need a ZIP utility for this. If you’re using Azure Cloud Shell, ZIP utility is pre-installed and already available.

zip YourWebSite.zip index.php

Deploy sample app

To deploy a sample application using ZIP Deploy, use this command:

az webapp deployment source config-zip --resource-group $ResourceGroupName  --name $WebAppName --src ./YourWebSite.zip

Check if your app is running

Use your browser or use curl command to check if your app is working correctly.

curl https://$URLofYourWebsite

Create the Private Endpoint

A private endpoint is a network interface that uses a private IP address from your virtual network. This network interface connects you privately and securely to a service that’s powered by Azure Private Link. By enabling a private endpoint, you’re bringing the service into your virtual network.

For more information about private endpoint, visit this page.

id=$(az webapp show --name $WebAppName --resource-group $ResourceGroupName --query '[id]' --output tsv)
az network private-endpoint create -n $PrivateEndpointName -g $ResourceGroupName --vnet-name $VirtualNetworkName --subnet $SubnetNameVnet --connection-name $PrivateEndpointConnectionName --private-connection-resource-id $id --group-id sites

Configure the private DNS zone

az network private-dns zone create --name privatelink.azurewebsites.net --resource-group $ResourceGroupName
az network private-dns link vnet create --name myDNSLink --resource-group $ResourceGroupName --registration-enabled false --virtual-network $VirtualNetworkName --zone-name privatelink.azurewebsites.net
az network private-endpoint dns-zone-group create --name myZoneGroup --resource-group $ResourceGroupName --endpoint-name $PrivateEndpointName --private-dns-zone privatelink.azurewebsites.net --zone-name privatelink.azurewebsites.net

Check if your website is unavailable

After enabling private endpoint, the web app should not be reachable from the Internet.

Use your browser or use curl command to check if your app is not reachable.

curl https://$URLofYourWebsite

The result should look similar to this.

Forbidden

Optional test

You can create a VM in the same virtual network as the private endpoint for Azure App Service and run a network connection test using private IP address. The name of the Azure App Service should resolve to a private IP address. You can check this using the ping or nslookup command. To check if the website is working properly by using the private IP address, use curl command or a browser on a VM that you will deploy.

Remember to use the standard App Service URL. Thanks to the integration with private DNS zone, the name will be translated into a private IP address. For more information about Azure App Service private endpoint DNS, visit this page.

First advanced scenario - Filter by http header

Currently, you can run Azure App Service with a private endpoint as well as allow traffic from the Internet to Azure App Service. Thanks to this, you can use, for example, Azure Front Door Standard SKU to make Azure App Service available from the Internet. Previously, when using a private endpoint for Azure App Service, it was required to use the Azure Front Door Premium SKU.

For more information about Secure Origin with Private Link in Azure Front Door Premium, visit this page.

In this guide you will add a rule that will allow access from Azure Front Door Standard instance to your Azure App Service using X-Azure-FDID.

Tip Access restrictions can use the following headers:

  1. X-Forwarded-Host - You can specify hostnames of the originating request to limit traffic if a load balancer or HTTP proxy supports hostname forwarding. Enter up to 8 hostnames separated by a comma.
  2. X-Forwarded-For - You can specify IP addresses of the originating client if a load balancer or HTTP proxy supports IP forwarding when the traffic is passing >through. Enter up to 8 CIDR addresses separated by a comma.
  3. X-Azure-FDID - You can specify a unique instance id of Azure Front Door or reverse proxies supporting unique header identification. Enter up to 8 ids >separated by a comma.
  4. X-FD-HealthProbe - You can specify health probe identification to allow probe traffic. Enter up to 8 health probe ids separated by a comma.

Enable public access

To allow traffic from the Internet, use this command.

az resource update --resource-group $ResourceGroupName --name $WebAppName --resource-type "Microsoft.Web/sites" --set properties.publicNetworkAccess=Enabled

You can also enable Allow public access from the GUI.

Allow public access

Check if your website is available

After enabling public access, the webapp should be available from the Internet and from the private endpoint.

Use your browser or curl command to check if your app is working correctly.

curl https://$URLofYourWebsite

Secure Access using Front Door Standard SKU

Azure Front Door is Microsoft’s modern cloud Content Delivery Network (CDN) that provides fast, reliable, and secure access between your users and your applications’ static and dynamic web content across the globe. Azure Front Door delivers your content using the Microsoft’s global edge network with hundreds of global and local POPs distributed around the world close to both your enterprise and consumer end users.

For more information about Azure Front Door, visit this page.

Create Azure Front Door profile

Run az afd profile create to create an Azure Front Door profile.

az afd profile create \
    --profile-name $FDName \
    --resource-group $ResourceGroupName \
    --sku Standard_AzureFrontDoor

Add an endpoint

Run az afd endpoint create to create an endpoint in your profile.

az afd endpoint create \
    --resource-group $ResourceGroupName \
    --endpoint-name endpoint-$FDName \
    --profile-name $FDName \
    --enabled-state Enabled

Create a variable with the URL of your Azure Front Door endpoint. You will use this variable later with the curl command to check if your Azure Front Door endpoint is working correctly.

URLofYourFrontDoorEndpoint=$(az afd endpoint show \
    --resource-group $ResourceGroupName \
    --profile-name $FDName \
    --endpoint-name endpoint-$FDName \
    --query hostName -o tsv)

You can also write down the URL of your Azure Front Door endpoint.

URL of your site

Create an origin group

Run az afd origin-group create to create an origin group that contains your web apps.

az afd origin-group create \
    --resource-group $ResourceGroupName \
    --origin-group-name $OriginGroup \
    --profile-name $FDName \
    --probe-request-type GET \
    --probe-protocol Https \
    --probe-interval-in-seconds 60 \
    --probe-path / \
    --sample-size 4 \
    --successful-samples-required 3 \
    --additional-latency-in-milliseconds 50

Add an origin to the group - primary website

Run az afd origin create to add an origin to your origin group.

az afd origin create \
    --resource-group $ResourceGroupName \
    --host-name $URLofYourWebsite \
    --profile-name $FDName \
    --origin-group-name $OriginGroup \
    --origin-name $OriginNamePrimary \
    --origin-host-header $URLofYourWebsite \
    --priority 1 \
    --weight 1000 \
    --enabled-state Enabled \
    --http-port 80 \
    --https-port 443

Add a route

Run az afd route create to map your endpoint to the origin group. This route forwards requests from the endpoint to your origin group.

az afd route create \
    --resource-group $ResourceGroupName  \
    --profile-name $FDName \
    --endpoint-name endpoint-$FDName \
    --forwarding-protocol MatchRequest \
    --route-name route \
    --https-redirect Enabled \
    --origin-group $OriginGroup \
    --supported-protocols Http Https \
    --link-to-default-domain Enabled

For more information about Azure CLI for Azure Front Door, visit Front Door CLI.

In a production environment you will probably need to implement a WAF policy for you application. For more information about Azure CLI for Azure Front Door WAF Policy, visit Front Door WAF Policy.

Check if your Azure Front Door Endpoint is running - this process may take a while

Use your browser or curl command to check if your app is working correctly. It may take 10-15 minutes for your app to be accessible using Front Door.

curl https://$URLofYourFrontDoorEndpoint

Add X-Azure-FDID rule

Create a variable with the ID of your Azure Front Door profile.

YourFrontDoorID=$(az afd profile show \
    --resource-group $ResourceGroupName \
    --profile-name $FDName \
    --query frontDoorId -o tsv)

Add a rule that only allows communication from the specific Azure Front Door profile.

az webapp config access-restriction add --resource-group $ResourceGroupName --name $WebAppName --rule-name FrontDoor --action Allow --priority 100 --service-tag AzureFrontDoor.Backend --http-header x-azure-fdid=$YourFrontDoorID

Check if your app allow connections using Azure Front Door URL

Use your browser or curl command to check if your app is working correctly using Azure Front Door URL.

curl https://$URLofYourFrontDoorEndpoint

Check if your app is blocked by network restrictions

Use your browser or curl command to check if your app is not available via direct URL access.

curl https://$URLofYourWebsite

Second advanced scenario - Multi-source rules

Multi-source rules allow you to combine up to eight IP ranges or eight Service Tags in a single rule. You might use this if you have more than 512 IP ranges or you want to create logical rules where multiple IP ranges are combined with a single http header filter.

First example - add multiple ip ranges to rule

In example 1, you will add several ip ranges to one rule.

Prepare to run the first scenario

To remove the policy from the previous scenario, please run the command below.

az webapp config access-restriction remove --resource-group $ResourceGroupName --name $WebAppName --rule-name FrontDoor

To change the default behavior Unmatched rule action to Deny, please run the command below.

az resource update --resource-group $ResourceGroupName --name $WebAppName --resource-type "Microsoft.Web/sites" --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Deny

Check if your app is blocked by network restrictions

Use your browser or curl command to check if your app is blocked by network restrictions.

curl https://$URLofYourWebsite

Check your public IP addresses and create variable

Remember If you are using Azure Cloud Shell, remember that you will have a different public IP address every time you restart your console.

YourPublicIPaddress=$(curl icanhazip.com)

TIP You can also use a Powershell command to check your public IP address.

(Invoke-WebRequest -uri "http://ifconfig.me/ip").Content

or you can use curl command

(curl icanhazip.com).Content

Add IP addresses to multi-source rule

To add a rule that will block traffic from several IP ranges, run the below command.

az webapp config access-restriction add --resource-group $ResourceGroupName --name $WebAppName --rule-name AllowBranchWarsawIPaddresses --action Allow --priority 200 --ip-address 192.168.1.0/24,192.168.10.0/24,192.168.100.0/24,$YourPublicIPaddress

Check if your app allows connections

Use your browser or curl command to check if your app is working correctly.

curl https://$URLofYourWebsite

Second example - add multiple service tags to a network restriction rule

This example show you how you can add multiple service tags to a network restriction rule. In this example we will allow connections from Logic Apps, Application Insights and API Management from West Europe. In this example you will test this rule using Application Insights availability test.

Prepare to run the second example

The following command will create Application Insights and Log Analytics Workspace for you.

az monitor log-analytics workspace create --resource-group $ResourceGroupName --workspace-name $LogAnalyticsName
LogAnalyticsId=$(az monitor log-analytics workspace show --resource-group $ResourceGroupName --workspace-name $LogAnalyticsName --query id -o tsv)
LogAnalyticsWorkspaceId=$(az monitor log-analytics workspace show --resource-group $ResourceGroupName --workspace-name $LogAnalyticsName --query customerId -o tsv)
az monitor app-insights component create --app $ApplicationInsightsName --location $LocationRegion --kind web -g $ResourceGroupName --application-type web --workspace $LogAnalyticsId
ApplicationInsightId=$(az monitor app-insights component show --app $ApplicationInsightsName -g $ResourceGroupName --query id -o tsv)
az monitor app-insights web-test create --web-test-kind "standard" --enabled true --location $LocationRegion --resource-group $ResourceGroupName --name $ApplicationInsightsWebTestName --defined-web-test-name $ApplicationInsightsWebTestName --tags "hidden-link:$ApplicationInsightId=Resource" --http-verb "GET" --request-url "https://$URLofYourWebsite" --timeout 30 --frequency 300 --retry-enabled true --locations Id="emea-nl-ams-azr" --locations Id="us-fl-mia-edge"

Show Application Insights availability test result

After running the command below, you should get a result from Application Insights that the tests failed.

Tip Please wait 5-10 minutes before you run this command. Availability tests are run every 5 minutes.

az monitor log-analytics query -w $LogAnalyticsWorkspaceId --analytics-query "AppAvailabilityResults | project TimeGenerated, Message, Location | order by TimeGenerated desc" -t P0DT1H -o table

Tip If you have multiple availability tests in one Application Insight, you can use the Name field for filtering.

The result should look similar to this.

403-ip-forbidden

Add service tags to multi-source rule

To add a rule that will allow traffic from several service tags, run the following command.

az webapp config access-restriction add --resource-group $ResourceGroupName --name $WebAppName --rule-name AllowMultipleServiceTags --action Allow --priority 300 --service-tag LogicApps,ApiManagement.WestEurope,ApplicationInsightsAvailability

Show Application Insight availability test result

After running the command below, you should get a result from Application Insight that the tests passed.

Tip Please wait 5-10 minutes before you run this command. Availability tests are run every 5 minutes.

az monitor log-analytics query -w $LogAnalyticsWorkspaceId --analytics-query "AppAvailabilityResults | project TimeGenerated, Message, Location | order by TimeGenerated desc" -t P0DT1H -o table

The result should look similar to this.

Passed

Third advanced scenario - Block a single IP address

Remove previous rules

To remove the rules from the previous scenario, run the command below.

az webapp config access-restriction remove --resource-group $ResourceGroupName --name $WebAppName --rule-name AllowBranchWarsawIPaddresses
az webapp config access-restriction remove --resource-group $ResourceGroupName --name $WebAppName --rule-name AllowMultipleServiceTags

Change default behavior for Unmatched rule action to Allow

To change the default behavior to Allow, run the command below.

az resource update --resource-group $ResourceGroupName --name $WebAppName --resource-type "Microsoft.Web/sites" --set properties.siteConfig.ipSecurityRestrictionsDefaultAction=Allow

Check if your app allow connections

Use your browser or curl command to check if your app allows connections.

curl https://$URLofYourWebsite

Block your public IP address

To add a rule that will block traffic from your IP address, run the command below.

az webapp config access-restriction add --resource-group $ResourceGroupName --name $WebAppName --rule-name BlockSingleIpAddress --action Deny --priority 200 --ip-address $YourPublicIPaddress

Check if your app is blocked by network restrictions

Use your browser or curl command to check if your app is blocked by network restriction.

curl https://$URLofYourWebsite

Fourth advanced scenario - Restrict access to the SCM site

You can use the same access restriction rules from the Main site or create your own rule for the SCM (Advanced tool) site. The SCM site is responsible for Web Deploy and Kudu console.

For more information about Kudu, visit Kudu service overview.

Verify that you can deploy your sample app

To verify that you can deploy your sample app via Web Deploy, run the command below.

az webapp deployment source config-zip --resource-group $ResourceGroupName  --name $WebAppName --src ./YourWebSite.zip

Use the same access restrictions rules from Main site in Advanced tool site

To use the same rules from the Main site in the Advanced tool site, run this command.

az webapp config access-restriction set --resource-group $ResourceGroupName  --name $WebAppName --use-same-restrictions-for-scm-site true

Verify that you can’t deploy your sample app

To verify that you can’t deploy your sample app via Web Deploy, please run the command below.

az webapp deployment source config-zip --resource-group $ResourceGroupName  --name $WebAppName --src ./YourWebSite.zip

Configure different rules for Advanced tool site

To configure other rules for Advanced tool site, run below command.

az webapp config access-restriction set --resource-group $ResourceGroupName  --name $WebAppName --use-same-restrictions-for-scm-site false

To add a rule that will allow traffic from your IP address to the SCM site, run the bellow command.

az webapp config access-restriction add --resource-group $ResourceGroupName --name $WebAppName --rule-name BlockSingleIpAddress --action Allow --scm-site true --priority 200 --ip-address $YourPublicIPaddress

Verify that you can deploy your sample app

To verify that you can deploy your sample app via Web Deploy, please run the command below.

az webapp deployment source config-zip --resource-group $ResourceGroupName  --name $WebAppName --src ./YourWebSite.zip

You successfully completed the article.