Vnet Integration for Your App Service
It’s always a good idea to secure the resources in your Azure subscriptions. One way to do this is by using virtual networks. In a lot of cases, you will put SQL Azure servers, storage accounts and, other services in a virtual network. This will make sure the services can’t be accessed from the public internet unless you explicitly say so.
There are many more advantages to putting services in a virtual network, which I won’t be covering in this post.
This post is on how to integrate an App Service to a virtual network.
The different VNet integration types
At this time, there are 2 types of VNet integration for App Services. They are called ‘Regional VNet Integration’ and ‘Gateway-required VNet Integration’
If you’re running a relatively simple setup, located in a single region, and don’t require a fancy networking setup, it’s probably a good idea to go with the Regional VNet Integration. This one is rather easy to set up and manage.
With this VNet integration, you can still use NSGs (Network Security Groups), route tables, private endpoints, ExpressRoute, and connect to resources in the same region you’re app is located in.
If there’s a need to connect to one or more VNets in another region, the Gateway-required VNet Integration is the way to go. With this integration your service plan can connect to multiple VNets (each app can only connect to a single one), you can manage your DNS and get to create a point-to-site VPN between the different VNets. This is a bit overkill for most scenarios I’m seeing, but if you’re at a large customer or going global, it makes sense to go with this option.
Integrate your App Service with a VNet
From the Portal
It’s not hard to add the VNet integration in the portal. Over here I’m assuming you already have a VNet at your disposal.
From the ‘Networking’-blade you can choose the option ‘VNet Integration’
From there you’re able to add the VNet you want to integrate with.
After clicking it you’ll see the available virtual networks & subnets to connect with.
It only takes a couple of seconds to set up the VNet Integration for the App Service. Afterward, you’ll get to see something similar to the picture below.
Easy, right?
From within an ARM template
Now that you’ve set up the integration, it’s time to store this inside your ARM template. Remember, infrastructure as code is a good idea!
What I did was press the ‘Export Template’ and go on from there. This is the relevant piece of JSON I got.
{
"type": "Microsoft.Web/sites/virtualNetworkConnections",
"apiVersion": "2018-11-01",
"name": "[concat(parameters('mySiteName'), '/c36431b1-fa25-493f-a14f-52adadf77ac0_janv-secureapi-app-subnet')]",
"location": "West Europe",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('mySiteName'))]"
],
"properties": {
"vnetResourceId": "[concat(parameters('virtualNetworks_janv_secureapi_backend_network_externalid'), '/subnets/janv-secureapi-app-subnet')]",
"isSwift": true
}
}
It matches up with my expectations from the ARM template reference site.
However, this is NOT what you need for a Regional VNet integration, like I had set up from within the portal. The above piece of JSON is a small part of the Gateway-required VNet integration!
When trying to deploy this resource you’ll be confronted with a message stating
Swift network cannot be modified with this API call. Please use call /networkConfig/VirtualNetwork
After having tried out a couple of combinations, searched through the documentation, and did some other stuff (proof!), I finally found a Stack Overflow post which helped me out. The post ARM Template for to configure App Services with new VNet Integration feature?, along with a linked GitHub issue is all the information you need.
To create a Regional VNet Integration the ’new’ virtualNetwork
sub-resource has to be used. The necessary JSON looks like this.
{
"name": "[concat(variables('nameOfYourAppServiceInstance'), '/virtualNetwork')]",
"type": "Microsoft.Web/sites/config",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('nameOfYourAppServiceInstance'))]",
"[resourceId('Microsoft.Network/virtualNetworks/', variables('nameOfTheVirtualNetwork'))]"
],
"properties":
{
"subnetResourceId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('nameOfTheVirtualNetwork'), variables('nameOfTheSubnetYouWantToIntegrateWith'))]",
"swiftSupported": true
}
},
It’s too bad this sub-resource isn’t mentioned, yet, in the ARM template reference docs. That would have saved me a lot of time.
If you’re interested, you can find the full ARM template in my GitHub repository (direct link to the correct version of the template) where I’m continuing my work securing my apps using the Azure services provided to me.