Virtual Network architecture 5 - App Service Private Endpoint
Published: 2022-08-29 14:39:00

# Summary

This article is Part.5 of virtual network architecture series and includes the details of the private endpoint with Azure App Service and Azure Functions App in [api-management-vnet](https://github.com/koheikawata/api-management-vnet). 

- [Virtual Network architecture 1 - Do I need virtual network?](https://dev.to/koheikawata/virtual-network-architecture-1-do-i-need-virtual-network-1nhk)
- [Virtual Network architecture 2 - Deployment pipelines](https://dev.to/koheikawata/virtual-network-architecture-2-deployment-pipelines-39p5)
- [Virtual Network architecture 3 - Key Vault Private Endpoint](https://dev.to/koheikawata/virtual-network-architecture-3-key-vault-private-endpoint-43nj)
- [Virtual Network architecture 4 - SQL Database Private Endpoit](https://dev.to/koheikawata/virtual-network-architecture-4-sql-database-private-endpoit-49o2)
- [Virtual Network architecture 5 - App Service Private Endpoint](https://dev.to/koheikawata/virtual-network-architecture-5-app-service-private-endpoint-5eao)
- [Virtual Network architecture 6 - Service Bus Private Endpoint](https://dev.to/koheikawata/virtual-network-architecture-6-service-bus-private-endpoint-oa)
- [Virtual Network architecture 7 - Self-hosted agent](https://dev.to/koheikawata/virtual-network-architecture-7-self-hosted-agent-32j4)

# TOC
- [Private Endpoint configuration](#configuration)
- [Inbound and Outbound](#in-and-out)
- [Access restrictions](#restrictions)
- [Support tier](#tier)

# Private Endpoint configuration <a name="configuration"></a>

- **Private Endpoint**: Deploy the private endpoint and connect it to App Service and Functions and their subnets in [PrivateEndpoint.bicep](https://github.com/koheikawata/api-management-vnet/blob/main/src/bicep/vnet/modules/PrivateEndpoint.bicep). Both App Service and Functions need two subnets for each for the purpose of [V-net integration](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration) and Private Endpoint.
  - This sample template takes [Regional V-net integration](https://docs.microsoft.com/en-us/azure/app-service/overview-vnet-integration#regional-virtual-network-integration) and it requires delegated subnet. The integration subnet has to be delegated to `Microsoft.Web/serverFarms`.
  - The Private Endpoint for App Service and Function App has to have one subnet that is not the same subnet as the one for V-net integration, according to the Microsoft documentation [Private Endpoint for App Service](https://docs.microsoft.com/en-us/azure/app-service/networking/private-endpoint#conceptual-overview).

```
AppServiceId:existingAppService.id
FuncId:existingFunc.id
VirtualNetwork2SubnetIdAsePe:existingVnet2.properties.subnets[1].id
VirtualNetwork2SubnetIdFuncPe:existingVnet2.properties.subnets[5].id

resource VirtualNetwork2 'Microsoft.Network/virtualNetworks@2021-03-01' = {
  properties: {
    subnets: [
      {
        name: snet_name_2_ase_vi
        properties: {
          addressPrefix: snet_prefix_2_ase_vi
          networkSecurityGroup: {
            id: Nsg2AseViId
          }
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverfarms'
              }
            }
          ]
          privateEndpointNetworkPolicies: 'Disabled'
        }
      }
      {
        name: snet_name_2_ase_pe
        properties: {
          addressPrefix: snet_prefix_2_ase_pe
          networkSecurityGroup: {
            id: Nsg2AsePeId
          }
          privateEndpointNetworkPolicies: 'Enabled'
        }
      }
      {
        name: snet_name_2_func_vi
        properties: {
          addressPrefix: snet_prefix_2_func_vi
          networkSecurityGroup: {
            id: Nsg2FuncViId
          }
          delegations: [
            {
              name: 'delegation'
              properties: {
                serviceName: 'Microsoft.Web/serverfarms'
              }
            }
          ]
          privateEndpointNetworkPolicies: 'Disabled'
        }
      }
      {
        name: snet_name_2_func_pe
        properties: {
          addressPrefix: snet_prefix_2_func_pe
          networkSecurityGroup: {
            id: Nsg2FuncPeId
          }
          privateEndpointNetworkPolicies: 'Enabled'
        }
      }
    ]
  }
}
```

- **Private DNS**: Deploy Private DNS with the DNS name `privatelink.azurewebsites.net` in [PrivateDns2.bicep](https://github.com/koheikawata/api-management-vnet/blob/main/src/bicep/vnet/modules/PrivateDns2.bicep). App Service and Functions can share one Private DNS Zone.

```
var pdns_name_app = 'privatelink.azurewebsites.net'

resource PrivateDnsApp 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: pdns_name_app
  location: 'global'
}
```

- **Virtual network link**: Link the deployed Private DNS to three of the virtual network  in [PrivateDns2.bicep](https://github.com/koheikawata/api-management-vnet/blob/main/src/bicep/vnet/modules/PrivateDns2.bicep). This is because App Service and Functions reach out to all three virtual networks. Also, the virtual network 1 and 2 are peered, and the virtual network 2 and 3, too.

```
VirtualNetwork1Id:existingVnet1.id
VirtualNetwork2Id:existingVnet2.id
VirtualNetwork3Id:existingVnet3.id

resource VnetLinkApp1 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${PrivateDnsApp.name}-link1'
  location: 'global'
  properties: {
    registrationEnabled: false
    virtualNetwork: {
      id: VirtualNetwork1Id
    }
  }
}

resource VnetLinkApp2 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${PrivateDnsApp.name}-link2'
  location: 'global'
  properties: {
    registrationEnabled: false
    virtualNetwork: {
      id: VirtualNetwork2Id
    }
  }
}

resource VnetLinkApp3 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${PrivateDnsApp.name}-link3'
  location: 'global'
  properties: {
    registrationEnabled: false
    virtualNetwork: {
      id: VirtualNetwork3Id
    }
  }
}
```

- **Private DNS A record**: Create DNS A records and set the IP address from the deployed private endpoints in [PrivateDns2.bicep](https://github.com/koheikawata/api-management-vnet/blob/main/src/bicep/vnet/modules/PrivateDns2.bicep). You have to create two A records each for App Service and Functions because both have another endpoint of SCM(Source Control Manager) site. You can see the documentation of [Kudu service](https://docs.microsoft.com/en-us/azure/app-service/resources-kudu) about it. Both private endpoints need the same private IP address configurations.

```
output PrivateEndpointAseIpAddress string = PrivateEndpointAse.properties.customDnsConfigs[0].ipAddresses[0]
output PrivateEndpointFuncIpAddress string = PrivateEndpointFunc.properties.customDnsConfigs[0].ipAddresses[0]

resource PrivateDnsAAse 'Microsoft.Network/privateDnsZones/A@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${AppServiceName}'
  properties: {
    ttl: 3600
    aRecords: [
      {
        ipv4Address: PrivateEndpointAseIpAddress
      }
    ]
  }
}

resource PrivateDnsAAseScm 'Microsoft.Network/privateDnsZones/A@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${AppServiceName}.scm'
  properties: {
    ttl: 3600
    aRecords: [
      {
        ipv4Address: PrivateEndpointAseIpAddress
      }
    ]
  }
}

resource PrivateDnsAFunc 'Microsoft.Network/privateDnsZones/A@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${FuncName}'
  properties: {
    ttl: 3600
    aRecords: [
      {
        ipv4Address: PrivateEndpointFuncIpAddress
      }
    ]
  }
}

resource PrivateDnsAFuncScm 'Microsoft.Network/privateDnsZones/A@2020-06-01' = {
  name: '${PrivateDnsApp.name}/${FuncName}.scm'
  properties: {
    ttl: 3600
    aRecords: [
      {
        ipv4Address: PrivateEndpointFuncIpAddress
      }
    ]
  }
}
```

# Inbound and Outbound <a name="in-and-out"></a>

App Service and Functions have different network features of inbound and outbound. Inbound works with Private Endpoint and outbound with V-net integration, and both need to have two different subnets for each.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/015q2w48e7zjnavmogq2.png)

# Access restrictions <a name="restrictions"></a>

According to the Microsoft documentation of [Private Endpoints for Azure Web App](https://docs.microsoft.com/en-us/azure/app-service/networking/private-endpoint#conceptual-overview), by default, enabling Private Endpoints to your Web App disables all public access. You do not need to configure [Access restrictions](https://docs.microsoft.com/en-us/azure/app-service/app-service-ip-restrictions).

# Support tier <a name="restrictions"></a>

Microsoft documentation of [Private Endpoints for Azure Web App](https://docs.microsoft.com/en-us/azure/app-service/networking/private-endpoint) describes only Basic, Standard, PremiumV2, PremiumV3, IsolatedV2, Functions Premium support Private Endpoint.