azureazure-app-service-plansazure-app-service-envrmntapp-service-environment

How to get App service environment ID to use in App service plan in terraform


Can someone help in deploying App service environment using ARM template.

data "azurerm_resource_group" "rg" {
  name = "${var.rg_name}"
}

resource "azurerm_template_deployment" "deploy" {
  name                = "${var.deployment_name}"
  resource_group_name = "${data.azurerm_resource_group.rg.name}"

  template_body = <<DEPLOY
{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "aseName": {
            "type": "string"
        },
        "subscriptionId": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "vnetName": {
            "type": "string"
        },
        "subnetName": {
            "type": "string"
        },
        "vnetId": {
            "type": "string"
        },
        "VNetResourceGroupName": {
            "type": "string"
        },
        "vnetAddress": {
            "type": "string"
        },
        "subnetAddress": {
            "type": "string"
        },
        "subnetRouteTableName": {
            "type": "string"
        },
        "subnetNSGName": {
            "type": "string"
        },
        "ilbMode": {
            "type": "int"
        },
        "subnetId": {
            "type": "string"
        }
    },
    "resources": [
        {
            "apiVersion": "2017-05-10",
            "name": "existingVnetTemplate",
            "type": "Microsoft.Resources/deployments",
            "resourceGroup": "[parameters('VNetResourceGroupName')]",
            "subscriptionId": "[parameters('subscriptionId')]",
            "properties": {
                "mode": "Incremental",
                "template": {
                    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                    "contentVersion": "1.0.0.0",
                    "parameters": {},
                    "variables": {},
                    "resources": [
                        {
                            "apiVersion": "2016-06-01",
                            "type": "Microsoft.Network/virtualNetworks/subnets",
                            "name": "[concat(parameters('vnetName'), '/', parameters('subnetName'))]",
                            "properties": {
                                "addressPrefix": "[parameters('subnetAddress')]",
                                "networkSecurityGroup": {
                                    "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('subnetNSGName'))]"
                                },
                                "routeTable": {
                                    "id": "[resourceId('Microsoft.Network/routeTables', parameters('subnetRouteTableName'))]"
                                }
                            }
                        }
                    ]
                },
                "parameters": {}
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkSecurityGroups/', parameters('subnetNSGName'))]",
                "[resourceId('Microsoft.Network/routeTables/', parameters('subnetRouteTableName'))]"
            ]
        },
        {
            "apiVersion": "2019-02-01",
            "type": "Microsoft.Web/hostingEnvironments",
            "name": "[parameters('aseName')]",
            "kind": "ASEV2",
            "location": "[parameters('location')]",
            "properties": {
                "name": "[parameters('aseName')]",
                "location": "[parameters('location')]",
                "InternalLoadBalancingMode": "[parameters('ilbMode')]",
                "virtualNetwork": {
                    "Id": "[parameters('subnetId')]"
                }
            },
            "tags": {},
            "dependsOn": [
                "['existingVnetTemplate']"
            ]
        },
        {
            "apiVersion": "2015-06-15",
            "type": "Microsoft.Network/routeTables",
            "name": "[parameters('subnetRouteTableName')]",
            "location": "[parameters('location')]",
            "tags": {
                "displayName": "UDR - Subnet"
            },
            "properties": {
                "routes": [
                    {
                        "name": "abdc-route",
                        "properties": {
                            "addressPrefix": "0.0.0.0/0",
                            "nextHopType": "Internet"
                        }
                    }
                ]
            }
        },
        {
            "apiVersion": "2017-06-01",
            "type": "Microsoft.Network/networkSecurityGroups",
            "name": "[parameters('subnetNSGName')]",
            "location": "[parameters('location')]",
            "tags": {
                "displayName": "NSG - Subnet"
            },
            "properties": {
                "securityRules": [
                    {
                        "name": "Inbound-management",
                        "properties": {
                            "description": "Used to manage ASE from public VIP",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "454-455",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 100,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-load-balancer-keep-alive",
                        "properties": {
                            "description": "Allow communication to ASE from Load Balancer",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "16001",
                            "sourceAddressPrefix": "AzureLoadBalancer",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 105,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "ASE-internal-inbound",
                        "properties": {
                            "description": "ASE-internal-inbound",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "[parameters('subnetAddress')]",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 110,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-HTTP",
                        "properties": {
                            "description": "Allow HTTP",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "80",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 120,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-HTTPS",
                        "properties": {
                            "description": "Allow HTTPS",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "443",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 130,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-FTP",
                        "properties": {
                            "description": "Allow FTP over port 21",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "21",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 140,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-FTPS",
                        "properties": {
                            "description": "Allow FTPS",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "990",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 150,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-FTP-Data",
                        "properties": {
                            "description": "RDP",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "10001-10020",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 160,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Inbound-Remote-Debugging",
                        "properties": {
                            "description": "Visual Studio remote debugging",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "4016-4022",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 170,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "Outbound-443",
                        "properties": {
                            "description": "Azure Storage blob",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "443",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 100,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "Outbound-DB",
                        "properties": {
                            "description": "Database",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "1433",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "Sql",
                            "access": "Allow",
                            "priority": 110,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "Outbound-DNS",
                        "properties": {
                            "description": "DNS",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "53",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 120,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "ASE-internal-outbound",
                        "properties": {
                            "description": "Azure Storage queue",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "[parameters('subnetAddress')]",
                            "access": "Allow",
                            "priority": 130,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "Outbound-80",
                        "properties": {
                            "description": "Outbound 80",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "80",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 140,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "ASE-to-VNET",
                        "properties": {
                            "description": "ASE to VNET",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "[parameters('vnetAddress')]",
                            "access": "Allow",
                            "priority": 150,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "Outbound-NTP",
                        "properties": {
                            "description": "Clock",
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "123",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 160,
                            "direction": "Outbound"
                        }
                    }
                ]
            }
        }
    ]
}
DEPLOY
  parameters = {
    "location"      = "${var.location}"
    "aseName" = "${var.aseName}"
    "subscriptionId" = "${var.subscriptionId}"
    "vnetName" = "${var.vnetName}"
    "subnetName" = "${var.subnetName}"
    "vnetId" = "${var.vnetId}"
    "VNetResourceGroupName" = "${var.VNetResourceGroupName}"
    "vnetAddress" = "${var.vnetAddress}"
    "subnetAddress" = "${var.subnetAddress}"
    "subnetRouteTableName" = "${var.subnetRouteTableName}"
    "subnetNSGName" = "${var.subnetNSGName}"
    "ilbMode" = "3"
    "subnetId" = "${var.subnetId}" 
  }

  deployment_mode = "Incremental"
}

"outputs": {
  "app_service_evironment_id": {
    "type": "string",
"value": "[resourceId('Microsoft.Web/hostingEnvironments', parameters('aseName'))]",
}
}

How do i get the ID of App service environment(Hostingenvironment) in this template so that i am able to output it in terraform and use it in App service plan parameter (app_service_environment_id). This is to deploy the app service in a private network.

https://www.terraform.io/docs/providers/azurerm/r/app_service_plan.html#app_service_environment_id

I tried deploying App service environment from azure portal and mentioning its ID in the format "/subscription/xxxx-xxx-xx-xxxx-xxx/Microsoft.web/Hostingenvironment/" which returned a 404.

eg: app_service_environment_id = "/subscription/xxxx-xxx-xx-xxxx-xxx/Microsoft.web/Hostingenvironment/xxxxxxx"

Any help


Solution

  • The mistake you made is that you need to put the output inside the template code, not the Terraform code. So your Terraform code should like this:

    data "azurerm_resource_group" "rg" {
      name = "${var.rg_name}"
    }
    
    resource "azurerm_template_deployment" "deploy" {
      name                = "${var.deployment_name}"
      resource_group_name = "${data.azurerm_resource_group.rg.name}"
    
      template_body = <<DEPLOY
    {
        "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "aseName": {
                "type": "string"
            },
            "subscriptionId": {
                "type": "string"
            },
            "location": {
                "type": "string"
            },
            "vnetName": {
                "type": "string"
            },
            "subnetName": {
                "type": "string"
            },
            "vnetId": {
                "type": "string"
            },
            "VNetResourceGroupName": {
                "type": "string"
            },
            "vnetAddress": {
                "type": "string"
            },
            "subnetAddress": {
                "type": "string"
            },
            "subnetRouteTableName": {
                "type": "string"
            },
            "subnetNSGName": {
                "type": "string"
            },
            "ilbMode": {
                "type": "int"
            },
            "subnetId": {
                "type": "string"
            }
        },
        "resources": [
            {
                "apiVersion": "2017-05-10",
                "name": "existingVnetTemplate",
                "type": "Microsoft.Resources/deployments",
                "resourceGroup": "[parameters('VNetResourceGroupName')]",
                "subscriptionId": "[parameters('subscriptionId')]",
                "properties": {
                    "mode": "Incremental",
                    "template": {
                        "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                        "contentVersion": "1.0.0.0",
                        "parameters": {},
                        "variables": {},
                        "resources": [
                            {
                                "apiVersion": "2016-06-01",
                                "type": "Microsoft.Network/virtualNetworks/subnets",
                                "name": "[concat(parameters('vnetName'), '/', parameters('subnetName'))]",
                                "properties": {
                                    "addressPrefix": "[parameters('subnetAddress')]",
                                    "networkSecurityGroup": {
                                        "id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('subnetNSGName'))]"
                                    },
                                    "routeTable": {
                                        "id": "[resourceId('Microsoft.Network/routeTables', parameters('subnetRouteTableName'))]"
                                    }
                                }
                            }
                        ]
                    },
                    "parameters": {}
                },
                "dependsOn": [
                    "[resourceId('Microsoft.Network/networkSecurityGroups/', parameters('subnetNSGName'))]",
                    "[resourceId('Microsoft.Network/routeTables/', parameters('subnetRouteTableName'))]"
                ]
            },
            {
                "apiVersion": "2019-02-01",
                "type": "Microsoft.Web/hostingEnvironments",
                "name": "[parameters('aseName')]",
                "kind": "ASEV2",
                "location": "[parameters('location')]",
                "properties": {
                    "name": "[parameters('aseName')]",
                    "location": "[parameters('location')]",
                    "InternalLoadBalancingMode": "[parameters('ilbMode')]",
                    "virtualNetwork": {
                        "Id": "[parameters('subnetId')]"
                    }
                },
                "tags": {},
                "dependsOn": [
                    "['existingVnetTemplate']"
                ]
            },
            {
                "apiVersion": "2015-06-15",
                "type": "Microsoft.Network/routeTables",
                "name": "[parameters('subnetRouteTableName')]",
                "location": "[parameters('location')]",
                "tags": {
                    "displayName": "UDR - Subnet"
                },
                "properties": {
                    "routes": [
                        {
                            "name": "abdc-route",
                            "properties": {
                                "addressPrefix": "0.0.0.0/0",
                                "nextHopType": "Internet"
                            }
                        }
                    ]
                }
            },
            {
                "apiVersion": "2017-06-01",
                "type": "Microsoft.Network/networkSecurityGroups",
                "name": "[parameters('subnetNSGName')]",
                "location": "[parameters('location')]",
                "tags": {
                    "displayName": "NSG - Subnet"
                },
                "properties": {
                    "securityRules": [
                        {
                            "name": "Inbound-management",
                            "properties": {
                                "description": "Used to manage ASE from public VIP",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "454-455",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 100,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-load-balancer-keep-alive",
                            "properties": {
                                "description": "Allow communication to ASE from Load Balancer",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "16001",
                                "sourceAddressPrefix": "AzureLoadBalancer",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 105,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "ASE-internal-inbound",
                            "properties": {
                                "description": "ASE-internal-inbound",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "*",
                                "sourceAddressPrefix": "[parameters('subnetAddress')]",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 110,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-HTTP",
                            "properties": {
                                "description": "Allow HTTP",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "80",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 120,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-HTTPS",
                            "properties": {
                                "description": "Allow HTTPS",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "443",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 130,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-FTP",
                            "properties": {
                                "description": "Allow FTP over port 21",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "21",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 140,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-FTPS",
                            "properties": {
                                "description": "Allow FTPS",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "990",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 150,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-FTP-Data",
                            "properties": {
                                "description": "RDP",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "10001-10020",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 160,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Inbound-Remote-Debugging",
                            "properties": {
                                "description": "Visual Studio remote debugging",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "4016-4022",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 170,
                                "direction": "Inbound"
                            }
                        },
                        {
                            "name": "Outbound-443",
                            "properties": {
                                "description": "Azure Storage blob",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "443",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 100,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "Outbound-DB",
                            "properties": {
                                "description": "Database",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "1433",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "Sql",
                                "access": "Allow",
                                "priority": 110,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "Outbound-DNS",
                            "properties": {
                                "description": "DNS",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "53",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 120,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "ASE-internal-outbound",
                            "properties": {
                                "description": "Azure Storage queue",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "*",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "[parameters('subnetAddress')]",
                                "access": "Allow",
                                "priority": 130,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "Outbound-80",
                            "properties": {
                                "description": "Outbound 80",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "80",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 140,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "ASE-to-VNET",
                            "properties": {
                                "description": "ASE to VNET",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "*",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "[parameters('vnetAddress')]",
                                "access": "Allow",
                                "priority": 150,
                                "direction": "Outbound"
                            }
                        },
                        {
                            "name": "Outbound-NTP",
                            "properties": {
                                "description": "Clock",
                                "protocol": "*",
                                "sourcePortRange": "*",
                                "destinationPortRange": "123",
                                "sourceAddressPrefix": "*",
                                "destinationAddressPrefix": "*",
                                "access": "Allow",
                                "priority": 160,
                                "direction": "Outbound"
                            }
                        }
                    ]
                }
            }
        ],
        "outputs": {
          "app_service_evironment_id": {
            "type": "string",
            "value": "[resourceId('Microsoft.Web/hostingEnvironments', parameters('aseName'))]"
        }
      }
    }
    DEPLOY
      parameters = {
        "location"      = "${var.location}"
        "aseName" = "${var.aseName}"
        "subscriptionId" = "${var.subscriptionId}"
        "vnetName" = "${var.vnetName}"
        "subnetName" = "${var.subnetName}"
        "vnetId" = "${var.vnetId}"
        "VNetResourceGroupName" = "${var.VNetResourceGroupName}"
        "vnetAddress" = "${var.vnetAddress}"
        "subnetAddress" = "${var.subnetAddress}"
        "subnetRouteTableName" = "${var.subnetRouteTableName}"
        "subnetNSGName" = "${var.subnetNSGName}"
        "ilbMode" = "3"
        "subnetId" = "${var.subnetId}" 
      }
    
      deployment_mode = "Incremental"
    }
    
    outputs "app_service_evironment_id" {
        value = "${azurerm_template_deployment.outputs["app_service_evironment_id"]}"
    }

    Or the outputs of the Terraform also can be in the format like this:

    outputs "app_service_evironment_id" {
            value = "${lookup(azurerm_template_deployment.app_service_evironment_id.outputs, "app_service_evironment_id")}"
        }
    

    The outputs of the Terraform only to show you how to use the output in template deployment. So you can also quote it in the service plan like this:

    resource "azurerm_app_service_plan" "example" {
      ...
      app_service_environment_id = "${lookup(azurerm_template_deployment.app_service_evironment_id.outputs, "app_service_evironment_id")}"
      ...
    }