This site is under development and subject to change. Please do not rely on the information contained here. Look out for some exciting updates to Azure Landing Zones coming in 2025!
Azure Landing Zones Documentation
Home GitHub Issue Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage
Edit page

Terraform - Azure Verified Modules for Platform Landing Zone (ALZ)

The platform_landing_zone starter module deploys the end to end platform landing zone using Azure Verified Modules. It is fully configurable to meet different scenarios.

This documentation covers the top scenarios and documents all available configuration settings for this module.

We aim to cover 80% of common scenarios. If the particular scenario is not covered here, it may be possible to adjust the configuration settings to match the requirements. If not, then it my be the case you need to adjust their Terraform code post bootstrap.

This documentation covers the following:

Usage

To use the starter module, follow the detailed steps documented in phases 1, 2, and 3 of the Accelerator. Here we cover come specifics of this starter module.

There are 3 sets of configuration that can be supplied to the accelerator to pre-configure it.

The available configuration inputs are:

Bootstrap Configuration File

This is the YAML file used to provide the base configuration required to bootstrap your version control system and Azure.

Some of this configuration is also fed into this starter module. You will see a terraform.tfvars.json file is created to hold these inputs. They include management group ID, subscriptions IDs, starter locations, etc.

We provide examples of this file for each version control system. These can be found in the Phase 2 documentation, but are also listed here for convenience:

Platform Landing Zone Configuration File

This is the tfvars file in HCL format that determines which resources are deployed and what type of hub networking connectivity is deployed.

This file is validated by the accelerator and then directly copied to your repository, so it retains the ordering, comments, etc. You will see the file is renamed to *.auto.tfvars, so that it is automatically picked up by Terraform.

We provide examples of this file for each scenario. These can be found in the scenarios documentation.

Platform Landing Zone Library (lib) Folder

This is a folder of configuration files used to customize the management groups and associated policies. This library and its usage is documented alongside the avm-ptn-alz module. However, we cover a common customization use case in our How To section.

By default we supply an empty lib folder. This folder can be overridden with a set of files to customize Management Groups and Policy Assignments. Use cases include:

  • Renaming management groups
  • Customizing the management group structure
  • Removing policy assignments
  • Adding custom policy definitions and assignments

The detailed documentation for the library and it’s usage can be found here:

Scenarios

Scenarios are common use cases when deploying the platform landing zone. The following section provide a description of the scenario and link to the pre-configured files for that scenario.

The available scenarios are:

Multi-Region Hub and Spoke Virtual Network with Azure Firewall

A full platform landing zone deployment with hub and spoke Virtual Network connectivity using Azure Firewall in multiple regions.

Multi-Region Virtual WAN with Azure Firewall

A full platform landing zone deployment with Virtual WAN network connectivity using Azure Firewall in multiple regions.

Multi-Region Hub and Spoke Virtual Network with Network Virtual Appliance (NVA)

A full platform landing zone deployment with hub and spoke Virtual Network connectivity in multiple regions, ready for a third party Network Virtual Appliance (NVA).

Multi-Region Virtual WAN with Network Virtual Appliance (NVA)

A full platform landing zone deployment with Virtual WAN network connectivity in multiple regions, ready for a third party Network Virtual Appliance (NVA).

Single-Region Hub and Spoke Virtual Network with Azure Firewall

A full platform landing zone deployment with hub and spoke Virtual Network connectivity using Azure Firewall in a single region.

The single region option is here for completeness, we recommend always having at least 2 regions to support resiliency.

Single-Region Virtual WAN with Azure Firewall

A full platform landing zone deployment with Virtual WAN network connectivity using Azure Firewall in a single region.

The single region option is here for completeness, we recommend always having at least 2 regions to support resiliency.

Management Groups, Policy and Management Resources Only

A platform landing zone deployment without any connectivity resources.

Options

The options section details how to make configuration changes that apply to the common scenarios.

The available options are:

Customize Management Group Names and IDs

You may want to customize the management groups names and IDs. In order to do this they need to supply a lib folder to the accelerator.

The lib folder should contain the following structure (we are showing it nested under the standard accelerator file structure here):

📂accelerator
┣ 📂config
┃ ┣ 📂lib
┃ ┃ ┗ 📂architecture_definitions
┃ ┃   ┗ 📜alz.alz_architecture_definition.json
┃ ┗ 📜inputs.yaml
┗ 📂output
The lib folder must be named lib, any other name will not work

The alz.alz_architecture_definition.json file content should be copied from here.

You can then edit this configuration file to update the management group names and IDs.

