Skip to content

Terraform module for deploying and managing Azure Virtual Networks with integrated DNS zones and network peering capabilities

Notifications You must be signed in to change notification settings

mbraunwart/terraform-azurerm-networking

Repository files navigation

title author date tags summary
Azure Virtual Networking Module
Matt Braunwart
2024-01-24
azure
network
vnet
dns
terraform
infrastructure
Terraform module for deploying and managing Azure Virtual Networks with integrated DNS zones and network peering capabilities

Azure Enterprise Network Foundation Module

This Terraform module provides an enterprise-ready framework for creating and managing secure, scalable, and compliant Azure Virtual Networks (VNets). It simplifies the deployment of networking components, integrates with Azure DNS and security features, and supports various connectivity models for both cloud-only and hybrid scenarios.

Purpose

The module’s main objective is to streamline the provisioning of Azure networking resources, ensuring they adhere to organizational standards for security and reliability. By packaging best practices into a reusable Terraform module, it reduces the overhead typically associated with large-scale or multi-environment VNet deployments.

Key Capabilities

  • Configurable Network Security Groups (NSGs)
    Enforce default deny-all rules and introduce granular inbound/outbound control to align with zero-trust security principles.

  • Private DNS Zone Integration
    Seamlessly create and link private DNS zones to VNets for internal name resolution, supporting cross-region and cross-subscription scenarios.

  • Hub and Spoke or VHUB Peering
    Establish hub-and-spoke network topologies or connect to Azure Virtual WAN for centralized network management and traffic routing.

  • Azure Monitor and Logging Support
    Stream diagnostic logs and metrics to Azure Monitor and Log Analytics to capture traffic flows, NSG hits, and gateway diagnostics.

Implementation Details

Beneath the surface, this module applies a “security-by-default” philosophy. Every subnet is created with an NSG that denies all inbound and outbound traffic unless explicitly permitted. Private endpoints can be deployed to securely connect to Azure PaaS services, while integrated private DNS ensures name resolution remains internal. Users can customize these behaviors through input variables, allowing the module to fit a broad range of enterprise requirements.

Architecture Overview

The module supports traditional hub-and-spoke designs, where spokes isolate workloads while sharing centralized services in the hub, as well as mesh architectures that provide direct connectivity among all VNets. In hybrid scenarios, you can add an ExpressRoute or VPN Gateway to your network for secure connections to on-premises environments. To further simplify connectivity, the module can attach to Azure Virtual WAN when global or large-scale connectivity is needed.

Best Practices

When deploying multiple VNets, plan out IP address ranges to avoid overlap, especially across different subscriptions or on-premises networks. Use Azure Policy to enforce tagging and logging standards so resources remain consistent. Apply role-based access control (RBAC) to minimize the blast radius of changes, and leverage Log Analytics for detailed monitoring. Finally, adopt the Azure Well-Architected Framework to guide decisions on performance, security, operational excellence, reliability, and cost optimization.

Diagnostic Settings

Diagnostics can be configured to route logs to Log Analytics, Azure Storage, or Event Hubs. This includes flow logs for each NSG, which record traffic details and rule matches. By centralizing logs in Azure Monitor, you gain real-time visibility and can create actionable alerts that help teams respond quickly to network anomalies or security incidents.

Known Limitations

Overlapping IP address spaces in complex networks may require additional planning. Cross-subscription deployments can fail without proper RBAC permissions. Latency in multi-region VNet peering depends on Azure’s global backbone, affecting highly latency-sensitive workloads. Lastly, ensure subscription and service quotas (e.g., number of VNets or peering links) are sufficient for large-scale rollouts.

Usage Example

module "vnet_advanced" {
  source = "github.com/example/terraform-azurerm-network"
  providers = {
    azurerm.prod   = azurerm.prod
    azurerm.shared = azurerm.shared
    azurerm        = azurerm
  }

  resource_group_name = "rg-advanced-network"
  vnet_name           = "vnet-advanced"
  vnet_address_prefixes = ["10.2.0.0/16"]

  subnets = [
    {
      name             = "snet-web"
      address_prefixes = ["10.2.1.0/24"]
      service_endpoints = ["Microsoft.Storage"]
    },
    {
      name             = "snet-db"
      address_prefixes = ["10.2.2.0/24"]
      delegation = {
        name = "db-delegation"
        service_delegation = {
          name    = "Microsoft.Sql/servers"
          actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
        }
      }
    }
  ]

