Brewing a Secure Hub-and-Spoke in Azure - Azure Firewall Premium

Azure Firewall Premium, your security barista on duty

If the hub-and-spoke is the café itself, Azure Firewall Premium is the barista making sure every shot pulled (packet inspected) is clean, safe, and consistent. You can run hub‑and‑spoke without it, but would you trust your flat white to a dodgy apprentice? Exactly.

What is Azure Firewall Premium?

Azure Firewall Premium is Microsoft’s managed, cloud-native next-gen firewall service. It’s not just packet filtering; it brings in deeper traffic inspection that usually required third-party NVAs. Its main feature set includes:

  • TLS Inspection: Decrypt and inspect HTTPS traffic.
  • IDPS (Intrusion Detection & Prevention System): Detects and blocks malicious activity in both inbound (north-south) and internal (east-west) flows.
  • Threat Intelligence-Based Filtering: Blocks or alerts on traffic to/from known malicious IPs/domains.
  • Web Categories: Allows policy setting by application category (e.g. block “Gambling” in corporate networks).

How it Works

  • North-South Traffic (Internet ↔ Workloads)
    Routes all inbound/outbound through Azure Firewall Premium. TLS inspection and IDPS help catch suspicious connections before they hit your apps.

  • East-West Traffic (Spoke ↔ Spoke or VNet ↔ VNet)
    Use UDRs to force inter‑VNet traffic through the hub firewall. This enables inspection of internal movement (lateral traffic) and is critical for Zero Trust.

  • Policy Enforcement
    Azure Firewall uses Firewall Policy objects (separate resource) for consistent, reusable rule configuration. Policies can be shared across multiple firewalls in different regions.

Here’s what the secure traffic flow looks like:

graph TD Internet --> FW[Azure Firewall Premium] FW --> HubVNet[Hub VNet] HubVNet --> Spoke1[Spoke VNet 1] HubVNet --> Spoke2[Spoke VNet 2] HubVNet --> Spoke3[Spoke VNet 3] Spoke1 -->|East-West| FW Spoke2 -->|East-West| FW

Real-World Impact

Think of these scenarios:

  • Ransomware: Malware spreads laterally between spokes. With east-west inspection enabled, the firewall can detect and block suspicious SMB traffic.
  • Phishing: An internal VM gets popped and tries calling a C2 (command-and-control) endpoint. Threat intelligence filtering stops the outbound connection.
  • Compliance: TLS inspection ensures sensitive data flows are logged and inspected, satisfying regulatory requirements.

Without these features, most orgs would need an NVA like Palo Alto, Fortinet, or Check Point. Azure Firewall Premium narrows that gap.

Implementation Examples

Azure Portal

  1. Create a Firewall Policy (Premium).
    • Enable TLS Inspection with a Key Vault certificate.
    • Turn on IDPS in Alert or Alert+Block mode.
    • Enable Threat Intelligence Mode (Alert or Deny).
  2. Attach the Firewall Policy to your Azure Firewall Premium instance.
  3. Add Application Rules (e.g. allow HTTPS, block categories).
  4. Add Network Rules for traffic needing explicit control.

Bicep Example — Firewall Policy with TLS Inspection, IDPS & Threat Intel

To continue on our previous post where we split things into modules we have created a few new resources in order to enable this feature set.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/bicep
  ├─ main.bicep              # Entry point
  ├─ modules/
  |   ├─ azfw.bicep          # Azure Firewall
  |   ├─ azfwpolicy.bicep    # Azure Firewall Policy
  |   ├─ azfwpolicypremium.bicep    # Azure Firewall Premium Policy
  |   ├─ keyvault.bicep      # Azure KeyVault + Managed Identity (Required for TLS Inspection)
  │   ├─ hub.bicep           # Hub VNet + Firewall Subnet
  │   ├─ spoke.bicep         # Spoke VNet + NSG + UDR
  │   └─ peering.bicep       # Hub-Spoke peering

🔹 main.bicep — Root deployment updated

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Deploy Key Vault & TLS Inspection cert
module keyVault './modules/keyvault.bicep' = {
  name: 'keyVaultDeployment'
  params: {
    location: location
    certName: 'AzFwTlsCert'
    certSubject: 'CN=AzFwTlsCert.brewedinthecloud.com'
    keyVaultName: 'kv-azfw-hub'
  }  
}

// Deploy Azure Firewall Premium Policy
module azfwPolicyPremium './modules/azfwpolicypremium.bicep' = {
  name: 'azfwPolicyPremiumDeployment'
  params: {
    location: location
    policyName: 'myAzureFirewallPolicyPremium'
    managedid: keyVault.outputs.managedIdentityId
    certName: keyVault.outputs.certName
    threatIntelMode: 'Alert'
    idpsMode: 'Alert'
  }
}