For example to prefix all the management group display names with Contoso and update the management group IDs to have the contoso- prefix they can update the file to look like this:

 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
{
  "$schema": "https://raw.githubusercontent.com/Azure/Azure-Landing-Zones-Library/main/schemas/architecture_definition.json",
  "name": "alz",
  "management_groups": [
    {
      "archetypes": [
        "root"
      ],
      "display_name": "Contoso",
      "exists": false,
      "id": "contoso-root",
      "parent_id": null
    },
    {
      "archetypes": [
        "platform"
      ],
      "display_name": "Contoso Platform",
      "exists": false,
      "id": "contoso-platform",
      "parent_id": "contoso-root"
    },
    {
      "archetypes": [
        "landing_zones"
      ],
      "display_name": "Contoso Landing zones",
      "exists": false,
      "id": "contoso-landingzones",
      "parent_id": "contoso-root"
    },
    {
      "archetypes": [
        "corp"
      ],
      "display_name": "Contoso Corp",
      "exists": false,
      "id": "contoso-corp",
      "parent_id": "contoso-landingzones"
    },
    {
      "archetypes": [
        "online"
      ],
      "display_name": "Contoso Online",
      "exists": false,
      "id": "contoso-online",
      "parent_id": "contoso-landingzones"
    },
    {
      "archetypes": [
        "sandboxes"
      ],
      "display_name": "Contoso Sandboxes",
      "exists": false,
      "id": "contoso-sandboxes",
      "parent_id": "contoso-root"
    },
    {
      "archetypes": [
        "management"
      ],
      "display_name": "Contoso Management",
      "exists": false,
      "id": "contoso-management",
      "parent_id": "contoso-platform"
    },
    {
      "archetypes": [
        "connectivity"
      ],
      "display_name": "Contoso Connectivity",
      "exists": false,
      "id": "contoso-connectivity",
      "parent_id": "contoso-platform"
    },
    {
      "archetypes": [
        "identity"
      ],
      "display_name": "Contoso Identity",
      "exists": false,
      "id": "contoso-identity",
      "parent_id": "contoso-platform"
    },
    {
      "archetypes": [
        "decommissioned"
      ],
      "display_name": "Contoso Decommissioned",
      "exists": false,
      "id": "contoso-decommissioned",
      "parent_id": "contoso-root"
    }
  ]
}
When updating the management group id, you also need to consider any child management groups that refer to it by the parent_id

Now, when deploying the accelerator they need to supply their lib folder as an argument with starterAdditionalFiles:

Deploy-Accelerator -inputs "c:\accelerator\config\inputs.yaml", "c:\accelerator\config\networking.yaml" -starterAdditionalFiles "c:\accelerator\config\lib" -output "c:\accelerator\output"

Turn off DDOS protection plan

You can choose to not deploy a DDOS protection plan. In order to do that, they need to remove the DDOS protection plan configuration and disable the DINE (deploy if not exists) policy. You can either comment out or remove the configuration entirely.

DDOS Protection plan is a critical security protection for public facing services. Carefully consider this and be sure to put in place an alternative solution, such as per IP protection.

The steps to follow are:

  1. To keep the code tidy remove the follow settings from custom_replacements.names:
  2. ddos_resource_group_name
  3. ddos_protection_plan_name
  4. To keep the code tidy remove the follow settings from custom_replacements.resource_group_identifiers:
  5. ddos_protection_plan_resource_group_id
  6. To keep the code tidy remove the follow settings from custom_replacements.resource_identifiers:
  7. ddos_protection_plan_id
  8. Remove the follow configuration settings from management_group_settings.policy_default_values:
  9. ddos_protection_plan_id
  10. Add the follow section to management_group_settings.policy_assignments_to_modify:
    connectivity = {
      policy_assignments = {
        Enable-DDoS-VNET = {
          enforcement_mode = "DoNotEnforce"
        }
      }
    }
    
  11. Remove the whole ddos_protection_plan section from hub_and_spoke_vnet_settings or virtual_wan_settings

Turn off Bastion host

You can choose to not deploy a Bastion Host. In order to do that, they need to remove the Bastion Host configuration. You can either comment out or remove the configuration entirely.

The steps to follow are:

  1. To keep the code tidy remove the follow settings from custom_replacements.names:
  2. <region>_bastion_subnet_address_prefix where <region> is for each region
  3. Remove the whole bastion section from each hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs region

Turn off Private DNS zones and Private DNS resolver

You can choose to not deploy any DNS related resources. In order to do that, they need to remove the DNS configuration and disable the DINE (deploy if not exists) policy. You can either comment out or remove the configuration entirely.

The steps to follow are:

  1. To keep the code tidy remove the follow settings from custom_replacements.names:

  2. dns_resource_group_name

  3. <region>_private_dns_resolver_subnet_address_prefix where <region> is for each region

  4. Remove the follow configuration settings from management_group_settings.policy_default_values:

  5. private_dns_zone_subscription_id

  6. private_dns_zone_region

  7. private_dns_zone_resource_group_name

  8. Add the follow section to management_group_settings.policy_assignments_to_modify:

    corp = {
      policy_assignments = {
        Deploy-Private-DNS-Zones = {
          enforcement_mode = "DoNotEnforce"
        }
      }
    }
    
  9. Remove the whole private_dns_zones section from each hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs region

Turn off Virtual Network Gateways

You can choose to not deploy any Virtual Network Gateways. In order to do that, you need to remove the Virtual Network Gateway configuration. You can either comment out or remove the configuration entirely.

The steps to follow are:

  1. To keep the code tidy remove the follow settings from custom_replacements.names:
  2. <region>_gateway_subnet_address_prefix where <region> is for each region
  3. Remove the whole virtual_network_gateways section from each hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs region

You can also just turn off the specific Virtual Network Gateway types you don’t want to deploy.

For ExpressRoute Virtual Network Gateways:

  1. Remove the whole express_route section from the virtual_network_gateways section in each hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs region

For VPN Virtual Network Gateways:

  1. Remove the whole vpn section from the virtual_network_gateways section in each hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs region

Additional Regions

Additional regions are supported. The custom can add up to 10 regions using the out of the box module.

If you need to scale beyond 10 regions, that can be accommodated by adding additional built in replacements here