  log_analytics_workspace_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/log-analytics/providers/Microsoft.OperationalInsights/workspaces/loganalytics"
}

Requirements

The following requirements are needed by this module:

Providers

The following providers are used by this module:

Resources

The following resources are used by this module:

Required Inputs

The following input variables are required:

Description: (Required) The environment identifier (e.g., 'dev', 'staging', 'prod'). Used for resource naming convention and environment-specific configurations.

Type: string

Description: (Optional) Map of Public IP configurations to create alongside the Virtual Network.

Properties for each Public IP:

  • name : (Required) Name of the Public IP resource
  • sku : (Required) SKU of the Public IP (Basic or Standard)
  • allocation_method : (Required) IP allocation method (Static or Dynamic)

Note: Standard SKU is required when using with Standard Load Balancer

Type:

map(object({
    allocation_method = string
    sku               = string
    name              = string
  }))

Description: (Required) The name of the Azure Resource Group where the Virtual Network and related resources will be deployed. This resource group must exist before deployment.

Type: string

Description: (Required) Name of the resource group containing shared resources. This resource group is used for Private DNS zones and must exist in the subscription referenced by the 'azurerm.shared' provider.

Type: string

Description: (Required) List of address spaces in CIDR notation for the Virtual Network.
Example: ["10.0.0.0/16", "172.16.0.0/12"]
Ensure these ranges:

  • Don't overlap with existing network ranges
  • Provide sufficient IP space for current and future needs
  • Comply with your organization's IP addressing scheme

Type: list(string)

Description: (Required) The name of the Virtual Network to be created. Should follow your organization's naming convention and clearly identify the network's purpose and environment.

Type: string

Optional Inputs

The following input variables are optional (have default values):

Description: (Optional) Controls whether to create a Private DNS Zone for the Virtual Network. Enable this for private DNS resolution capabilities within the VNet and across peered networks.

Type: bool

Default: false

Description: (Optional) Controls creation of a connection between this VNet and an Azure Virtual WAN hub. Enable for integration with Azure Virtual WAN architecture.

Type: bool

Default: false

Description: (Optional) Number of days to retain diagnostic logs (0-365). Set to 0 for infinite retention. Helps manage compliance and audit requirements while controlling storage costs.

Type: number

Default: 30

Description: (Optional) Resource ID of an existing Private DNS Zone to link with this Virtual Network. This variable is required if create_dns_zone is false and DNS integration is needed.

Type: string

Default: null

Description: (Optional) The DNS subdomain name for the private DNS zone (e.g., "prod.internal.contoso.com").
Required when create_dns_zone is true.
Must be:

  • A valid DNS name format
  • Unique within your DNS hierarchy
  • Compliant with your organization's naming standards

Type: string

Default: ""

Description: (Optional) Custom DNS server IP address for the Virtual Network. When specified, this IP will be configured as the primary DNS server for name resolution within the VNet.

Type: string

Default: null

Description: (Optional) The Azure region where the Virtual Network and associated resources will be created. Defaults to East US if not specified. Should align with your organization's region strategy.

Type: string

Default: "East US"

Description: (Optional) The resource ID of the Log Analytics workspace for diagnostic settings. Required for centralized logging and monitoring of network traffic and events.

Type: string

Default: null

Description: (Optional) List of Virtual Networks to peer with this VNet. Supports both hub-spoke and mesh topologies.

Each peering configuration requires:

  • resource_group_name : (Required) Resource group containing the remote VNet
  • name : (Required) Name of the remote VNet
  • id : (Required) Resource ID of the remote VNet
  • source : (Optional) Outbound peering configuration
    • allow_gateway_transit : (Optional) Allow gateway transit, defaults to true
    • allow_forwarded_traffic : (Optional) Allow forwarded traffic, defaults to true
    • use_remote_gateways : (Optional) Use remote gateways, defaults to true
    • triggers : (Optional) Map of values that trigger peering updates
  • remote : (Optional) Inbound peering configuration
    • Same options as source, plus:
    • provider : (Optional) Provider alias for remote VNet (prod or shared)

Type:

