A hub-and-spoke network topology is a popular design pattern used to manage and control network traffic when deploying enterprise workloads to Microsoft Azure. This article will guide you through deploying a hub-and-spoke network in Microsoft Azure using HashiCorp Terraform. We will cover the basic concepts, provide sample Terraform code, discuss security best practices to ensure a robust and secure network design, and discuss using Azure Resource Groups to best organize all the Azure resources.

What is a Hub-and-Spoke Network?

A hub-and-spoke network topology is a design where a central hub network connects to multiple spoke networks. The hub network serves as a common point of connectivity and control, while the spoke networks are used for different business units or applications. Every network in Microsoft Azure is implemented as an Azure Virtual Network (VNet). This is a standard networking design in the Azure cloud that simplifies network management, improves security, and optimizes resource usage.

Deploying Hub-and-Spoke Network Topology in Microsoft Azure using Terraform 2
Diagram: Simplified Hub-and-Spoke Network

Key Components of a Hub-and-Spoke Network

Here’s a break out of the key components of a hub-and-spoke network topology:

Central Hub

The Hub network, implemented as an Azure Virtual Nework (VNet), serves as the primary point of connectivity and control for the network topology. This network serves as a central routing point for directing traffic between spokes and external networks; including connectivity to an on-premises network via Azure ExpressRoute or Site-to-Site VPN connectivity.

The Hub network is the home for provisioning certain shared resources used by the organization. These include resources like: DNS, Azure Entra ID (Azure AD), Firewalls, and logging services.

Spoke Networks

The Spoke networks, implemented as Azure Virtual Networks (VNets), serve as the network for connecting services and VMs for specific business units, applications, or environments (e.g. dev, stage, production). The network topology can be made up of as many Spoke VNets as necessary. The Spoke VNets will each have their own IP Address space, as well as provide isolation and more granular control over the networking connectivity and security for specific workloads, applications or sets of Azure resources.

Communication between spokes occurs through the hub, allowing for centralized control over traffic routing and security policies.

Benefits of Hub-and-Spoke Networks

Implementing a hub-and-spoke network topology in Microsoft Azure offers several advantages, making it a preferred choice for many organizations.

Here are explanations of several key benefits of using a hub-and-spoke networking topology:

Centralized Management

In a hub-and-spoke architecture, the hub VNet acts as a central point for managing and monitoring network traffic. This centralization simplifies network operations by providing a single point for configuring and enforcing policies.

The offers several advantages:

  • Unified Control: Centralized control allows network administrators to manage routing, security, and traffic policies from a single location.
  • Simplified Troubleshooting: With all traffic passing through the hub, diagnosing and resolving network issues becomes easier.
  • Consistent Policies: Ensures that security and operational policies are uniformly applied across the network.

Improved Security

The centralized nature of the hub-and-spoke topology enhances security by allowing the implementation of robust security controls at the hub.

The offers several advantages:

  • Centralized Security Appliances: Security appliances like firewalls and intrusion detection systems can be deployed in the hub, protecting all connected spokes.
  • Consistent Security Policies: Uniform security policies can be enforced across all spokes, reducing the risk of misconfigurations.
  • Network Segmentation: Segmentation of the network reduces the attack surface and limits the spread of potential security breaches.

Cost-Effective

The hub-and-spoke model promotes efficient use of resources, leading to cost savings.

The offers several advantages:

  • Shared Resources: Shared services like DNS, logging, and security appliances in the hub reduce duplication and save costs.
  • Optimized Traffic Flow: By routing traffic through the hub, organizations can optimize bandwidth usage and reduce the need for redundant connections.
  • Economies of Scale: Centralizing services and resources in the hub can result in economies of scale, lowering operational costs.

Scalability

The hub-and-spoke architecture is inherently scalable, making it easy to expand as organizational needs grow.

