14

I am working on ARM Templates, I have created the template file with two or more azure app services along with app service plan and then configured with VNET Integration of each app service.

This is sample JSON code:

    {
  "comments": "Web-App-01",
  "name": "[variables('app_name_01')]",
  "type": "Microsoft.Web/sites",
  "location": "[variables('location')]",
  "apiVersion": "2016-08-01",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('asp_name_01'))]"
  ],
  "tags": {
    "displayName": "[variables('app_name_01')]"
  },
  "properties": {
    "name": "[variables('app_name_01')]",
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('asp_name_01'))]",
    "siteConfig": {
      "alwaysOn": true
    }
  },
    "resources": [
      {
        "type": "Microsoft.Web/sites/virtualNetworkConnections",
        "name": "[concat(variables('app_name_01'), '/', variables('vnet_connection_name'),uniqueString('asdsdaxsdsd'))]",
        "apiVersion": "2016-08-01",
        "location": "[variables('location')]",
        "properties": {
          "vnetResourceId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vm_vnet_name'), variables('web_subnet_name'))]"
        },
        "dependsOn": [
          "[resourceId('Microsoft.Web/sites', variables('app_name_01'))]",
          "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vm_vnet_name'), variables('web_subnet_name'))]"
        ]
      }
    ]
},
{
  "comments": "Web-App-02",
  "name": "[variables('app_name_02')]",
  "type": "Microsoft.Web/sites",
  "location": "[variables('location')]",
  "apiVersion": "2016-08-01",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('asp_name_02'))]"
  ],
  "tags": {
    "displayName": "[variables('app_name_02')]"
  },
  "properties": {
    "name": "[variables('app_name_02')]",
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('asp_name_01'))]",
    "siteConfig": {
      "alwaysOn": true
    }
  },
    "resources": [
      {
        "type": "Microsoft.Web/sites/virtualNetworkConnections",
        "name": "[concat(variables('app_name_02'), '/', variables('vnet_connection_name'),uniqueString('asdsdaxsdsd'))]",
        "apiVersion": "2016-08-01",
        "location": "[variables('location')]",
        "properties": {
          "vnetResourceId": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vm_vnet_name'), variables('web_subnet_name'))]"
        },
        "dependsOn": [
          "[resourceId('Microsoft.Web/sites', variables('app_name_02'))]",
          "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vm_vnet_name'), variables('web_subnet_name'))]"
        ]
      }
    ]
}

The above code works fine for few azure app services, but for the rest of the app services I am getting internal server error or Conflict or Bad Request during VNET Integration of Azure App Service.

Note: When I deployed the above the JSON Code, the old VNET integration is configured instead of New VNET (Preview) feature. So, I need to configure New VNET (Preview) feature for each app service.

So, can anyone suggest me how to resolve the above issue.

Pradeep
  • 5,101
  • 14
  • 68
  • 140

4 Answers4

22

I've found a working example for this on an Azure Docs GitHub post:

How do we integrate the new vnet integrartion with ARM templates?

Seems to work a different way with the new VNet integration which uses a Microsoft.Web/sites/config sub-resource named virtualNetwork instead of the Microsoft.Web/sites/virtualNetworkConnections sub-resource

As well as a few requirements that need to be set on the target subnet / vnet (described in the link). The integration piece looks something like this:

   {
      "apiVersion": "2018-02-01",
      "type": "Microsoft.Web/sites",
      "name": "[parameters('appName')]",
      "location": "[resourceGroup().location]",

...

      "resources": [
        {
          "name": "virtualNetwork",
          "type": "config",
          "apiVersion": "2018-02-01",
          "location": "[resourceGroup().location]",
          "properties": {
            "subnetResourceid": "[parameters('subnetResourceId')]",
            "swiftSupported": true
          },
          "dependsOn": [
            "[resourceId('Microsoft.Web/sites', parameters('appName'))]"
          ]
        }
      ]
   },

Apart from this I've not found much else documented, except for a reference to it in the azure-rest-api-specs which has the "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/networkConfig/virtualNetwork" endpoint defined:

azure-rest-api-specs / WebApps.json

It also seems (as the spec suggests) replacing "type": "config" with "type": "networkConfig" also works.

Simon Gregory
  • 566
  • 7
  • 10
  • Thank you for the link! Personally I have encountered quite some inconsistencies around this feature, we might open an issue but for the moment it works only if the virtual network is created in the same template stating the dependency. – reim Jul 10 '19 at 08:00
  • 2
    This really helped us as well, be sure to set delegation on the subnet for this to work. (as the top github link also states) – Jurjen Ladenius Aug 08 '19 at 10:35
  • Indeed, especially because with no delegation one just gets a laconic 500 from the API; the swift setting should also be set to true. – reim Nov 03 '20 at 11:06
10

I've talked to a Prem Engineer of Microsoft.

The Key is to replace the Automation Template

    {
        "type": "Microsoft.Web/sites/virtualNetworkConnections",
        "apiVersion": "2018-11-01",
        "name": "[concat(parameters('sites_FelixOFA_name'), '/xxxxxxx_Functions')]",
        "location": "West Europe",
        "dependsOn": [
            "[resourceId('Microsoft.Web/sites', parameters('sites_FelixOFA_name'))]"
        ],
        "properties": {
            "vnetResourceId": "[concat(parameters('virtualNetworks_FelixODevPremNet_externalid'), '/subnets/Functions')]",
            "isSwift": true
        }
    }

with

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

Where subnetResourceId is the resource id of their subnet – it should look like /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName}

Felixo
  • 101
  • 1
  • 2
2

I tried to reach same functionality by Bicep file, finally using

virtualNetworkSubnetId:

worked for me. For example:

resource webAppName_resource 'Microsoft.Web/sites@2020-12-01' =  {
  name: '${webAppName}'
  location: location
  properties: {
    serverFarmId: appServicePlanPortalName.id
    virtualNetworkSubnetId: '${vnetDeploy_module.outputs.vnetid}/subnets/${vnetDeploy_module.outputs.subnetname}'
    siteConfig: {
      linuxFxVersion: linuxFxVersion
      minTlsVersion: minTlsVersion
      http20Enabled: http20Enabled
    }
    httpsOnly: httpsOnly
  }
}

See templates in https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.web/app-service-regional-vnet-integration.

Result in ARM is:

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-01-01",
  "name": "[parameters('appName')]",
  "location": "[parameters('location')]",
  "kind": "app",
  "properties": {
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
    "virtualNetworkSubnetId": "[reference(resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))).subnets[0].id]",
    "httpsOnly": true,
    "siteConfig": {
      "vnetRouteAllEnabled": true,
      "http20Enabled": true
    }
  },
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
    "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]"
  ]
}
0

To fix this, I simply changed the isSwift or swiftSupported option to false.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77