Skip to content
Cloud architecture templates

Azure — Hub-and-Spoke Landing Zone

The enterprise pattern: a hub virtual network carrying the shared firewall, bastion and gateway, with workload spokes peered to it. Reports clean. Note the boundary edges — traffic that crosses from one virtual network to another names the gateway it crosses at, which is what stops the engine reporting an unexplained boundary crossing.

Template previewCloud architecture
Azure landing zone — hub and spokeAn Azure architecture diagram: 12 resources in 10 scopes (3 networks, 0 availability zones), joined by 11 connections. Categories drawn: Compute, Databases, Networking, Security, Observability, Clients. No error or warning across 12 resources and 11 edges, every line read; 1 of the 10 checks could not run at all and 2 ran only in part — so this is a clean result on the part that could be checked, not a clean bill of health.Azure landing zone — hub and spokeAzure · 12 resources · 10 scopes · 3 networks · 0 zones · 11 connectionsNo error or warning across 12 resources and 11 edges, every line read; 1 of the 10 checks could not run at all and 2 ran only in part — so this is a cleanresult on the part that could be checked, not a clean bill of health.Internetintern…9AccountProduction subscription9On-premisesHead off…9Regionwesteuro…9NetworkHub VNet10.0.0.0/169+NetworkSpoke — application10.1.0.0/169+NetworkSpoke — data10.2.0.0/169+SubnetApplica…10.1.1.0…private9+SubnetManagement10.1.2.0/…private9+SubnetD…10.2.1.0…isolated9+Staff—4+Customers—4+AzureFirewallaz6+Bastion hostaz4+VPN gatewayaz6+Applicationgatewayaz4+Order APIaz×34+Jump hostaz4+Orders databaseaz4+Key vaultaz1+Azure Monitoraz3+Directoryserveraz6+https 443https 443https 443 · via fwssh 22ssh 22 · via fwipsec 500ldaps 636 · via fwtds 1433 · via fwhttps 443LegendComputeDatabasesNetworkingSecurityObservabilityClientsRequest trafficDepends onChecks — what ran, and what could notWhether the internet reaches something that ho…ran over 8 subjects, found nothingWhether anything holding data at rest sits in …ran over 1 subject, 1 gap — a partial passWhether anything claiming redundancy is spread…could not run here — 1 reason givenEdges that leave one network for another, or c…ran over 10 subjects, 1 gap — a partial passResources that appear in no edge at all. A leg…ran over 12 subjects, found nothingEvery id an edge or a scope names is one that …ran over 12 subjects, found nothingEach id is declared once. Two declarations mak…ran over 22 subjects, found nothingType words that did not resolve. A hole in thi…ran over 12 subjects, found nothingDeclared ranges: that each parses, sits inside…ran over 6 subjects, found nothingWhether every line was read and no shape cap b…ran over 22 subjects, found nothingFindings1`kv` holds data at rest and sits inside no subnet at all, so nothing in this document says whether it is publicly routable and this check had nothing to read.in the figure: kv2This document declares no availability zone, so the redundancy check DID NOT RUN AT ALL: nothing here claims redundancy either, so nothing was missed. Declare thezones (`zone az-a`, `zone az-b`) and put the resources inside them, and the claim becomes checkable.3`kv` and `mon` are joined to something inside a network but sit in no network, internet or on-premises scope of their own, so whether those edges cross a boundaryCOULD NOT BE DECIDED.in the figure: kv (badge 1), mon4The walk reached 8 resources from the internet; every one of the 2 that hold data at rest — `orders` and `kv` — sits behind an ingress.in the figure: staff, customers, agw, bastion, api +3 more5The one datastore this check could read — `orders` — sits in a subnet declared private or isolated.in the figure: orders (badge 4)6Every edge this check could read stays inside one network, stays outside all of them, or names a gateway to cross at; 10 endpoints were read across 3 declarednetworks.in the figure: customers (badge 4), agw (badge 4), staff (badge 4), api (badge 4), bastion (badge 4) +5 more7All 12 declared resources appear in at least one edge.in the figure: staff (badge 4), customers (badge 4), ad (badge 6), fw (badge 6), bastion (badge 4) +7 more8All 12 ids named by edges and scopes were declared somewhere in this document.in the figure: customers (badge 4), agw (badge 4), staff (badge 4), api (badge 4), fw (badge 6) +7 more9All 22 declared ids are distinct.in the figure: internet, hq, sub, westeurope, hub +17 more10All 12 resources resolved to a type this engine knows, so every check above had the full vocabulary to read.in the figure: staff (badge 4), customers (badge 4), ad (badge 6), fw (badge 6), bastion (badge 4) +7 more11All 6 declared ranges parse, each of the 3 drawn inside an addressed network sits inside it, and no two ranges under one parent share an address. The 3 subnets thathave instances drawn in them hold them. Ranges under different parents were not compared — two networks numbered alike is ordinary and correct.in the figure: hub (badge 9), spoke-app (badge 9), app (badge 9), mgmt (badge 9), spoke-data (badge 9) +1 more12Every line was read and no shape cap bit: the 22 declarations above are the whole document, so the counts are totals rather than floors.

Make it your own.

title "Azure landing zone — hub and spoke"
provider azure

internet {
  user staff "Staff"
  user customers "Customers"
}

onprem hq "Head office" {
  server ad "Directory server"
}

cloud sub "Production subscription" {
  region westeurope {
    network hub "Hub VNet" cidr 10.0.0.0/16 {
      firewall fw "Azure Firewall"
      bastion bastion "Bastion host"
      vpn-gateway vpngw "VPN gateway"
      app-gateway agw "Application gateway"
    }

    network spoke-app "Spoke — application" cidr 10.1.0.0/16 {
      subnet app "Application" private cidr 10.1.1.0/24 {
        app-service api "Order API" count 3 tier api
      }
      subnet mgmt "Management" private cidr 10.1.2.0/24 {
        vm jump "Jump host"
      }
    }

    network spoke-data "Spoke — data" cidr 10.2.0.0/16 {
      subnet data "Data" isolated cidr 10.2.1.0/24 {
        sql-database orders "Orders database"
      }
    }

    key-vault kv "Key vault"
    monitor mon "Azure Monitor"
  }
}

customers -> agw : https 443
staff -> agw : https 443
agw -> api : https 443 via fw
staff -> bastion : ssh 22
bastion -> jump : ssh 22 via fw
ad -> vpngw : ipsec 500
vpngw -> api : ldaps 636 via fw
api -> orders : tds 1433 via fw
api -> kv : https 443
mon ..> api
mon ..> orders