One of the essential aspects of application design is security. Without adequate security at all layers of infrastructure, an application could be exposed, and a breach potential is much higher. But, if we talk about Platform-as-a-Service services in Azure, many people think that their infrastructures are secured by design. Moreover, they are sure that Azure is responsible for handling all security features. Unfortunately, that is not a correct statement, and we have to implement or enable additional security features to improve security at all.
If we have Azure App Service as a frontend layer and Azure SQL as a database layer, one of the implementations should be Private Link. With the Private Link implemented, App Service and Azure SQL will use the virtual network for the communication. Azure App Service, as an additional option, can be integrated with a specific virtual network. On the other hand, a private link endpoint could be implemented on the Azure SQL Server side. So, let’s take a look at how to configure this for the App Service and Azure SQL Server.
Initial App Service/Azure SQL configuration
In our demo environment, App Service hosts a simple .NET Core application and has a connection with Azure SQL Database. At the same time, Azure SQL Server has configured firewall configuration „Allow Azure services and resources to access this server“ on YES, which allows our App Service to communicate with Azure SQL Server. Unfortunately, although that feature enables our Azure SQL Server to communicate with App Service, which is an Azure Service, that firewall configuration poses a significant security risk and leaves the SQL Server vulnerable. That configuration allows any traffic from resources/services hosted in Azure (not just our Azure subscription) to access the database.
One of the possible solutions to minimize risk is implementing the aforementioned Private Link on Azure SQL Server side and the virtual network integration on the App Service side. Before we start with the implementation, we can check how our App Server resolves the FQDN of our Azure SQL Server. To complete this check, we need to open Console access of the App Service and run command nameresolver <azure-sql-server-fqdn>.
Once we confirm that the App Service is resolving the Azure SQL Server FQDN with the public IP, we can start with the implementation of changes.
Deploying Azure SQL Server private link
The first step in that implementation is configuring a private endpoint for Azure SQL. Once we open the desired Azure SQL Server in Azure, we can find that Private endpoint connections under the Security in the left pane.
When we start with creating a private endpoint, we just need to follow the wizard. We have to select a resource group, name, location, what resource is affected by this private link, and what virtual network will be the host of the private endpoint. Enabling a private endpoint gives us the possibility to integrate Private DNS Zones with this feature, which is recommended. Once the deployment is completed, we can see that our Azure SQL Server now has a private IP address.
Enabling App Service vNet integration
The next step is enabling the virtual network integration in our App Service. Once we open the desired App Service, in the left pane under the settings, we can find Networking.
When we open the Networking section, the first option to configure is VNet Integration. The process is straightforward and just need to select an appropriate virtual network and empty subnet. Then, we just need to add two parameters more in the App Service configuration to have a fully functional App Service. By default, App Service routes only RFC1918 traffic into your VNet and cannot work with the Azure DNS Private Zones. If we want to route all of your outbound traffic into your VNet and use the Azure DNS Private Zones, we need to add the following settings in App Service configuration:
- WEBSITE_DNS_SERVER with value 18.104.22.168
- WEBSITE_VNET_ROUTE_ALL with value 1
Once we have implemented those changes, we can disable public access to our Azure SQL Server, by setting Deny public network access on YES and Allow Azure services and resources to access this server to NO. Now, we can run the command nameresolver <azure-sql-server-fqdn> from App Service console again, to see what result will be:
As we can see, our App Service now communicates with the Azure SQL Server using the private IP address, assigned to the Azure SQL Server as a private endpoint. Along with that, public access is disabled, and we can say that communication between these services is secure.