To add an additional regions, the process is copy -> paste -> update:

  1. Copy, paste and update the regional resource group names in custom_replacements.names
  2. Copy, paste and update the regional IP Ranges in custom_replacements.names
  3. Copy, paste and update the regional resource group in connectivity_resource_groups
  4. Copy, paste and update the region in hub_and_spoke_vnet_virtual_networks or virtual_wan_virtual_hubs

IP Address Ranges

The example configuration files that include connectivity include an out of the box set of ip address ranges. These ranges have been chosen to support a real world scenario with optimal use to avoid ip exhaustion as you scale. However you may not want to use these ranges if they may overlap with their existing ranges or they are planning to scale beyond the /16 per region we cater for.

In order to update the IP ranges, you can update the custom_replacements.names section that includes the IP ranges. For example if you prefer to use 172.16 or 192.168, they could update the ranges as follows:

 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
# Example of 172.16 IP ranges for a hub and spoke Virtual Network
# NOTE: The 172.16 prefix is only suitable for medium sized deployments as it only supports 1,000,000 ip addresses)
custom_replacements = {
  names = {
    # IP Ranges Primary
    # Regional Address Space: 172.16.0.0/16
    primary_hub_address_space                          = "172.16.0.0/16"
    primary_hub_virtual_network_address_space          = "172.16.0.0/22"
    primary_firewall_subnet_address_prefix             = "172.16.0.0/26"
    primary_bastion_subnet_address_prefix              = "172.16.0.64/26"
    primary_gateway_subnet_address_prefix              = "172.16.0.128/27"
    primary_private_dns_resolver_subnet_address_prefix = "172.16.0.160/28"

    # IP Ranges Secondary
    # Regional Address Space: 172.17.0.0/16
    secondary_hub_address_space                          = "172.17.0.0/16"
    secondary_hub_virtual_network_address_space          = "172.17.0.0/22"
    secondary_firewall_subnet_address_prefix             = "172.17.0.0/26"
    secondary_bastion_subnet_address_prefix              = "172.17.0.64/26"
    secondary_gateway_subnet_address_prefix              = "172.17.0.128/27"
    secondary_private_dns_resolver_subnet_address_prefix = "172.17.0.160/28"
  }
}
# Example of 192.168 IP ranges for a hub and spoke Virtual Network
# NOTE that the 192.168 prefix is only suitable for a small, isngle region deployment as it only supports 65,000 ip addresses)
custom_replacements = {
  names = {
    # IP Ranges Primary
    # Regional Address Space: 192.168.0.0/16
    primary_hub_address_space                          = "192.168.0.0/16"
    primary_hub_virtual_network_address_space          = "192.168.0.0/22"
    primary_firewall_subnet_address_prefix             = "192.168.0.0/26"
    primary_bastion_subnet_address_prefix              = "192.168.0.64/26"
    primary_gateway_subnet_address_prefix              = "192.168.0.128/27"
    primary_private_dns_resolver_subnet_address_prefix = "192.168.0.160/28"
  }
}

# Example of 172.16 IP ranges for a Virtual WAN
# NOTE: The 172.16 prefix is only suitable for medium sized deployments as it only supports 1,000,000 ip addresses)
custom_replacements = {
  names = {
    # IP Ranges Primary
    # Regional Address Space: 172.16.0.0/16
    primary_hub_address_space                          = "172.16.0.0/22"
    primary_side_car_virtual_network_address_space     = "172.16.4.0/22"
    primary_bastion_subnet_address_prefix              = "172.16.4.0/26"
    primary_private_dns_resolver_subnet_address_prefix = "172.16.4.64/28"

    # IP Ranges Secondary
    # Regional Address Space: 172.17.0.0/16
    secondary_hub_address_space                          = "172.17.0.0/22"
    secondary_side_car_virtual_network_address_space     = "172.17.4.0/22"
    secondary_bastion_subnet_address_prefix              = "172.17.4.0/26"
    secondary_private_dns_resolver_subnet_address_prefix = "172.17.4.64/28"
  }
}
# Example of 192.168 IP ranges for a Virtual WAN
# NOTE that the 192.168 prefix is only suitable for a small, isngle region deployment as it only supports 65,000 ip addresses)
custom_replacements = {
  names = {
    # IP Ranges Primary
    # Regional Address Space: 192.168.0.0/16
    primary_hub_address_space                          = "10.0.0.0/22"
    primary_side_car_virtual_network_address_space     = "10.0.4.0/22"
    primary_bastion_subnet_address_prefix              = "10.0.4.0/26"
    primary_private_dns_resolver_subnet_address_prefix = "10.0.4.64/28"
  }
}

Platform landing zone configuration file

This section details the available configuration settings / variables in this starter module.

Custom Replacements (custom_replacements)

The custom_replacements variable builds on the built-in replacements to provide user defined replacements that can be used throughout your configuration. This reduces the complexity of the configuration file by allowing re-use of names and other definitions that may be repeated throughout the configuration.

There are 4 layers of replacements that can be built upon to provide the level of flexibility you need. The order of precedence determines which other replacements can be used to build your replacement. For example a ‘Name’ replacement can be used to build a ‘Resource Group Identifier’ replacement, but a ‘Resource Group Identifier’ replacement cannot be used to build a ‘Name’ replacement.

