Skip to content

Private Endpoints — Database (SQL)

Overview

Each environment’s Azure SQL Server is reachable only over a private endpoint — there is no public access path. The private endpoint lives in the spoke VNet’s PE subnet and registers an A record in the privatelink.database.windows.net private DNS zone, so apps, VMs, and VPN clients resolve sql-eshars-{env}-cus.database.windows.net to the private IP.

This is created by the workload-env root, once per environment (dev, qa, regression, training, uat, prod). The SQL private DNS zone itself is owned by the workload-network root (it is intentionally not a global zone — see below).

Resources

Defined in infrastructure/workload-env/main.tf (azurerm_private_endpoint.sql):

AttributeValue
PE namepe-sql-sql-eshars-{env}-cus (pe-sql-${local.sql_name})
Connection namepe-sql-sql-eshars-{env}-cus-psc
Resource grouprg-eshars-data-{tier}-cus (the env’s data RG)
Subnetsnet-pe-eshars-{tier}-cus (PE subnet in the spoke VNet)
Targetmodule.sql_server.id
subresource_names["sqlServer"]
is_manual_connectionfalse
DNS zone groupdefaultprivatelink.database.windows.net

The SQL Server module sets public_network_access_enabled = false, so the private endpoint is the only ingress.

DNS Configuration

The private endpoint joins a private_dns_zone_group that points at the SQL private DNS zone:

Zoneprivatelink.database.windows.net
Owned byworkload-network root (azurerm_private_dns_zone.sql)
Resource grouprg-eshars-{tier}-network-cus (spoke network RG)
ScopePer tier (nonprod / prod)

Unlike the blob and vaultcore zones — which are global, region-less zones in rg-eshars-global-{tier} (owned by control-plane-dns-zones) — the SQL zone deliberately lives with the spoke network. workload-env reads it via a data "azurerm_private_dns_zone" "sql" lookup in local.rg_network.

The spoke VNet is linked to this zone so anything in the spoke resolves the SQL FQDN to the PE IP. VPN clients resolve it through the DNS forwarder (vm-eshars-dns-{tier}-cus) → see INFRA-0009.

Application DNS Alias Layer

Applications do not connect to the raw SQL FQDN. workload-env also creates a per-environment custom zone db.{env}.eshars.internal (the private-dns module) with CNAME aliases:

  • eshars-primary.db.{env}.eshars.internal
  • eshars-reporting.db.{env}.eshars.internal

These CNAME to the SQL server FQDN, which then resolves via the private endpoint to the private IP. Connection strings use the alias, so the underlying server can be swapped without a config redeploy. CNAME targets are managed operationally; Terraform uses lifecycle { ignore_changes } and does not own them. See Application Infrastructure.

Testing Connectivity

From a host inside the spoke (e.g. the ops VM) or over the VPN:

Terminal window
# Should resolve to a 10.x private IP, not a public one
nslookup sql-eshars-dev-cus.database.windows.net
# Resolve via the app alias (CNAME -> SQL FQDN -> private IP)
nslookup eshars-primary.db.dev.eshars.internal
# TCP reachability to SQL
Test-NetConnection sql-eshars-dev-cus.database.windows.net -Port 1433

If the FQDN resolves to a public IP, the PE’s private_dns_zone_group link or the VNet-to-zone link is missing.