Anthony Attwood

Punny Stuff

Deploying Azure App Service Regional VNet Integration with ARM

2020-06-29 Anthony Attwoodazure

Azure App Service has a networking feature called VNet Integration, which allows outbound traffic from your App Service app to be pushed into a private VNet rather than go directly to the public internet. This can be really useful if you need to reach resources or servers inside a VNet, or over an ExpressRoute connection to on-premises, or send all outbound traffic via an egress controller on your security perimeter, or … etc etc.

The docs are really quite good at explaining the feature and when/where/why/how you use it. https://docs.microsoft.com/en-us/azure/app-service/web-sites-integrate-with-vnet

There are two distinct flavours of VNet Integration, Regional and Gateway-Required. Gateway-Required has been around for a while and uses a point-to-site VPN to get traffic into your VNet. Regional is much newer and simpler to use, and is what this post is about.

Also Known As - AKA:

There have been a variety of terms attached to the Regional VNet Integration feature throughout its development and release, and you sometimes see them in documentation and APIs, you might see some of them in your travels. They all refer in some way to Regional VNet Integration as opposed to Gateway-Required:

  • Swift - this one comes up in the REST API methods and payloads, and in ARM templates.
  • New VNet - common in blog posts and articles from 2018 to late 2019, when Regional was still in preview or only just GA.
  • VNet Injection - the docs sometimes refer to vnet injection without defining the term.

How NOT to deploy Regional VNet Integration

If, like me, you go to the ARM reference documentation and look under Microsoft.Web, you’ll see sites/virtualNetworkConnections and sites/slots/virtualNetworkConnections.

ARM reference docs - Microsoft.Web/sites/virtualNetworkConnections

This is not the ARM resource type you want! This is for Gateway-Required VNet Integration.

It's a trap!

If you use a Microsoft.Web/sites/virtualNetworkConnections resource type, you’ll configure a Gateway-Required integration. Even if you don’t do it correctly, which I didn’t, ARM won’t report any issues, and the integration will not work.

A helpful Microsoft support engineer was able to diagnose my problem - that I had (mis)configured a Gateway-Required VNet Integration - and pointed me to the correct way to set it up with ARM.

The solution

Stackoverflow to the rescue!

https://stackoverflow.com/questions/54534924/arm-template-for-to-configure-app-services-with-new-vnet-integration-feature/59857601#59857601

The resource type you want is Microsoft.Web/sites/networkConfig (and .../sites/slots/... if you’re using them), not Microsoft.Web/sites/virtualNetworkConnections.

{
  "type": "Microsoft.Web/sites/networkConfig",
  "name": "[concat(parameters('webAppName'),'/VirtualNetwork')]",
  "apiVersion": "2016-08-01",
  "properties":
  {
    "subnetResourceId": "[parameters('subnetResourceId')]",
    "swiftSupported": true
  }
}

Microsoft.Web/sites/networkConfig appears to be entirely undocumented in the official ARM docs, but it does appear in the ARM schema, which you can find on GitHub. Note the end of the name must be /virtualNetwork, you can’t change it.

That’s it for the solution. If you’re interested in knowing how to tell whether the thing you’ve configured is a Gateway-Required or Regional VNet Integration, read on!

The diagnosis

Our friend here is the Azure Resource Explorer, https://resources.azure.com. If you’ve never seen it, take a moment to explore, it’s a really useful way to see details that are not surfaced in the Azure portal.

Here’s what to look for to check you’ve set up your Regional VNet Integration correctly.

Navigate to the web app’s config/virtualNetwork node

Subscriptions --> {subscription} --> resourceGroups --> {resource group} --> providers --> Microsoft.Web --> {web app} --> config --> virtualNetwork

resources.azure.com web app virtualNetwork node

Note the properties you set in the ARM template. They’re not exactly the same as in the ARM template, but pretty close:

  • "name": "virtualNetwork"
  • "type": "Microsoft.Web/sites/config"
  • "swiftEnabled": true

Navigate to the web app’s site/virtualNetworkConnections node

Subscriptions --> {subscription} --> resourceGroups --> {resource group} --> providers --> Microsoft.Web --> {web app} --> virtualNetworkConnections

resources.azure.com web app virtualNetworkConnections node

Note the value of the name property, this is the important bit;

"name": "{guid}_{app-service-plan-name}"

Regional VNet Integration will result in the name field derived from the resourceGuid of the vnet and the name of the app service plan, {guid}_{app-service-plan-name}. If, like me, you used ARM to create a virtualNetworkConnections sub-resource (and hence created a Gateway-Required integration by mistake), then the name will not have the {guid}_{app-service-plan-name} format but will be whatever you set as the resource name in your ARM template.

There’s also the isSwift property. If it’s set to true, then it means you’ve set up a Regional VNet Integration like you wanted.

Summary

This a bit of a long post, so here’s a tl-dr;

  • Gateway-Required VNet Integration is configured with the ARM resource Microsoft.Web/sites/virtualNetworkConnections. You can’t use this for Regional.
  • Regional VNet Integration is configured with Microsoft.Web/sites/networkConfig (or Microsoft.Web/sites/slots/networkConfig)
  • No it’s not documented in the ARM reference docs 😑
  • StackOverflow has the answer: https://stackoverflow.com/a/59857601
  • There are clues in the Azure Resource Explorer (https://resources.azure.com) if you look carefully