The layers and precedence order is:

  1. Built-in Replacements: These can be found at the top of our example config files and you can also see them in the code base here
  2. Names: This is for resource names and other basic strings
  3. Resource Group Identifiers: This is for resource group IDs
  4. Resource Identifiers: This is for resource IDs

Names (custom_replacements.names)

Used to define custom names and strings that can be used throughout the configuration file. This can leverage the built-in replacements.

Exanple usage:

 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
custom_replacements = {
  names = {
    # Resource group names
    management_resource_group_name                 = "rg-management-$${starter_location_01}"
    connectivity_hub_primary_resource_group_name   = "rg-hub-$${starter_location_01}"
    connectivity_hub_secondary_resource_group_name = "rg-hub-$${starter_location_02}"
    dns_resource_group_name                        = "rg-hub-dns-$${starter_location_01}"
    ddos_resource_group_name                       = "rg-hub-ddos-$${starter_location_01}"
    asc_export_resource_group_name                 = "rg-asc-export-$${starter_location_01}"

    # Resource names
    log_analytics_workspace_name            = "law-management-$${starter_location_01}"
    ddos_protection_plan_name               = "ddos-$${starter_location_01}"
    automation_account_name                 = "aa-management-$${starter_location_01}"
    ama_user_assigned_managed_identity_name = "uami-management-ama-$${starter_location_01}"
    dcr_change_tracking_name                = "dcr-change-tracking"
    dcr_defender_sql_name                   = "dcr-defender-sql"
    dcr_vm_insights_name                    = "dcr-vm-insights"

    # IP Ranges Primary
    # Regional Address Space: 10.0.0.0/16
    primary_hub_address_space                          = "10.0.0.0/16"
    primary_hub_virtual_network_address_space          = "10.0.0.0/22"
    primary_firewall_subnet_address_prefix             = "10.0.0.0/26"
    primary_bastion_subnet_address_prefix              = "10.0.0.64/26"
    primary_gateway_subnet_address_prefix              = "10.0.0.128/27"
    primary_private_dns_resolver_subnet_address_prefix = "10.0.0.160/28"
  }
}

Resource Group Identifiers (custom_replacements.resource_group_identifiers)

Used to define resource group IDs that can be used throughout the configuration file. This can leverage the built-in replacements and custom names.

Exanple usage:

1
2
3
4
5
6
custom_replacements = {
  resource_group_identifiers = {
    management_resource_group_id           = "/subscriptions/$${subscription_id_management}/resourcegroups/$${management_resource_group_name}"
    ddos_protection_plan_resource_group_id = "/subscriptions/$${subscription_id_connectivity}/resourcegroups/$${ddos_resource_group_name}"
  }
}

Resource Identifiers (custom_replacements.resource_identifiers)

Used to define resource IDs that can be used throughout the configuration file. This can leverage the built-in replacements, custom names, and resource group IDs.

Exanple usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
custom_replacements = {
  resource_identifiers = {
    ama_change_tracking_data_collection_rule_id = "$${management_resource_group_id}/providers/Microsoft.Insights/dataCollectionRules/$${dcr_change_tracking_name}"
    ama_mdfc_sql_data_collection_rule_id        = "$${management_resource_group_id}/providers/Microsoft.Insights/dataCollectionRules/$${dcr_defender_sql_name}"
    ama_vm_insights_data_collection_rule_id     = "$${management_resource_group_id}/providers/Microsoft.Insights/dataCollectionRules/$${dcr_vm_insights_name}"
    ama_user_assigned_managed_identity_id       = "$${management_resource_group_id}/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$${ama_user_assigned_managed_identity_name}"
    log_analytics_workspace_id                  = "$${management_resource_group_id}/providers/Microsoft.OperationalInsights/workspaces/$${log_analytics_workspace_name}"
    ddos_protection_plan_id                     = "$${ddos_protection_plan_resource_group_id}/providers/Microsoft.Network/ddosProtectionPlans/$${ddos_protection_plan_name}"
  }
}

Enable Telemetry (enable_telemetry)

The enable_telemetry variable determines whether telemetry about module usage is sent to Microsoft, enabling us to invest in improvements to the Accelerator and Azure Verified Modules.

Example usage:

1
enable_telemetry = true

Tags (tags)

The tags variable is a default set of tags to apply to resources that support them. In many cases, these tags can be overriden on a per resource basis.

Example usage:

1
2
3
4
tags = {
  deployed_by = "terraform"
  source      = "Azure Landing Zones Accelerator"
}

Management Resource Settings (management_resource_settings)

The management_resource_settings variable is used to configure the management resources. This includes the log analytics workspace, automation account, and data collection rules for Azure Monitoring Agent (AMA).

This variable is of type any as it maps directly to the Azure Verified Module variables. To determine what can be supplied to this variable you can refer to the documentation for this module directly:

Documentation link: registry.terraform.io/modules/Azure/avm-ptn-alz-management

Example usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
management_resource_settings = {
  automation_account_name      = "$${automation_account_name}"
  location                     = "$${starter_location_01}"
  log_analytics_workspace_name = "$${log_analytics_workspace_name}"
  resource_group_name          = "$${management_resource_group_name}"
  user_assigned_managed_identities = {
    ama = {
      name = "$${ama_user_assigned_managed_identity_name}"
    }
  }
  data_collection_rules = {
    change_tracking = {
      name = "$${dcr_change_tracking_name}"
    }
    defender_sql = {
      name = "$${dcr_defender_sql_name}"
    }
    vm_insights = {
      name = "$${dcr_vm_insights_name}"
    }
  }
}

