All posts
2 min read

Zero-Public-IP Architecture: Securing Azure Landing Zones with Bicep

A hub-and-spoke landing zone with no public IPs, private endpoints for every PaaS service, and OIDC federation replacing standing credentials.

A strong firewall at the edge and a soft interior is a design that assumes the perimeter holds. In healthcare and fintech it has to survive the assumption that it does not — because once an attacker is inside a flat network, lateral movement and exfiltration are unobstructed.

For an enterprise hybrid cloud migration the mandate was specific: the Azure landing zone must contain zero reachable public assets. No public IPs, no open RDP or SSH management ports, no standing administrative credentials.

Hub-and-spoke, codified

I codified the infrastructure in Azure Bicep as a hub-and-spoke topology. The hub holds shared services and does the inspection; the spokes hold the workloads and have no direct outbound internet path of their own.

HUB-AND-SPOKE LANDING ZONEOUTSIDE AZUREHUB VNETshared servicesSPOKE VNET · APP TIER SUBNETSPOKE VNET · DATA TIER SUBNETdeny all inbound except app tierOn-premises datacentercorporate networkPublic internetno route to any subnetBLOCKEDAzure FirewallDPI · threat intelligencePrivate DNS zonesprivate name resolutionInternal load balancerprivate IP, internal onlyAKS worker nodesapplication podsAzure SQLprivate endpointCosmosDBprivate endpointAzure Key Vaultprivate endpoint1. IPSec VPN / ExpressRouteno inbound route2. resolve privately3. VNet peering, no transit4. distribute5. private endpoint5. private endpoint5. private endpointnumbered happy pathblocked path
The data tier denies all inbound except from the app tier, and every PaaS service is reached by private endpoint — nothing traverses the public backbone.

How traffic moves through it

  1. The on-premises corporate datacenter reaches Azure over an IPSec VPN or ExpressRoute circuit — the only connection into the estate.
  2. In the hub, Azure Firewall applies centralised traffic control with deep packet inspection and threat intelligence, and private DNS zones resolve names for the private endpoints so nothing has to look anything up publicly.
  3. VNet peering connects hub to spoke under strict NSG routing rules, with no transit traffic allowed — spokes cannot reach each other through the hub.
  4. Inside the spoke's app tier subnet, an internal load balancer on a private IP distributes to AKS worker nodes that are internal-only.
  5. The data tier subnet denies all inbound except from the app tier, and exposes Azure SQL, CosmosDB and Key Vault solely through private endpoints.

The public internet has no route into either subnet. That is not a firewall rule that could be relaxed — there is no public IP to route to.

Removing the credential, not rotating it

Deploying into a fully private environment normally means a jump box or a corporate VPN, and both bring their own administrative overhead and rotation risk. OIDC workload identity federation removes the question.

DEPLOYING INTO IT WITHOUT A CREDENTIALDELIVERYIDENTITYTARGETGitHub Actionsno stored client secretMicrosoft Entra IDOIDC federationShort-lived tokenscoped to the runAKSSHA-tagged imageMicrosoft Defendercontinuous posture1. federated request2. issue3. promote imagesurface stays zeronumbered happy pathcontinuous validation
There is no secret in the pipeline to rotate or leak — the token is issued per run and expires with it.

Rather than holding a privileged Azure client secret in the CI/CD platform, GitHub Actions requests an ephemeral token from Microsoft Entra ID, scoped to the duration of that run, and uses it to promote a SHA-tagged container image into AKS. Microsoft Defender continuously validates that the exposed surface has not moved.

There is no long-lived credential in the pipeline to rotate, leak, or audit — which is a materially different security posture from rotating one on a schedule. If the federation fails, the pipeline gets no token and the deployment stops, because there is nothing to fall back on by design.