The offers several advantages:

  • Ease of Expansion: New spokes can be added with minimal changes to the existing network infrastructure.
  • Flexibility: Supports diverse application requirements by allowing different spokes to be tailored for specific purposes.
  • Future-Proofing: Accommodates future growth and changes in network demands without significant reconfiguration.

Example Hub-and-Spoke Networking Scenario

Consider an organization with multiple departments, each requiring its own isolated network environment for different applications (e.g., HR, Finance, Development).

Using a hub-and-spoke topology, the organization can:

  1. Centrally manage the network: Manage all network policies, routing, and security controls from the hub VNet.
  2. Improve security: Deploy an Azure Firewall in the hub to inspect and control traffic to and from each spoke VNet and the Hub VNet.
  3. Reduce costs: Share common resources like monitoring, logging, and DNS services hosted in the hub VNet.
  4. Easily scale: Add new departmental networks as spoke VNets without disrupting any existing workloads.

This approach not only streamlines network operations but also enhances security and efficiency, providing a robust framework for the organization’s evolving network needs.

Step-by-Step: Deploy a Hub-and-Spoke Network in Microsoft Azure Using Terraform

Prerequisites

  1. Azure Account: Ensure you have an active Azure subscription.
  2. Terraform: Install Terraform on your local machine.

Step 1: Create Resource Group

An Azure Resource Group provides a structured and efficient way to manage, secure, and monitor resources, facilitating better governance and operational control in your Azure environment.

Create a file named main.tf and add the following code to create a resource group.

resource "azurerm_resource_group" "b59_rg" {
  name     = "b59-hub-spoke-network-rg"
  location = "East US"
}

The Resource Group is essential for organizing and managing all resources in Azure. It serves as a container that holds related resources for an Azure solution, making it easier to manage and organize them.

Step 2: Create Virtual Network with Hub-and-Spokes

A Virtual Network (VNet) in Azure is a fundamental building block for your private network in the cloud. It enables Azure resources, such as virtual machines (VMs), to securely communicate with each other, the internet, and on-premises networks.

Add the following code to main.tf to create the hub-and-spoke VNets.