Management Group Settings (management_group_settings)

The management_group_settings variable is used to configure the management groups, policies, and policy role assignments.

This variable is of type any as it maps directly to the Azure Verified Module variables. To determine what can be supplied to this variable you can refer to the documentation for this module directly:

Documentation link: registry.terraform.io/modules/Azure/avm-ptn-alz

Example usage:

 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
management_group_settings = {
  location           = "$${starter_location_01}"
  architecture_name  = "alz"
  parent_resource_id = "$${root_parent_management_group_id}"
  # Example of how to set default values for policy parameters
  policy_default_values = {
    ama_change_tracking_data_collection_rule_id = "$${ama_change_tracking_data_collection_rule_id}"
    ama_mdfc_sql_data_collection_rule_id        = "$${ama_mdfc_sql_data_collection_rule_id}"
    ama_vm_insights_data_collection_rule_id     = "$${ama_vm_insights_data_collection_rule_id}"
    ama_user_assigned_managed_identity_id       = "$${ama_user_assigned_managed_identity_id}"
    ama_user_assigned_managed_identity_name     = "$${ama_user_assigned_managed_identity_name}"
    log_analytics_workspace_id                  = "$${log_analytics_workspace_id}"
    ddos_protection_plan_id                     = "$${ddos_protection_plan_id}"
    private_dns_zone_subscription_id            = "$${subscription_id_connectivity}"
    private_dns_zone_region                     = "$${starter_location_01}"
    private_dns_zone_resource_group_name        = "$${dns_resource_group_name}"
  }
  # Example of how to place the 3 platform subscriptions under their management groups
  subscription_placement = {
    identity = {
      subscription_id       = "$${subscription_id_identity}"
      management_group_name = "identity"
    }
    connectivity = {
      subscription_id       = "$${subscription_id_connectivity}"
      management_group_name = "connectivity"
    }
    management = {
      subscription_id       = "$${subscription_id_management}"
      management_group_name = "management"
    }
  }
  policy_assignments_to_modify = {
    # Example of how to update a policy assignment parameters for Defender for Cloud
    alzroot = {
      policy_assignments = {
        Deploy-MDFC-Config-H224 = {
          parameters = {
            ascExportResourceGroupName                  = "$${asc_export_resource_group_name}"
            ascExportResourceGroupLocation              = "$${starter_location_01}"
            emailSecurityContact                        = "security_contact@replace_me"
            enableAscForServers                         = "DeployIfNotExists"
            enableAscForServers                         = "DeployIfNotExists"
            enableAscForServersVulnerabilityAssessments = "DeployIfNotExists"
            enableAscForSql                             = "DeployIfNotExists"
            enableAscForAppServices                     = "DeployIfNotExists"
            enableAscForStorage                         = "DeployIfNotExists"
            enableAscForContainers                      = "DeployIfNotExists"
            enableAscForKeyVault                        = "DeployIfNotExists"
            enableAscForSqlOnVm                         = "DeployIfNotExists"
            enableAscForArm                             = "DeployIfNotExists"
            enableAscForOssDb                           = "DeployIfNotExists"
            enableAscForCosmosDbs                       = "DeployIfNotExists"
            enableAscForCspm                            = "DeployIfNotExists"
          }
        }
      }
    }
    # Example of how to update a policy assignment enforcement mode for DDOS Protection Plan
    connectivity = {
      policy_assignments = {
        Enable-DDoS-VNET = {
          enforcement_mode = "DoNotEnforce"
        }
      }
    }
  }
}

Connectivity Type (connectivity_type)

The connectivity_type variable is used to choose the type of connectivity to deploy. Supported values are:

  • hub_and_spoke_vnet: Deploy hub and spoke networking using Azure Virtual Networks
  • virtual_wan: Deploy Azure Virtual WAN networking
  • none: Don’t deploy any networking

Example usage:

1
2
3
4
5
6
7
8
# Example of how to use a hub and spoke Virtual Network for connectivity
connectivity_type = "hub_and_spoke_vnet"

# Example of how to use a Virtual WAN for connectivity
connectivity_type = "virtual_wan"

# Example of how to disable connectivity
connectivity_type = "none"

Connectivity Resource Groups (connectivity_resource_groups)

The connectivity_resource_groups variable is used to specify the name and location of the resource groups used for connectivity.

This variable is a map(object) and has two properties:

  • name: The resource group name
  • location: The resource group location

Example usage:

 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
# Example for hub and spoke Virtual Network
connectivity_resource_groups = {
  ddos = {
    name     = "$${ddos_resource_group_name}"
    location = "$${starter_location_01}"
  }
  vnet_primary = {
    name     = "$${connectivity_hub_primary_resource_group_name}"
    location = "$${starter_location_01}"
  }
  vnet_secondary = {
    name     = "$${connectivity_hub_secondary_resource_group_name}"
    location = "$${starter_location_02}"
  }
  dns = {
    name     = "$${dns_resource_group_name}"
    location = "$${starter_location_01}"
  }
}

