Blog Post

Apps on Azure Blog
6 MIN READ

Tutorials : Integrate Application Gateway with App Service behind Private Endpoint

Calvin_Cai's avatar
Calvin_Cai
Icon for Microsoft rankMicrosoft
Sep 14, 2023

You can securely connect to your App Service from the internet using the Application Gateway when you integrate your Application Gateway with App Service behind Private Endpoint.

 

This article will illustrate and provide detailed steps about how to setup an Application Gateway with an App Service behind a Private Endpoint. We will use a test domain and self-signed certificate for the Application Gateway to simulate a live environment.

 

In the diagram below, your client will connect to the application gateway through the public Ip address. The application gateway will connect privately and securely to your App Service application using a private endpoint which is a network interface that uses a private IP address from your private network.

 

Prerequisite

Create Resource Group and VNET

  1. From Azure portal, click "Resource groups" icon, and then create a resource group.

     

  2. Enter Resource group and create a Virtual network

    Specify the VNET name.

You can keep the default value and confirm the IP addresses space.

 

Select Review + create to create the VNET, the VNET will be used for the Application Gateway and the Private Endpoint used to connect to the Azure App Service.

Create App Service

Navigate to the resource group created in the previous step.

  1. Create resource and select "Web App"

     

  2. Set the app service name and other parameters, select any Runtime stack. You will use the default page for testing purposes. 

     

  3. Keep other settings as default click "Review + create" button to create the App Service

Enable Private Endpoint

  1. View the default page. The default page is publicly accessible when the Azure App Service is created successfully.

     

  2. Navigate to the App Service on Azure portal, visit "Networking" --> "Access restriction"

     

  3. Un-check "Allow public access" and "Save" the changes in App Access to block all incoming traffic except traffic that comes from private endpoints.

     

  4. Click "Networking" -> "Private Endpoints" and click "Add" -> "Express" button.

     

  5. Fill the Private Endpoint name and select the Virtual Network and Subnet previously created. You will need to check "Yes" for Integrated with private DNS zone to resolve your app service FQDN to a private IP address.

     

  6. And now when you visit the web site to test public access to the site, you will receive 403 error.

    *If public network access is restricted through the default (public) endpoint, an Error 403-Forbidden will be shown when you visit the default page. 

     


     

Create Application Gateway

  1. Navigate to the VNet you created in the earlier steps and create a new subnet for Application Gateway

     

  2. Navigate to the resource group and click "New Resource" and select "Application Gateway"

     

  3. On basic page, select the VNET/Subnet you created in the earlier steps.

     

  4. On Frontends page, create a new Public IP for Application Gateway to allow internet resources to communicate inbound to the Application Gateway. 

     

  5. On backends page, create a new backend pool and select the App Service we created before.

     

  6. On Configuration Page, add a "Routing Rule", fill the Listener as below

     


    For backend targets, select the Backend Pool we created before and create new Backend Settings

     


    On backend setting, select HTTPS and override the host name with App Service default FQDN

     

  7. Click "Review + Create" button and create Application Gateway

  8. Once Application Gateway created successfully.
    Check the public IP of Application Gateway and visit the IP address

     

You should see the App Service page displayed successfully

 

Create Self Signed Certificate

Now you will create a self-signed certificate for Application Gateway and use "www.contoso.com " as an example.


You will use OpenSSL to sign certificate. Confirm OpenSSL from https://www.openssl.org/   is installed before running below scripts.

 

  1. Save below config file to "openssl.cnf"

 

 

[ req ]
distinguished_name = req_distinguished_name
policy             = policy_match
x509_extensions     = v3_ca

# For the CA policy
[ policy_match ]
countryName             = optional
stateOrProvinceName     = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = IN
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name) ## Print this message
stateOrProvinceName_default     = KARNATAKA ## This is the default value
localityName                    = Locality Name (eg, city) ## Print this message
localityName_default            = BANGALORE ## This is the default value
0.organizationName              = Organization Name (eg, company) ## Print this message
0.organizationName_default      = GoLinuxCloud ## This is the default value
organizationalUnitName          = Organizational Unit Name (eg, section) ## Print this message
organizationalUnitName_default  = Admin ## This is the default value
commonName                      = Common Name (eg, your name or your server hostname) ## Print this message
commonName_max                  = 64
emailAddress                    = Email Address ## Print this message
emailAddress_max                = 64

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical,CA:true
nsComment = "OpenSSL Generated Certificate"

[ user_crt ]
nsCertType              = client, server, email
nsComment               = "OpenSSL Generated Certificate"
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid,issuer