# Hub VNet
resource "azurerm_virtual_network" "hub_vnet" {
  name                = "hub-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

# Spoke 1 VNet
resource "azurerm_virtual_network" "spoke1_vnet" {
  name                = "spoke1-vnet"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

# Spoke 2 VNet
resource "azurerm_virtual_network" "spoke2_vnet" {
  name                = "spoke2-vnet"
  address_space       = ["10.2.0.0/16"]
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

Step 3: Create Subnets

Subnets are subdivisions of the IP Address space within a network. They allow you to segment the VNet into smaller, manageable sections, each with its own unique range of IP addresses. By dividing a VNet into subnets, you can organize and secure your network resources effectively.

Add the following code to create subnets within each VNet.

# Hub Subnet
resource "azurerm_subnet" "hub_subnet" {
  name                 = "hub-subnet"
  resource_group_name  = azurerm_resource_group.b59_rg.name
  virtual_network_name = azurerm_virtual_network.hub_vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Spoke 1 Subnet
resource "azurerm_subnet" "spoke1_subnet" {
  name                 = "spoke1-subnet"
  resource_group_name  = azurerm_resource_group.b59_rg.name
  virtual_network_name = azurerm_virtual_network.spoke1_vnet.name
  address_prefixes     = ["10.1.1.0/24"]
}

# Spoke 2 Subnet
resource "azurerm_subnet" "spoke2_subnet" {
  name                 = "spoke2-subnet"
  resource_group_name  = azurerm_resource_group.b59_rg.name
  virtual_network_name = azurerm_virtual_network.spoke2_vnet.name
  address_prefixes     = ["10.2.1.0/24"]
}

Step 4: Configure VNet Peering to Connect VNets

VNet Peering is a feature in Microsoft Azure that enables you to connect two or more virtual networks (VNets) directly, allowing resources in different VNets to communicate with each other as if they were on the same network.

VNet Peering is the feature that enables Azure Networking to support the connectivity necessary for deploying a hub-and-spoke network topology.

Add the following code to create VNet peering between the hub-and-spoke VNets.

# Hub to Spoke1 Peering
resource "azurerm_virtual_network_peering" "hub_to_spoke1" {
  name                      = "hub-to-spoke1"
  resource_group_name       = azurerm_resource_group.b59_rg.name
  virtual_network_name      = azurerm_virtual_network.hub_vnet.name
  remote_virtual_network_id = azurerm_virtual_network.spoke1_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = true
  use_remote_gateways          = false
}

# Spoke1 to Hub Peering
resource "azurerm_virtual_network_peering" "spoke1_to_hub" {
  name                      = "spoke1-to-hub"
  resource_group_name       = azurerm_resource_group.b59_rg.name
  virtual_network_name      = azurerm_virtual_network.spoke1_vnet.name
  remote_virtual_network_id = azurerm_virtual_network.hub_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = false
  use_remote_gateways          = false
}

# Hub to Spoke2 Peering
resource "azurerm_virtual_network_peering" "hub_to_spoke2" {
  name                      = "hub-to-spoke2"
  resource_group_name       = azurerm_resource_group.b59_rg.name
  virtual_network_name      = azurerm_virtual_network.hub_vnet.name
  remote_virtual_network_id = azurerm_virtual_network.spoke2_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = true
  use_remote_gateways          = false
}

# Spoke2 to Hub Peering
resource "azurerm_virtual_network_peering" "spoke2_to_hub" {
  name                      = "spoke2-to-hub"
  resource_group_name       = azurerm_resource_group.b59_rg.name
  virtual_network_name      = azurerm_virtual_network.spoke2_vnet.name
  remote_virtual_network_id = azurerm_virtual_network.hub_vnet.id
  allow_virtual_network_access = true
  allow_forwarded_traffic      = true
  allow_gateway_transit        = false
  use_remote_gateways          = false
}

Top Security Best Practices to Consider

Ensuring the security of your hub-and-spoke network in Azure is critical. Always make sure security is planned upfront with any solution deployed to Microsoft Azure.

Below are some of the top security best practices with detailed explanations and code examples.

Use Network Security Groups (NSGs)

NSGs are used to control inbound and outbound traffic to network interfaces (NIC), VMs, and subnets. By defining security rules in NSGs, you can allow or deny traffic based on source and destination IP addresses, ports, and protocols.

# NSG for Hub Subnet
resource "azurerm_network_security_group" "hub_nsg" {
  name                = "hub-nsg"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

# NSG Rule to Allow SSH
resource "azurerm_network_security_rule" "allow_ssh" {
  name                        = "allow-ssh"
  priority                    = 1001
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "Tcp"
  source_port_range           = "*"
  destination_port_range      = "22"
  source_address_prefix       = "*"
  destination_address_prefix  = "*"
  resource_group_name         = azurerm_resource_group.b59_rg.name
  network_security_group_name = azurerm_network_security_group.hub_nsg.name
}

# Associate NSG with Hub Subnet
resource "azurerm_subnet_network_security_group_association" "hub_subnet_nsg" {
  subnet_id                 = azurerm_subnet.hub_subnet.id
  network_security_group_id = azurerm_network_security_group.hub_nsg.id
}

Implement Azure Firewall or Network Virtual Appliances (NVAs)

Azure Firewall is a managed network security service that protects your Azure Virtual Network resources. NVAs are third-party firewall solutions that can provide advanced security capabilities. These are used to inspect and filter traffic between subnets, VNets, and on-premises networks.

# Azure Firewall
resource "azurerm_firewall" "azure_firewall" {
  name                = "hub-firewall"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
  sku_name            = "AZFW_VNet"
  sku_tier            = "Standard"

  ip_configuration {
    name                 = "configuration"
    subnet_id            = azurerm_subnet.hub_subnet.id
    public_ip_address_id = azurerm_public_ip.firewall_pip.id
  }
}

# Public IP for Firewall
resource "azurerm_public_ip" "firewall_pip" {
  name                = "firewall-pip"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

# Route Table for Hub VNet to Direct Traffic through Firewall
resource "azurerm_route_table" "hub_route_table" {
  name                = "hub-route-table"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

resource "azurerm_route" "firewall_route" {
  name                   = "firewall-route"
  resource_group_name    = azurerm_resource_group.b59_rg.name
  route_table_name       = azurerm_route_table.hub_route_table.name
  address_prefix         = "0.0.0.0/0"
  next_hop_type          = "VirtualAppliance"
  next_hop_in_ip_address = azurerm_firewall.azure_firewall.ip_configuration[0].private_ip_address
}

# Associate Route Table with Hub Subnet
resource "azurerm_subnet_route_table_association" "hub_route_association" {
  subnet_id       = azurerm_subnet.hub_subnet.id
  route_table_id  = azurerm_route_table.hub_route_table.id
}

Enable DDoS Protection

DDoS protection helps protect your Azure resources from distributed denial-of-service (DDoS) attacks. Azure provides DDoS Protection Basic by default and DDoS Protection Standard for enhanced protection.

# DDoS Protection Plan
resource "azurerm_ddos_protection_plan" "ddos_plan" {
  name                = "ddos-plan"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
}

# Associate DDoS Protection Plan with Hub VNet
resource "azurerm_virtual_network" "hub_vnet" {
  name                = "hub-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
  ddos_protection_plan {
    id = azurerm_ddos_protection_plan.ddos_plan.id
  }
}

Use Private Endpoints

Private Endpoints are network interfaces that connect you privately and securely to Azure services through a private link, using a private IP address within your virtual network (VNet). Private Endpoints allow you to connect to Azure services over a private IP address in your VNet, ensuring that traffic between your VNet and the service remains within the Azure backbone network.

# Private Endpoint for Storage Account
resource "azurerm_private_endpoint" "storage_pe" {
  name                = "storage-pe"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
  subnet_id           = azurerm_subnet.hub_subnet.id

  private_service_connection {
    name                           = "storage-psc"
    private_connection_resource_id = azurerm_storage_account.example.id
    subresource_names              = ["blob"]
    is_manual_connection           = false
  }
}

# Storage Account
resource "azurerm_storage_account" "example" {
  name                     = "examplestorageacct"
  resource_group_name      = azurerm_resource_group.b59_rg.name
  location                 = azurerm_resource_group.b59_rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

Use Azure Bastion for VM Management

Azure Bastion is a fully managed service that provides secure and seamless RDP/SSH connectivity to your virtual machines directly through the Azure portal. By using Azure Bastion, you eliminate the need to expose your VMs to the public internet via RDP/SSH ports, thereby reducing the risk of brute force attacks.

# Create Subnets
resource "azurerm_subnet" "bastion_subnet" {
  name                 = "AzureBastionSubnet"
  resource_group_name  = azurerm_resource_group.b59_rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.2.0/24"]
}

# Create Public IP for Bastion
resource "azurerm_public_ip" "bastion_pip" {
  name                = "example-bastion-pip"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

# Create Azure Bastion
resource "azurerm_bastion_host" "bastion" {
  name                = "example-bastion"
  location            = azurerm_resource_group.b59_rg.location
  resource_group_name = azurerm_resource_group.b59_rg.name

  dns_name            = "example-bastion"  # Optional: Custom DNS name for Bastion

  ip_configuration {
    name                 = "configuration"
    subnet_id            = azurerm_subnet.bastion_subnet.id
    public_ip_address_id = azurerm_public_ip.bastion_pip.id
  }
}

Regular Audits and Monitoring

Regular audits and continuous monitoring are essential to ensure your network remains secure and compliant with organizational policies and industry regulations. These practices help identify potential security vulnerabilities, misconfigurations, and performance issues before they can be exploited or cause disruptions.

  • Azure Monitor provides comprehensive visibility into the performance and health of your network resources by collecting and analyzing metrics, logs, and events. It enables you to set up alerts for specific conditions, automate responses, and gain insights through dashboards and visualizations.
  • Azure Security Center enhances your security posture by providing advanced threat protection across your Azure resources. It continuously assesses your network for vulnerabilities, recommends best practices to improve security, and offers centralized management of security policies.
  • Azure Policy ensures compliance with corporate standards and service-level agreements by defining and enforcing policies across your Azure environment. It allows you to audit configurations, apply governance rules, and remediate non-compliant resources automatically.

By integrating these tools, you can maintain a proactive security strategy, continuously monitor your network’s health, and ensure compliance with organizational and regulatory requirements.

# Log Analytics Workspace for Monitoring
resource "azurerm_log_analytics_workspace" "log_analytics" {
  name                = "log-analytics-workspace"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

# Enable Diagnostics for Hub VNet
resource "azurerm_monitor_diagnostic_setting" "hub_vnet_diag" {
  name               = "hub-vnet-diagnostics"
  target_resource_id = azurerm_virtual_network.hub_vnet.id
  log_analytics_workspace_id = azurerm_log_analytics_workspace.log_analytics.id

  enabled_log {
    category = "NetworkSecurityGroupEvent"
    retention_policy {
      enabled = false
    }
  }

  metric {
    category = "AllMetrics"
    enabled  = true
    retention_policy {
      enabled = false
    }
  }
}

# Azure Security Center Standard Tier
resource "azurerm_security_center_subscription_pricing" "asc" {
  tier          = "Standard"
  resource_type = "VirtualMachines"
}

Organize using Multiple Azure Resource Groups

The examples in this article for deploying the hub-and-spoke network topology in Microsoft Azure, including all the other example security resource examples, all deploy to a single Azure Resource Group. This makes the code samples simple. However, by deploying all these resources to the same Resource Group, the resulting set of resources will become too disorganized over time to manage. For this reason, it’s best practice to deploy the Azure resources to multiple Resource Groups to better organize everything.

It’s good to deploy each separate workload, application, or other set of resources to a dedicated Azure Resource Group for those resources. This will break things up to be much more manageable as the number of Azure resources deployed increases over time.

Keep in mind, the Hub VNet and shared networking resources are a sort of workload on their own. So, it may be a good idea to create a dedicated Resource Group just for the Hub and related resources. Then a separate Resource Group for each workloads reasources including the Spoke VNet, Subnets, etc. for that workload.

Here’s an example of the Azure Resource Groups for this:

b59-hub-rg
b59-spoke1-rg
b50-spoke2-rg

Another common breakout for many organizations is to create individual Azure Resource Groups for the Hub VNet and different Spoke VNets and their related Azure networking resources accordingly. Then separate Resource Groups for the other application level Azure resources the workload is comprised of. It’s even common enough to deploy the application and database resources for the workload to separate Resource Groups as well. This is a more granular Resource Group break out, that will give more granular security control over management of the various Azure resources that are deployed.

Here’s an example of the Azure Resource Groups for this:

b59-hub-rg
b59-spoke1-net-rg
b59-spoke1-app-rg
b59-spoke1-data-rg
b59-spoke2-net-rg
b59-spoke2-app-rg
b59-spoke2-data-rg

Azure Resource Naming Best Practice: An organization best practice to follow when creating resources in Microsoft Azure is to come up with a naming standard or convention to follow. The “Azure Resource Naming Conventions and Best Practices” article covers this topic in detail.

Conclusion

Deploying a hub-and-spoke network in Azure using Terraform allows you to automate and manage your network infrastructure efficiently. By following the steps outlined in this article, you can set up a scalable and secure network topology that meets your organizational needs. Implementing the recommended security best practices ensures your network is robust and protected against potential threats.

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
Microsoft MVP HashiCorp Ambassador

Discover more from Build5Nines

Subscribe now to keep reading and get access to the full archive.

Continue reading