# Example for Virtual WAN
connectivity_resource_groups = {
  ddos = {
    name     = "$${ddos_resource_group_name}"
    location = "$${starter_location_01}"
  }
  vwan = {
    name     = "$${connectivity_hub_vwan_resource_group_name}"
    location = "$${starter_location_01}"
  }
  vwan_hub_primary = {
    name     = "$${connectivity_hub_primary_resource_group_name}"
    location = "$${starter_location_01}"
  }
  vwan_hub_secondary = {
    name     = "$${connectivity_hub_secondary_resource_group_name}"
    location = "$${starter_location_02}"
  }
  dns = {
    name     = "$${dns_resource_group_name}"
    location = "$${starter_location_01}"
  }
}

Hub and Spoke Virtual Network Settings (hub_and_spoke_vnet_settings)

The hub_and_spoke_vnet_settings variable is used to set the non-regional settings for the hub and spoke Virtual Network connectivity option. It is only used to set the DDOS Protection Plan at this time.

This variable is of type any as it will be used for other purposes moving forward.

Example usage:

1
2
3
4
5
6
7
hub_and_spoke_vnet_settings = {
  ddos_protection_plan = {
    name                = "$${ddos_protection_plan_name}"
    resource_group_name = "$${ddos_resource_group_name}"
    location            = "$${starter_location_01}"
  }
}

Hub and Spoke Virtual Networks (hub_and_spoke_vnet_virtual_networks)

The hub_and_spoke_vnet_virtual_networks variable is used to set the regional settings for the hub and spoke Virtual Network connectivity options. This includes Hub Networks, Peering, Routing, Subnets, Firewalls, Virtual Network Gateways, Bastion Hosts, Private DNS Zones, and Private DNS Resolver

This variable is of type map(object). Some of the object properties map directly to the Azure Verified Module variables. To determine what can be supplied to these variable you can refer to the documentation for this module directly.

The map(object) definition can be found here.

The supported object properties are:

  • hub_virtual_network: This object maps directly to the variables of the Azure Verified Module, which can be found here: registry.terraform.io/modules/Azure/avm-ptn-hubnetworking
  • bastion: This an object to specify the Bastion Host settings (omit this object if you don’t want to deploy a Bastion Host)
  • virtual_network_gateways: This an object to specify the Virtual Network Gateways settings (omit this object if you don’t want to deploy any Virtual Network Gateways)
  • private_dns_zones: This an object to specify the Private DNS Zone settings (omit this object if you don’t want to deploy any Private DNS Zones)
    • subnet_address_prefix: The Private DNS Resolver subnet address space
    • resource_group_name: The name of the resource group to deploy the Private DNS Zones into
    • is_primary: Whether this is the primary region. Any non-regional Private Link Private DNS Zones will be deployed into this region. Although the Private DNS Zones are a global resource, their meta-data needs to reside in a specific region.
    • private_link_private_dns_zones: This is a map(object) used to override the Private Link Private DNS Zones that are deployed, leave this empty to deploy the default set of zones specified by ALZ
      • zone_name: The name of the Private DNS Zone to deploy
    • auto_registration_zone_enabled: Whether to deploy the Virtual Machine auto-registration Private DNS Zone
    • auto_registration_zone_name: The name of the Virtual Machine auto-registration Private DNS Zone
    • private_dns_resolver: This is an object to specify the Private DNS Resolver
      • name: The name of the Private DNS Resolver
      • resource_group_name: The name of the resource group to deploy the Private DNS Resolver into
      • ip_address: The static IP Address of the Private DNS Resolver. This will be auto calculated if not supplied

Example usage:

 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
hub_and_spoke_vnet_virtual_networks = {
  primary = {
    # Example hub network settings for this region
    hub_virtual_network = {
      name                            = "vnet-hub-$${starter_location_01}"
      resource_group_name             = "$${connectivity_hub_primary_resource_group_name}"
      resource_group_creation_enabled = false
      location                        = "$${starter_location_01}"
      address_space                   = ["$${primary_hub_virtual_network_address_space}"]
      routing_address_space           = ["$${primary_hub_address_space}"]
      route_table_name_firewall       = "rt-hub-fw-$${starter_location_01}"
      route_table_name_user_subnets   = "rt-hub-std-$${starter_location_01}"
      mesh_peering                    = true
      ddos_protection_plan_id         = "$${management_resource_group_id}/providers/Microsoft.Network/ddosProtectionPlans/$${ddos_protection_plan_name}"
      subnets                         = {}
      # Example Azure Firewall settings for this region (omit this section if not using Azure Firewall)
      firewall = {
        subnet_address_prefix = "$${primary_firewall_subnet_address_prefix}"
        name                  = "fw-hub-$${starter_location_01}"
        sku_name              = "AZFW_VNet"
        sku_tier              = "Standard"
        zones                 = "$${starter_location_01_availability_zones}"
        default_ip_configuration = {
          public_ip_config = {
            name  = "pip-fw-hub-$${starter_location_01}"
            zones = "$${starter_location_01_availability_zones}"
          }
        }
        # Example firewall policy settings for this region
        firewall_policy = {
          name = "fwp-hub-$${starter_location_01}"
        }
      }
    }
    # Example Virtual Network Gateway settings for this region (omit this section if not using Virtual Network Gateway)
    virtual_network_gateways = {
      subnet_address_prefix = "$${primary_gateway_subnet_address_prefix}"
      # Example ExpressRoute settings for this region (omit this section if not using ExpressRoute)
      express_route = {
        location = "$${starter_location_01}"
        name     = "vgw-hub-expressroute-$${starter_location_01}"
        sku      = "$${starter_location_01_virtual_network_gateway_sku_express_route}"
        ip_configurations = {
          default = {
            name = "ipconfig-vgw-hub-expressroute-$${starter_location_01}"
            public_ip = {
              name  = "pip-vgw-hub-expressroute-$${starter_location_01}"
              zones = "$${starter_location_01_availability_zones}"
            }
          }
        }
      }
      # Example VPN Gateway settings for this region (omit this section if not using VPN Gateway)
      vpn = {
        location = "$${starter_location_01}"
        name     = "vgw-hub-vpn-$${starter_location_01}"
        sku      = "$${starter_location_01_virtual_network_gateway_sku_vpn}"
        ip_configurations = {
          default = {
            name = "ipconfig-vgw-hub-vpn-$${starter_location_01}"
            public_ip = {
              name  = "pip-vgw-hub-vpn-$${starter_location_01}"
              zones = "$${starter_location_01_availability_zones}"
            }
          }
        }
      }
    }
    # Example Private DNS Zone settings for this region (omit this section if not using Private DNS Zones)
    private_dns_zones = {
      resource_group_name            = "$${dns_resource_group_name}"
      is_primary                     = true
      auto_registration_zone_enabled = true
      auto_registration_zone_name    = "$${starter_location_01}.azure.local"
      subnet_address_prefix          = "$${primary_private_dns_resolver_subnet_address_prefix}"
      private_dns_resolver = {
        name = "pdr-hub-dns-$${starter_location_01}"
      }
    }
    # Example Bastion Host settings for this region (omit this section if not using Bastion Host)
    bastion = {
      subnet_address_prefix = "$${primary_bastion_subnet_address_prefix}"
      bastion_host = {
        name = "bastion-hub-$${starter_location_01}"
      }
      bastion_public_ip = {
        name  = "pip-bastion-hub-$${starter_location_01}"
        zones = "$${starter_location_01_availability_zones}"
      }
    }
  }
}