[ v3_inter_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
extendedKeyUsage = critical,serverAuth,clientAuth,codeSigning,timeStamping,emailProtection,OCSPSigning,ipsecIKE,msCodeInd,msCodeCom,msCTLSign,msEFS


[ v3_client ]
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName      = @alternate_names

[ alternate_names ]
DNS.1 = www.contoso.com

 

 

  1. Save below file to a powershell script, e.g. selfsign.ps1

 

 

Write-Host "SelfSign Test" -ForegroundColor:Green

$domainname = "www.contoso.com"
$password = "Start123"

rm *.csr , *.crt, *.key, *.pfx

# ca.key , ca.csr , ca.crt
# inter.key , inter.csr, inter.crt

Write-Host "Create RootCA"  -ForegroundColor:Green
openssl genrsa -out ca.key 4096
openssl req -new -x509 -days 3650 -subj='/O=MS/OU=CSS/CN=SelfSign Root CA' -config openssl.cnf -key ca.key -out ca.crt
openssl x509 -text -noout -in ca.crt


Write-Host "Create Inter Cert" -ForegroundColor:Green
openssl genrsa -out inter.key 4096
openssl req -new -sha256 -key inter.key -subj='/O=MS/OU=CSS/CN=SelfSign Intermediate CA' -out inter.csr -config openssl.cnf
openssl x509 -req -sha256 -in inter.csr -out inter.crt -CA ca.crt -CAkey ca.key -CAcreateserial -extfile openssl.cnf -extensions v3_inter_ca -days 3650
openssl x509 -text -noout -in inter.crt
openssl verify -CAfile ca.crt inter.crt


Write-Host "Create Client Cert" -ForegroundColor:Green
openssl genrsa -out client.key 4096
openssl req -new -sha256 -key client.key -subj="/O=MS/OU=CSS/CN=$domainname" -out client.csr -config openssl.cnf
openssl x509 -req -sha256 -in client.csr -out client.crt -CA inter.crt -CAkey inter.key -CAcreateserial -extfile openssl.cnf -extensions v3_client -days 3650
openssl x509 -text -noout -in client.crt
openssl verify -CAfile ca.crt -untrusted inter.crt client.crt

Write-Host "Put CA and Inter Cert together"
$caContent = Get-Content ca.crt
$interContent = Get-Content inter.crt
Set-Content ".\cafile.crt" $caContent
Add-Content ".\cafile.crt" $interContent

Write-Host "Package PFX"
openssl pkcs12 -export -passout "pass:$password" -out client.pfx -inkey client.key -in client.crt -CAfile cafile.crt

 

 

 

  1. Run the powershell script, it will generate the CA cert, Intermediate Cert, and the client cert for custom domain

     

  2. Double click ca.crt and click "Install Certificate", click "Current User" and click "Next" button

     

  3. Then Browse and select "Trusted Root Certificate Authorities", click "Next" install the certificate

     

  4. Follow the same steps and install inter.crt to "Intermediate Certification Authorities" store

     

Now you client has trusted the root ca and intermediate ca, and will trust the self-signed certificate as well.

Configure the custom domain for Application Gateway

  1. On your local machine, open an administrative command prompt, and navigate to c:\Windows\System32\drivers\etc.
  2. Open the hosts file, and add the following entries, where x.x.x.x is the application gateway's public IP address:

 

 

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost
x.x.x.x www.contoso.com

 

 

Configure HTTPS listener for Application Gateway

  1. Create a HTTPS Listener for Appliation Gateway

     

  2. Update the Routing Rule and select the httpsListner

     

  3. You should able to visit https://www.consoto.com  successfully, and certificate is also working.

     

References

Updated Sep 12, 2023
Version 1.0
  • Jayendran's avatar
    Jayendran
    Iron Contributor

    Hi Calvin_Cai, thanks for the detailed explanation. How can we restrict direct access to the azure app service after we integrated to app gateway? I would like to control all the traffic to come via appgateway and would like to restrict or deny direct access to .azurewebsites.net 

  • Hi Hareth200 , this document didn't talk about layer 4 firewall. 

    You could setup the layer 4 firewall before or after Application Gateway accoding your requirements, thanks.  

  • dmbuk's avatar
    dmbuk
    Copper Contributor

    good stuff, but with a very little explanation of WHY we do specific steps. Also, Calvin_Cai , you can safely omit steps like "Create a resource group" or virtual network. 🤦‍

    Complex topic with some unnecessary basic and noisy steps. 

  • Hi dmbuk , thanks very much for your suggestion, yes, I think the screenshots for "Create a resource group" or "virtual network" could omit, but the steps should keep as this is a tutorial, we hope user could just follow the steps to setup an environment, thanks. 

  • aditya239's avatar
    aditya239
    Copper Contributor

    I am getting 502 bad gateway when I hit the public IP of application Gateway. I followed the same steps as above. Can you please help me out

  • For 502 bad gateway - Check the status of the Backend Health in the Application Gateway, your server (backend pool) will be in the unhealthy state.

     

    In the App services go to the Web App, Enable the Health check under monitor > Health probe path /index.php > Save. Check the status again on the Application gateway Backend Health, the Server (backend pool) will show healthy. Once the backend health shows healthy you can test the App Gateway and will reach your web app.

  • Gzelger-SWO's avatar
    Gzelger-SWO
    Copper Contributor

    Calvin_Cai 

    Hi,

    in the draft is shown that only one private endpoint is needed but showing 3 Apps in the app service plan.

    Is this a correct draft of what is really working with mor than one web app?

    A private endpoint is more than only a private IP and a network card in a vnet/subnet.

    There is a private link too and more than one DNS entries in the private DNS zone by creating a private endpoint for an azure web app.

    I think that for correct resolution of more than one web app with different custom domain names each web app needs his own private endpoint. -> Am I right or wrong?

     

    For private outbound traffic from the web app going to the vnet or to the internet a vnet integration is also needed.