How to Securely Connect a .NET App to Azure SQL Database Using Private Endpoints with Azure CLI
Table of contents
When deploying applications to the cloud, one of the most critical aspects is keeping connections secure. Today, I’ll walk you through how I set up a secure connection between an Azure SQL Database and an Azure App Service using Private Endpoints and Private DNS Zones.
This is a purely CLI-based approach, and we’ll cover each step while keeping it straightforward and focused. If you're following along for learning purposes, remember to delete all resources after testing to avoid unnecessary charges. Alternatively, you can enable public access and scale down to the free tier for the App Service if you’d like to keep resources up for future testing.
Prerequisites
To follow along, it’s helpful to be familiar with the Azure CLI and have Azure CLI installed, or you can use Azure Cloud Shell directly in the Azure Portal for a browser-based CLI experience. Also, you’ll need a Standard or Premium App Service Plan for VNet integration. If you’re new to deploying .NET apps with Azure App Service, I have an end-to-end guide here.
1. Set Up Variables
To make things easier, start by defining variables to use throughout the setup process.
RESOURCE_GROUP="<your_resource_group>"
LOCATION="<location>"
SQL_SERVER_NAME="<your_sql_server_name>"
DATABASE_NAME="<your_database_name>"
ADMIN_USERNAME="<your_admin_username>"
ADMIN_PASSWORD="<your_admin_password>"
APP_SERVICE_NAME=""
VNET_NAME="<your_vnet_name>"
DB_SUBNET_NAME="dbSubnet"
APP_SUBNET_NAME="appSubnet"
PRIVATE_ENDPOINT_NAME="sqlPrivateEndpoint"
PRIVATE_DNS_ZONE_NAME="privatelink.database.windows.net"
2. Create the SQL Server and SQL Database
Our app needs a database, so let’s set up an Azure SQL Database and SQL Server for it. We’ll also use the S0 service objective here, which is a good starting point for development and testing.
# Create Resource Group
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create SQL Server
az sql server create \
--name $SQL_SERVER_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--admin-user $ADMIN_USERNAME \
--admin-password $ADMIN_PASSWORD
# Create SQL Database
az sql db create \
--resource-group $RESOURCE_GROUP \
--server $SQL_SERVER_NAME \
--name $DATABASE_NAME \
--service-objective S0
3. Create a Virtual Network and Subnets
Next, we’ll set up a Virtual Network (VNet) with two subnets: one for the SQL Database Private Endpoint and another for the App Service.
# Create VNet
az network vnet create \
--name $VNET_NAME \
--resource-group $RESOURCE_GROUP \
--address-prefix 10.0.0.0/16 \
--location $LOCATION
# Create Subnet for SQL Database Private Endpoint
az network vnet subnet create \
--name $DB_SUBNET_NAME \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--address-prefix 10.0.1.0/24
# Create Subnet for App Service VNet Integration
az network vnet subnet create \
--name $APP_SUBNET_NAME \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--address-prefix 10.0.2.0/24
4. Create the Private Endpoint for SQL Database
A Private Endpoint restricts SQL Database access to within the VNet, enhancing security. This means only resources in the VNet can connect to the database.
az network private-endpoint create \
--name $PRIVATE_ENDPOINT_NAME \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--subnet $DB_SUBNET_NAME \
--location $LOCATION \
--private-connection-resource-id $(az sql server show --name $SQL_SERVER_NAME --resource-group $RESOURCE_GROUP --query "id" -o tsv) \
--group-id sqlServer \
--connection-name "${PRIVATE_ENDPOINT_NAME}_connection"
5. Link a Private DNS Zone
For the App Service to resolve the private IP of our SQL Database using the default database.windows.net
domain, we’ll create and link a Private DNS Zone.
# Create Private DNS Zone
az network private-dns zone create \
--resource-group $RESOURCE_GROUP \
--name $PRIVATE_DNS_ZONE_NAME
# Link the DNS Zone to the Virtual Network
az network private-dns link vnet create \
--resource-group $RESOURCE_GROUP \
--zone-name $PRIVATE_DNS_ZONE_NAME \
--name "${VNET_NAME}_dns_link" \
--virtual-network $(az network.vnet show --resource-group $RESOURCE_GROUP --name $VNET_NAME --query id -o tsv) \
--registration-enabled false
# Create DNS Zone Group
az network private-endpoint dns-zone-group create \
--resource-group $RESOURCE_GROUP \
--endpoint-name $PRIVATE_ENDPOINT_NAME \
--name "${PRIVATE_ENDPOINT_NAME}_dns_group" \
--private-dns-zone $PRIVATE_DNS_ZONE_NAME \
--zone-name $PRIVATE_DNS_ZONE_NAME
6. Configure VNet Integration for App Service
Now, we’ll enable VNet Integration for the App Service to allow it to connect to resources within our VNet, including the SQL Database.
az webapp vnet-integration add \
--name APP_SERVICE_NAME \
--resource-group $RESOURCE_GROUP \
--vnet $VNET_NAME \
--subnet $APP_SUBNET_NAME
7. Configure the Connection String in App Service
Finally, add the database connection string to the App Service. This ensures that it uses the SQL Database securely over the Private Endpoint.
{
"ConnectionStrings:DefaultConnection": "Server=tcp:<sql_server_name>.database.windows.net,1433;Initial Catalog=<database_name>;Persist Security Info=False;User ID=<username>;Password=<password>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
}
Add this connection string in App Service using the CLI:
az webapp config connection-string set \
--name APP_SERVICE_NAME \
--resource-group $RESOURCE_GROUP \
--settings DefaultConnection="Server=tcp:<sql_server_name>.database.windows.net,1433;Initial Catalog=<database_name>;Persist Security Info=False;User ID=<username>;Password=<password>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
--connection-string-type SQLServer
Wrapping Up
With this setup, you’ve securely connected your .NET app to an Azure SQL Database using Private Endpoints and DNS Zones, fully contained within your Virtual Network. Remember to delete the resources when you’re done to avoid costs:
az group delete --name $RESOURCE_GROUP --yes --no-wait
This hands-on experience with Private Endpoints and DNS Zones deepens your understanding of securing connections in Azure. This setup is a solid foundation for anyone looking to create secure and scalable cloud applications.
Subscribe to my newsletter
Read articles from Freeman Madudili directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by