Virtual WAN Settings (virtual_wan_settings)

The virtual_wan_settings variable is used to set the non-regional settings for the Virtual WAN connectivity option. It is used to set the Virtual WAN non-regional properites and the DDOS Protection Plan.

This variable is of type any as it maps directly to the Azure Verified Module variables. To determine what can be supplied to this variable you can refer to the documentation for this module directly:

Documentation link: registry.terraform.io/modules/Azure/avm-ptn-virtualwan

Example usage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
virtual_wan_settings = {
  name                = "vwan-$${starter_location_01}"
  resource_group_name = "$${connectivity_hub_vwan_resource_group_name}"
  location            = "$${starter_location_01}"
  ddos_protection_plan = {
    name                = "$${ddos_protection_plan_name}"
    resource_group_name = "$${ddos_resource_group_name}"
    location            = "$${starter_location_01}"
  }
}

Virtual WAN Virtual Hubs (virtual_wan_virtual_hubs)

The hub_and_spoke_vnet_virtual_networks variable is used to set the regional settings for the Virtual WAN connectivity options. This includes Virtual WAN Hubs, Firewalls, Virtual Network Gateways, Bastion Hosts, Private DNS Zones, and Private DNS Resolver

This variable is of type map(object). Some of the object properties map directly to the Azure Verified Module variables. To determine what can be supplied to these variable you can refer to the documentation for this module directly.

The map(object) definition can be found here.

The supported object properties are:

  • hub: This object maps directly to the virtual_hubs variable of the Azure Verified Module, which can be found here: registry.terraform.io/modules/Azure/avm-ptn-virtualwan
  • firewall: This object maps directly to the firewalls variable of the Azure Verified Module, which can be found here: registry.terraform.io/modules/Azure/avm-ptn-virtualwan
  • firewall_policy: This object maps directly to the Azure Verified Module, which can be found here: registry.terraform.io/modules/Azure/avm-res-network-firewallpolicy
  • bastion: This an object to specify the Bastion Host settings (omit this object if you don’t want to deploy a Bastion Host)
  • virtual_network_gateways: This an object to specify the Virtual Network Gateways settings (omit this object if you don’t want to deploy any Virtual Network Gateways)
  • private_dns_zones: This an object to specify the Private DNS Zone settings (omit this object if you don’t want to deploy any Private DNS Zones)
    • subnet_address_prefix: The Private DNS Resolver subnet address space
    • resource_group_name: The name of the resource group to deploy the Private DNS Zones into
    • is_primary: Whether this is the primary region. Any non-regional Private Link Private DNS Zones will be deployed into this region. Although the Private DNS Zones are a global resource, their meta-data needs to reside in a specific region.
    • private_link_private_dns_zones: This is a map(object) used to override the Private Link Private DNS Zones that are deployed, leave this empty to deploy the default set of zones specified by ALZ
      • zone_name: The name of the Private DNS Zone to deploy
    • auto_registration_zone_enabled: Whether to deploy the Virtual Machine auto-registration Private DNS Zone
    • auto_registration_zone_name: The name of the Virtual Machine auto-registration Private DNS Zone
    • private_dns_resolver: This is an object to specify the Private DNS Resolver
      • name: The name of the Private DNS Resolver
      • resource_group_name: The name of the resource group to deploy the Private DNS Resolver into
      • ip_address: The static IP Address of the Private DNS Resolver. This will be auto calculated if not supplied
  • side_car_virtual_network: This object maps directly to the variables of the Azure Verified Module, which can be found here: registry.terraform.io/modules/Azure/avm-res-network-virtualnetwork

