Home / Azure

AzureRunbookAdvanced

Transformation: move Azure PaaS from public endpoints to Private Link without an outage

A phased plan to put Storage, SQL, Key Vault and other PaaS services behind private endpoints. Build DNS first, add endpoints alongside public access, move clients, then disable public network access with policy.

Deepak Bhardwaj3 min read

Applies toAzure Private Link, Azure Private DNS, Azure Storage, Azure SQL, Key Vault, App Service, Azure Policy

The order that avoids outages

  1. DNS architecture
  2. Private endpoints added (public access still on)
  3. Clients moved to private paths and verified
  4. Public network access disabled
  5. Policy to keep it that way

Teams that start with step 4 cause the outage this plan is meant to avoid.

1. DNS first

  • Create the privatelink.* zones you need (one per service type: privatelink.blob.core.windows.net, privatelink.database.windows.net, privatelink.vaultcore.azure.net, …) in a central resource group.
  • Link them to the hub VNet where your DNS resolver lives and to any VNet that uses Azure-provided DNS.
  • On-premises: conditional forwarders for the public zone names (blob.core.windows.net etc.) to an Azure DNS Private Resolver inbound endpoint.
az network private-dns zone create -g rg-dns -n privatelink.blob.core.windows.net
az network private-dns link vnet create -g rg-dns -z privatelink.blob.core.windows.net -n link-hub \
  --virtual-network <hub-vnet-id> --registration-enabled false

2. Add private endpoints

az network private-endpoint create -g rg-data -n pe-stdata-blob \
  --vnet-name vnet-spoke-data --subnet snet-pe \
  --private-connection-resource-id <storage-account-id> --group-id blob \
  --connection-name stdata-blob

az network private-endpoint dns-zone-group create -g rg-data --endpoint-name pe-stdata-blob \
  -n default --private-dns-zone privatelink.blob.core.windows.net --zone-name blob

Public access is still on, so nothing breaks yet. Clients that resolve the private IP start using it immediately.

3. Move and verify clients

From each client network, check resolution returns the private IP:

nslookup stdata.blob.core.windows.net
Client What to do
App Service / Functions VNet integration, and WEBSITE_VNET_ROUTE_ALL / route-all enabled
AKS, VMs in peered spokes Hub DNS resolver or zone links
On-premises Conditional forwarders to the resolver
Developers' laptops over the internet VPN / point-to-site, or keep a tightly restricted public path
Azure services (ADF, Synapse, Fabric) Managed private endpoints or trusted-services exceptions

Watch the service logs: requests should now come from private IPs.

StorageBlobLogs
| where TimeGenerated > ago(1d)
| summarize count() by CallerIpAddress

4. Disable public access

az storage account update -g rg-data -n stdata --public-network-access Disabled
az sql server update -g rg-sql -n sql-prod --enable-public-network false
az keyvault update -n kv-prod --public-network-access Disabled

Do one service at a time, during business hours with the owners watching.

Warning

Check managed services that reach your resources from Microsoft networks (backup, Defender scans, Azure Monitor, Power BI). Some need a trusted-services exception or their own private endpoints.

5. Enforce

Assign Azure Policy definitions that deny public network access for each service type, and DeployIfNotExists policies that create DNS zone groups for new private endpoints.

Checklist

  • Central private DNS zones linked; on-prem forwarding works
  • Endpoints and DNS zone groups for each resource
  • Logs show clients on private IPs only
  • Public network access disabled per resource
  • Deny policies assigned