list(object({
    resource_group_name = string
    name                = string
    id                  = string
    source = object({
      allow_gateway_transit   = optional(bool, true)
      allow_forwarded_traffic = optional(bool, true)
      use_remote_gateways     = optional(bool, true)
      triggers                = optional(map(string))
    })
    remote = object({
      allow_gateway_transit   = optional(bool, true)
      allow_forwarded_traffic = optional(bool, true)
      use_remote_gateways     = optional(bool, true)
      provider                = optional(string)
      triggers                = optional(map(string))
    })
  }))

Default: []

Description: (Optional) Defines subnet configurations within the Virtual Network. Each subnet can be customized with security, connectivity, and service integration options.

  • name : (Required) Unique identifier for the subnet (1-80 characters, alphanumeric, hyphens, underscores)

  • address_prefixes : (Required) List of CIDR ranges for the subnet (must be within VNet address space)

  • service_endpoints : (Optional) List of Azure service endpoints to enable on the subnet

  • delegation : (Optional) Configuration for Azure service delegation

    • name : (Required) Name of the delegation configuration
    • service_delegation : (Required) Service-specific delegation settings
      • name : (Required) Azure service to delegate to (e.g., Microsoft.Web/serverFarms)
      • actions : (Required) List of actions the service is allowed to perform
  • nsg_name : (Optional) Name for the Network Security Group

  • security_rules : (Optional) Map of security rules

    • priority : (Required) Rule priority (100-4096)
    • direction : (Required) Traffic direction (Inbound/Outbound)
    • access : (Required) Allow/Deny
    • protocol : (Required) Network protocol
    • source_port_range : (Required) Source port or range
    • destination_port_range : (Required) Destination port or range
    • source_address_prefix : (Required) Source address prefix
    • destination_address_prefix : (Required) Destination address prefix
    • description : (Required) Rule description
  • private_endpoint_network_policies_enabled : (Optional) Enable/disable private endpoint network policies

  • private_link_service_network_policies_enabled : (Optional) Enable/disable private link service network policies

Type:

list(object({
    name              = string
    address_prefixes  = list(string)
    service_endpoints = optional(list(string), [])

    delegation = optional(object({
      name = string
      service_delegation = object({
        name    = string
        actions = list(string)
      })
    }))
    nsg_name = optional(string)
    security_rules = optional(map(object({
      name                       = optional(string, null)
      priority                   = number
      direction                  = string
      access                     = string
      protocol                   = string
      source_port_range          = string
      destination_port_range     = string
      source_address_prefix      = string
      destination_address_prefix = string
      description                = optional(string, "")
    })), {})
    private_endpoint_network_policies_enabled     = optional(bool, true)
    private_link_service_network_policies_enabled = optional(bool, true)

  }))

Default: []

Description: (Optional) A map of tags to be applied to all resources created by this module. Tags help organize and track resources across your Azure infrastructure.

Type: map(string)

Default: {}

Description: (Optional) Configuration for Azure Virtual WAN hub connection. Required if create_virtual_hub_connection is true.

Configuration properties:

  • name : (Required) Name of the Virtual Hub to connect to
  • id : (Required) Resource ID of the Virtual Hub
  • vhub_route_table : (Optional) Route table configuration
    • associated_id : (Optional) Route table to associate with connection
    • inbound_route_map_id : (Optional) Resource ID of inbound route map
    • outbound_route_map_id : (Optional) Resource ID of outbound route map
    • propagated_route_table: (Optional) Route propagation settings

Type:

object({
    name = string
    id   = string
    vhub_route_table = optional(object({
      associated_id         = optional(string)
      inbound_route_map_id  = optional(string)
      outbound_route_map_id = optional(string)
      propagated_route_table = optional(object({
        labels          = list(string)
        route_table_ids = list(string)
      }))
    }), null)
  })

Default: null

Outputs

The following outputs are exported:

Description: Private DNS zone configuration

Description: Network Security Groups configurations

Description: Network peering configurations

Description: Public IP configurations indexed by name

Description: Map of subnet configurations indexed by subnet name

Description: Virtual Hub connection configuration

Description: Virtual Network configuration and properties

About

Terraform module for deploying and managing Azure Virtual Networks with integrated DNS zones and network peering capabilities

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published