Example usage:

 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
virtual_wan_virtual_hubs = {
  primary = {
    # Example hub network settings for this region
    hub = {
      name = "vwan-hub-$${starter_location_01}"
      resource_group = "$${connectivity_hub_primary_resource_group_name}"
      location       = "$${starter_location_01}"
      address_prefix = "$${primary_hub_address_space}"
    }
    # Example Azure Firewall settings for this region (omit this section if not using Azure Firewall)
    firewall = {
      name     = "fw-hub-$${starter_location_01}"
      sku_name = "AZFW_Hub"
      sku_tier = "Standard"
      zones    = "$${starter_location_01_availability_zones}"
    }
    # Example firewall policy settings for this region (omit this section if not using Azure Firewall)
    firewall_policy = {
      name = "fwp-hub-$${starter_location_01}"
    }
    # Example Virtual Network Gateway settings for this region (omit this section if not using Virtual Network Gateway)
    virtual_network_gateways = {
      # Example ExpressRoute settings for this region (omit this section if not using ExpressRoute)
      express_route = {
        name = "vgw-hub-expressroute-$${starter_location_01}"
      }
      # Example VPN Gateway settings for this region (omit this section if not using VPN Gateway)
      vpn = {
        name = "vgw-hub-vpn-$${starter_location_01}"
      }
    }
    # Example Private DNS Zone settings for this region (omit this section if not using Private DNS Zones)
    private_dns_zones = {
      resource_group_name            = "$${dns_resource_group_name}"
      is_primary                     = true
      auto_registration_zone_enabled = true
      auto_registration_zone_name    = "$${starter_location_01}.azure.local"
      subnet_address_prefix          = "$${primary_private_dns_resolver_subnet_address_prefix}"
      private_dns_resolver = {
        name = "pdr-hub-dns-$${starter_location_01}"
      }
    }
    # Example Bastion Host settings for this region (omit this section if not using Bastion Host)
    bastion = {
      subnet_address_prefix = "$${primary_bastion_subnet_address_prefix}"
      bastion_host = {
        name = "bastion-hub-$${starter_location_01}"
      }
      bastion_public_ip = {
        name  = "pip-bastion-hub-$${starter_location_01}"
        zones = "$${starter_location_01_availability_zones}"
      }
    }
    # Example Side Car Virtual Network settings for this region
    side_car_virtual_network = {
      name          = "vnet-side-car-$${starter_location_01}"
      address_space = ["$${primary_side_car_virtual_network_address_space}"]
    }
  }
}

Azure Verified Modules Reference

For reference, the following is a list of the Azure Verified Modules used by this starter module

Used and can be configured

Applies ToModule TypeModule NameDescriptionLink
AllPatternManagement Groups and PolicyUsed to create the management group structure, deploy policy definitions, assign policies, and create role assignmentshttps://github.com/Azure/terraform-azurerm-avm-ptn-alz
AllPatternManagement ResourcesUsed to deploy the management resource, including log analytics workspace and automation accounthttps://github.com/Azure/terraform-azurerm-avm-ptn-alz-management
AllUtilityRegionsUsed to lookup the availability zones in the regions selected, so they can be used in the replacementshttps://github.com/Azure/terraform-azurerm-avm-utl-regions
Both ConnectivityResourceResource GroupUsed to create the Resource Groups if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-resources-resourcegroup
Both ConnectivityResourcePrivate DNS ResolverUsed to deploy the Private DNS Resolver if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-network-dnsresolver
Both ConnectivityPatternPrivate Link Private DNS ZonesUsed to deploy the Private Link Private DNS Zones if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-ptn-network-private-link-private-dns-zones
Both ConnectivityResourcePrivate DNS ZoneUsed to deploy the Virtual Machine auto-registration DNS Zone if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-network-privatednszone
Both ConnectivityResourceDDOS Protection PlanUsed to deploy the DDOS Protection Plan if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-network-ddosprotectionplan
Both ConnectivityResourcePublic IP AddressUsed to deploy the Public IP Address for the Bastion Host if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-network-publicipaddress
Both ConnectivityResourceBastion HostUsed to deploy the Bastion Host if connectivity is enabledhttps://github.com/Azure/terraform-azurerm-avm-res-network-bastionhost
Hub and Spoke VNETPatternHub NetworkingUsed to deploy and configure the Hub and Spoke Virtual Network if that option is selectedhttps://github.com/Azure/terraform-azurerm-avm-ptn-hubnetworking
Hub and Spoke VNETPatternVirtual Network GatewaysUsed to deploy the virtual network gateways for the Hub and Spoke Virtual Network optionshttps://github.com/Azure/terraform-azurerm-avm-ptn-vnetgateway
Virtual WANPatternVirtual WANUsed to deploy and configure the Virtual WAN if that option is selectedhttps://github.com/Azure/terraform-azurerm-avm-ptn-virtualwan
Virtual WANResourceFirewall PolicyUsed to deploy the Firewall Policy if the Virtual WAN option is selectedhttps://github.com/Azure/terraform-azurerm-avm-res-network-firewallpolicy
Virtual WANResourceVirtual NetworkUsed to deploy the Sidecar Virtual Network and Subnets if the Virtual WAN option is selectedhttps://github.com/Azure/terraform-azurerm-avm-res-network-virtualnetwork