Enable IP restriction for a public facing App service
In this blog article, we will cover how to control the app service deployment to support only public facing app service with IP restriction enabled.
Note: The policy should allow the end-user experience to be the same whether they deploy the app service using the Azure portal, ARM template, or terraform.
Policy Definition
Note: The policy below is applicable only for the resource type Microsoft.Web/sites.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "Microsoft.Web/sites/publicNetworkAccess",
"equals": "Enabled"
},
{
"anyOf": [
{
"allOf": [
{
"field": "Microsoft.Web/sites/siteConfig.ipSecurityRestrictionsDefaultAction",
"notEquals": "Deny"
}
]
},
{
"allOf": [
{
"field": "Microsoft.Web/sites/siteConfig.ipSecurityRestrictionsDefaultAction",
"equals": "Deny"
},
{
"not": {
"count": {
"field": "Microsoft.Web/sites/siteConfig.ipSecurityRestrictions[*]",
"where": {
"count": {
"value": "[if(equals(parameters('environment'), 'prod'), parameters('allowedIPAddressesProd'), parameters('allowedIPAddressesDev'))]",
"name": "allowedIpAddress",
"where": {
"allOf": [
{
"value": "[if(equals(current('Microsoft.Web/sites/siteConfig.ipSecurityRestrictions[*].ipAddress'), 'Any'), 'true', ipRangeContains(current('allowedIpAddress'), current('Microsoft.Web/sites/siteConfig.ipSecurityRestrictions[*].ipAddress')))]",
"equals": true
}
]
}
},
"greater": 0
}
},
"equals": "[length(field('Microsoft.Web/sites/siteConfig.ipSecurityRestrictions[*]'))]"
}
}
]
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy."
},
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Audit"
},
"environment": {
"type": "String",
"metadata": {
"displayName": "Environment",
"description": "Select the environment to apply the correct IP restrictions."
},
"allowedValues": [
"dev",
"prod"
],
"defaultValue": "prod"
},
"allowedIPAddressesDev": {
"type": "Array",
"metadata": {
"displayName": "Allowed IP addresses for Dev",
"description": "Array with allowed public IP addresses for the Dev environment."
},
"defaultValue": [
"203.0.113.0/24"
]
},
"allowedIPAddressesProd": {
"type": "Array",
"metadata": {
"displayName": "Allowed IP addresses for Prod",
"description": "Array with allowed public IP addresses for the Prod environment."
},
"defaultValue": [
"198.51.100.0/24",
"203.0.113.5/32"
]
}
}
}
Explanation about policy
The above policy will not allow any public-facing app service to be created unless their public access is "Disabled" or it satisfies the following conditions:
- Enabled from selected network
- Default action should be deny
- Only trusted IP’s are allowed based on the environment i.e above policy is using 198.51.100.0/25 and 203.0.113.5/32 as an example.
Note: You can add more trusted IPs, the above IPs are just examples.
Deployment using Azure portal
If we try to deploy app service using azure portal, in the networking tab we could see only two option i.e enable public access or disable public access.
If we keep enable public access as "ON", we will be blocked from creating the app service with the following error.
Now we know that the portal only supports either enabling or disabling public access for the app service, so we need to create another policy that changes the setting from disable public access to enable public access with IP restrictions in place. Please find the policy below, which will perform the deployment after the app service is deployed through the Azure portal.
Policy definition
The policy below identifies resources like Microsoft.Web/sites and if it finds the app service has public access disabled, it will modify the networking setting of the app service. Via the Azure portal, it is not possible to create an app service with a firewall, and it requires manual changes to be done.
Note: The policy below will automatically enable IP restrictions on newly created app services using the Azure portal with public access disabled for an app service.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Web/sites"
},
{
"anyOf": [
{
"field": "Microsoft.Web/sites/publicNetworkAccess",
"exists": "false"
},
{
"field": "Microsoft.Web/sites/publicNetworkAccess",
"equals": "Disabled"
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"type": "Microsoft.Web/sites/config",
"evaluationDelay": "AfterProvisioningSuccess",
"existenceCondition": {
"field": "Microsoft.Web/sites/config/minTlsVersion",
"equals": "1.1"
},
"name": "web",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/de139f84-1756-47ae-9be6-808fbbe84772",
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"deployment": {
"properties": {
"mode": "incremental",
"parameters": {
"siteName": {
"value": "[field('name')]"
},
"ipAddresses": {
"value": "[parameters('ipAddresses')]"
}
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"siteName": {
"type": "string"
},
"ipAddresses": {
"type": "array"
}
},
"resources": [
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2021-02-01",
"name": "[concat(parameters('siteName'), '/web')]",
"properties": {
"publicNetworkAccess": "Enabled",
"ipSecurityRestrictionsDefaultAction": "Deny",
"copy": [
{
"name": "ipSecurityRestrictions",
"count": "[length(parameters('ipAddresses'))]",
"input": {
"ipAddress": "[parameters('ipAddresses')[copyIndex('ipSecurityRestrictions')]]",
"action": "Allow",
"priority": "[add(100, copyIndex('ipSecurityRestrictions'))]",
"name": "[concat('ipRestriction_', copyIndex('ipSecurityRestrictions'))]"
}
}
]
}
}
],
"outputs": {}
}
}
}
}
}
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"DeployIfNotExists",
"Disabled"
],
"defaultValue": "DeployIfNotExists"
},
"ipAddresses": {
"type": "Array",
"metadata": {
"displayName": "ipAddresses",
"description": "List of IP addresses to allow access to the web app."
},
"defaultValue": [
"198.51.100.0/24"
]
}
}
}
Deployment using ARM template
We export the ARM template of an existing app service and modify the required parameters to deploy another app service with IP restrictions in place. However, the policy doesn’t allow the creation of an app service and is blocked with the same error message.
If we closely look at the policy rule of an IP restriction policy, it is checking the field Microsoft.Web/sites/siteconfig.
But, the exported ARM template is using the field below.
Similar to what Azure policy supports, we tried to define all these siteconfig attributes under Microsoft.Web/sites and tried to deploy the ARM template and removed that resource completely from the ARM template.
Deployment using Terraform
Once the IP restriction policy is in place, try to use the below azurerm providers to deploy the app service with IP restrictions enabled.
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_function_app --- Linux function app
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/windows_function_app ---Windows function app
We need to use the above modules to deploy the app service with the attributes below set for the app service or it must be supported.
Disclaimer
- Please note that products and options presented in this article are subject to change. This article reflects custom policy for enable ip restriction for app service in October 2024.
- If users have the required permissions, they can create exemptions for their resources, which makes this policy ineffective for those resources.
- It is highly recommended to test this policy in a non-production environment before applying it to your production environment to avoid any unintended disruptions and to make sure it meets your requirements.
References
Programmatically create policies - Azure Policy | Microsoft Learn
Troubleshoot common errors - Azure Policy | Microsoft Learn
Overview of Azure Policy - Azure Policy | Microsoft Learn
Published on:
Learn more