🔹 modules/keyvault.bicep — Deploy a KeyVault & Certificate for TLS Inspection

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
@description('Name of the Key Vault')
param keyVaultName string

@description('Location of the Key Vault')
param location string = resourceGroup().location

@description('Certificate name to create in the Key Vault')
param certName string = 'AzFwTlsCert'

@description('Subject name for the self-signed certificate')
param certSubject string = 'CN=AzFwTlsCert.brewedinthecloud.com'

@description('Key Vault SKU')
param kvSku string = 'standard'

resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
  name: keyVaultName
  location: location
  properties: {
    tenantId: subscription().tenantId
    sku: {
      family: 'A'
      name: kvSku
    }
    enabledForDeployment: false
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: false
  }
}

resource kvCert 'Microsoft.KeyVault/vaults/certificates@2023-07-01' = {
  name: '${keyVault.name}/${certName}'
  properties: {
    secretProperties: {
      contentType: 'application/x-pkcs12'
    }
    x509CertificateProperties: {
      subject: certSubject
      validityInMonths: 12
      keyUsage: [
        'digitalSignature'
        'keyEncipherment'
      ]
    }
    keyProperties: {
      exportable: true
      keyType: 'RSA'
      keySize: 2048
      reuseKey: false
    }
    issuerParameters: {
      name: 'Self'
    }
    createMode: 'Default'
  }
  dependsOn: [
    keyVault
  ]
}

resource kvmangedid 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
  name: '${keyVault.name}-mi'
  location: location
}

resource kvAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2023-07-01' = {
  name: '${keyVault.name}/add'
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: kvmangedid.properties.principalId
        permissions: {
          certificates: [
            'get'
            'list'
          ]
          secrets: [
            'get'
            'list'
          ]
          keys: [
            'get'
            'list'
          ]
        }
      }
    ]
  }
  dependsOn: [
    keyVault
    kvmangedid
  ]
}

output keyVaultId string = keyVault.id
output certSecretId string = kvCert.properties.secretId
output certName string = kvCert.name
output managedIdentityId string = kvmangedid.id

🔹 modules/azfwpolicypremium.bicep — Deploy a new Firewall Policy on premium Tier

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@description('Name of the Azure Firewall Policy')
param policyName string

@description('Location of the Firewall Policy')
param location string = resourceGroup().location

@description('Object ID of the Azure Firewall managed identity (for cert access)')
param managedid string

@description('Certificate name to create in the Key Vault')
param certName string = 'AzFwTlsCert'

@description('Threat intelligence mode (Off, Alert, Deny)')
param threatIntelMode string = 'Alert'

@description('IDPS mode (Off, Alert, AlertAndBlock)')
param idpsMode string = 'Alert'

resource azfwPolicy 'Microsoft.Network/firewallPolicies@2023-11-01' = {
  name: policyName
  location: location
  properties: {
    threatIntelMode: threatIntelMode
    intrusionDetection: {
      mode: idpsMode
    }
    sku: {
      tier: 'Premium'
    }
    transportSecurity: {
      certificateAuthority: {
        keyVaultSecretId: 'https://kv-azfw-hub.vault.azure.net/secrets/${certName}'
        name: certName
      }
    }
  }
}

output policyId string = azfwPolicy.id
output policyNameOut string = azfwPolicy.name

Gotchas & Edge Cases

  • TLS Inspection + Certificates: You’ll need to manage a trusted root CA in Key Vault and distribute the cert to clients. Miss that and apps will break.
  • Performance Overhead: TLS decryption eats into throughput and adds latency. Size accordingly.
  • IDPS Tuning: Default signatures can be noisy. You’ll likely need to tune exclusions.
  • Costs: Firewall Policy Premium and TLS inspection certificate handling do add to bills. Don’t enable everything blindly.

Best Practices

  • Attach multiple firewalls to the same Policy for consistent management.
  • Start IDPS in Alert mode before jumping into block. Get a baseline, then tighten up.
  • Use categories where possible (e.g. block “High Risk Domains”) to reduce rule sprawl.
  • Instrument with Log Analytics immediately – you’ll want visibility into which inspection rules are firing.
🍺
Brewed Insight:

Azure Firewall Premium isn’t perfect — NVAs from big vendors still win on advanced integrations. But for most enterprises in Azure, especially if you’re centralising security in a hub-and-spoke, Premium gets you 80% of the way with far less operational sweat.

Your mileage? Depends on whether you need user‑identity controls and advanced VPN terminations — if not, Azure Firewall Premium is usually the better roast.

Learn More