Creates an Azure virtual network and its subnets, with each subnet's optional NSG and route table associations. Route tables and NSGs are separate modules; this one associates them by id.
A single virtual network plus its subnets (keyed map, stable for_each). Each subnet sets its
prefixes, service endpoints, delegations (name the service; the actions are looked up from
subnet_delegation_actions), and an optional NSG / route table id that the module associates. NSGs
and route tables are owned by the separate nsg and route-table modules, so this composes by id
without depending on them. Need subnets on an existing vnet from another stack? Use the standalone
subnet module, which shares this subnet schema.
Secure defaults: subnets default to private_endpoint_network_policies = "Enabled" (enforces NSG
and route rules on private endpoints) and default_outbound_access_enabled = false (no implicit
outbound; Azure is retiring default outbound, so attach an explicit egress such as the nat-gateway
module). Both are overridable per subnet.
module "network" {
source = "libre-devops/network/azurerm"
version = "~> 4.0"
resource_group_id = module.rg.ids["rg-ldo-uks-prd-001"]
location = "uksouth"
tags = module.tags.tags
vnet_name = "vnet-ldo-uks-prd-001"
address_space = ["10.0.0.0/16"]
subnets = {
"snet-app-vnet-ldo-uks-prd-001" = {
address_prefixes = ["10.0.1.0/24"]
service_endpoints = ["Microsoft.Storage"]
delegations = ["Microsoft.Web/serverFarms"]
}
}
# Associations are keyed by subnet name; the ids may be computed in the same apply.
nsg_associations = {
"snet-app-vnet-ldo-uks-prd-001" = module.nsg.id
}
}examples/minimal- a virtual network with one subnet.examples/complete- multiple subnets with service endpoints, a delegation, and NSG / route table associations.
Both examples call the tags and rg modules first, then this module.
Local work needs PowerShell 7+ and just, because the recipes
wrap the LibreDevOpsHelpers
PowerShell module (the same engine the libre-devops/terraform-azure action runs in CI). Install
just with brew install just, or uv tool add rust-just then uv run just <recipe>.
Run just to list recipes: just update-ldo-pwsh (install or force-update LibreDevOpsHelpers from
PSGallery), just validate, just scan (Trivy only), just pwsh-analyze (PSScriptAnalyzer only),
just plan, just apply, just destroy, just e2e, just test, and just docs (the
plan/apply/destroy recipes mirror the action, including the storage firewall dance; just e2e
applies an example then always destroys it, defaulting to minimal, so nothing is left running).
Releasing is also just:
just increment-release [patch|minor|major] bumps, tags, and publishes a GitHub release, and the
Terraform Registry picks up the tag.
This module is scanned with Trivy; HIGH and CRITICAL
findings fail the build. Any waiver is a deliberate, reviewed decision, never a way to quiet a
finding that should be fixed. Waivers live in .trivyignore.yaml (the
machine-applied source of truth, passed to Trivy with --ignorefile) and are mirrored in the table
below so the reason is auditable.
| Trivy ID | Resource | Finding | Justification |
|---|---|---|---|
| None |
To add an exception: add an entry to .trivyignore.yaml (id, optional paths to scope it, and a
statement recording why), then add a matching row here. Where the finding is out of this module's
scope, point the justification at the Libre DevOps module that does address it (for example the
private-endpoint module). Both the file and this table are reviewed in the pull request.
The Requirements, Providers, Inputs, Outputs, and Resources below are generated by terraform-docs.
| Name | Version |
|---|---|
| terraform | >= 1.9.0, < 2.0.0 |
| azurerm | >= 4.0.0, < 5.0.0 |
| Name | Version |
|---|---|
| azurerm | >= 4.0.0, < 5.0.0 |
No modules.
| Name | Type |
|---|---|
| azurerm_subnet.this | resource |
| azurerm_subnet_network_security_group_association.this | resource |
| azurerm_subnet_route_table_association.this | resource |
| azurerm_virtual_network.this | resource |
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| address_space | Address space (CIDR ranges) for the virtual network. Set this OR ip_address_pool, not both. | list(string) |
[] |
no |
| bgp_community | BGP community for the virtual network, in the format :. Null for none. | string |
null |
no |
| ddos_protection_plan | DDoS protection plan to associate. id is the plan resource id; enable defaults to true but the caller controls it. Null for none. | object({ |
null |
no |
| dns_servers | Custom DNS servers for the virtual network. Empty uses Azure-provided DNS. | list(string) |
[] |
no |
| edge_zone | Edge zone within the Azure region. Null for none. | string |
null |
no |
| encryption_enforcement | When set, enables virtual network encryption with this enforcement. Allowed: AllowUnencrypted, DropUnencrypted. Null leaves encryption unset: encryption needs supported VM SKUs, and encrypted vnets do not support the DNS Private Resolver, Application Gateway, or Azure Firewall, so it is opt-in. | string |
null |
no |
| flow_timeout_in_minutes | Flow timeout in minutes (4 to 30). Null uses the Azure default. | number |
null |
no |
| ip_address_pool | Allocate the virtual network's address space from a Network Manager IPAM pool. Set this OR address_space, not both. | object({ |
null |
no |
| location | Azure region for the virtual network. | string |
n/a | yes |
| nsg_associations | Map of subnet name to network security group id to associate. Keys are subnet names (must exist in subnets); values may be computed in the same apply (the static keys keep for_each valid). | map(string) |
{} |
no |
| private_endpoint_vnet_policies | Private endpoint policy mode for the virtual network. Allowed: Disabled, Basic. | string |
"Disabled" |
no |
| resource_group_id | Resource id of the resource group to create the virtual network and subnets in. The name and subscription are parsed from it (pass the rg module's ids output, for example module.rg.ids["rg-..."]). | string |
n/a | yes |
| route_table_associations | Map of subnet name to route table id to associate. Keys are subnet names (must exist in subnets); values may be computed in the same apply. | map(string) |
{} |
no |
| subnet_delegation_actions | Lookup of subnet delegation service name to its delegated actions. A subnet's delegations reference these by service name; a service not listed here falls back to the platform-inferred actions. | map(list(string)) |
{ |
no |
| subnets | Subnets to create in the virtual network, keyed by subnet name. Each subnet sets its address prefixes (or ip_address_pool) and optional service endpoints, delegations (service names only; the actions are looked up from subnet_delegation_actions), and policy flags. NSG and route table associations are separate inputs (nsg_associations / route_table_associations) so their ids may be computed in the same apply. Secure defaults: private_endpoint_network_policies defaults to "Enabled" (enforces NSG and route table rules on private endpoints), and default_outbound_access_enabled defaults to false (no implicit outbound internet; Azure is retiring default outbound, so attach an explicit egress such as the nat-gateway module). Both are overridable per subnet. |
map(object({ |
{} |
no |
| tags | Tags to apply to the virtual network. | map(string) |
{} |
no |
| vnet_name | Name of the virtual network. | string |
n/a | yes |
| Name | Description |
|---|---|
| resource_group_name | Resource group name parsed from resource_group_id. |
| subnet_address_prefixes | Map of subnet name to its address prefixes. |
| subnet_ids | Map of subnet name to its id. |
| subnet_ids_zipmap | Map of subnet name to a { name, id } object, so the whole object can be passed where something needs the name and id together. |
| subnet_names | The subnet names. |
| subnet_nsg_association_ids | Map of subnet name to its network security group association id. |
| subnet_route_table_association_ids | Map of subnet name to its route table association id. |
| subnets | The full azurerm_subnet resources, keyed by subnet name. |
| subscription_id | Subscription id parsed from resource_group_id. |
| tags | The tags applied to the virtual network. |
| vnet_address_space | The address space of the virtual network. |
| vnet_dns_servers | The DNS servers set on the virtual network. |
| vnet_guid | The GUID of the virtual network. |
| vnet_id | The id of the virtual network. |
| vnet_location | The region of the virtual network. |
| vnet_name | The name of the virtual network. |
| vnet_resource_group_name | The resource group of the virtual network. |
| vnet_tags | The tags on the virtual network. |