diff --git a/.gitignore b/.gitignore index 48c0febe..793d6391 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,6 @@ override.tf.json # example: *tfplan* .terraform.lock.hcl terraform.log -*.tfvars !terraform.tfvars templates/basic/terraform.tfvars templates/test_* diff --git a/templates/complete_multi_region/README.md b/templates/complete_multi_region/README.md new file mode 100644 index 00000000..cabb486a --- /dev/null +++ b/templates/complete_multi_region/README.md @@ -0,0 +1,48 @@ +# Azure Landing Zones Accelerator Starter Module for Terraform - Complete Multi-Region + +This module is part of the Azure Landing Zones Accelerator solution. It is a complete multi-region implementation of the Azure Landing Zones Platform Landing Zone for Terraform. + +It deploys a hub and spoke virtual network or Virtual WAN architecture across multiple regions. + +The module deploys the following resources: + +- Management group hierarchy +- Azure Policy definitions and assignments +- Role definitions +- Management resources, including Log Analytics workspace and Automation account +- Hub and spoke virtual network or Virtual WAN architecture across multiple regions +- DDOS protection plan +- Private DNS zones + +## Usage + +The module is intended to be used with the [Azure Landing Zones Accelerator](https://aka.ms/alz/accelerator/docs). Head over there to get started. + +>NOTE: The module can be used independently if needed. Example tfvars files can be found in the `examples` directory for that use case. + +### Running Directly + +#### Run the local examples + +Create a `terraform.tfvars` file in the root of the module directory with the following content, replacing the placeholders with the actual values: + +```hcl +starter_locations = ["uksouth", "ukwest"] +subscription_id_connectivity = "00000000-0000-0000-0000-000000000000" +subscription_id_identity = "00000000-0000-0000-0000-000000000000" +subscription_id_management = "00000000-0000-0000-0000-000000000000" +``` + +##### Hub and Spoke Virtual Networks Multi Region + +```powershell +terraform init +terraform apply -var-file ./examples/config-hub-and-spoke-virtual-networks-multi-region.tfvars +``` + +##### Virtual WAN Multi Region + +```powershell +terraform init +terraform apply -var-file ./examples/config-virtual-wan-multi-region.tfvars +``` diff --git a/templates/complete_multi_region/config-hub-and-spoke-vnet-multi-region.yaml b/templates/complete_multi_region/config-hub-and-spoke-vnet-multi-region.yaml deleted file mode 100644 index e36e1b12..00000000 --- a/templates/complete_multi_region/config-hub-and-spoke-vnet-multi-region.yaml +++ /dev/null @@ -1,164 +0,0 @@ -# This file contains templated variables to avoid repeating the same hard-coded values. -# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: -# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. -# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. -# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. -# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. -# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. -# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. ---- -management_groups: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. - - # Base variables - root_name: alz - root_id: Azure-Landing-Zones - default_location: ${starter_location_01} - subscription_id_connectivity: ${subscription_id_connectivity} - subscription_id_identity: ${subscription_id_identity} - subscription_id_management: ${subscription_id_management} - root_parent_id: ${root_parent_management_group_id} - deploy_core_landing_zones: true - deploy_corp_landing_zones: true - deploy_online_landing_zones: true - deploy_management_resources: true - deploy_connectivity_resources: false # We are using the AVM patterns for connectivity - deploy_identity_resources: true - - # Management resource settings - configure_management_resources: - location: ${starter_location_01} - settings: - log_analytics: - enabled: true - config: - retention_in_days: 50 - enable_monitoring_for_vm: true - enable_monitoring_for_vmss: true - enabled_sentinel: true - enable_solution_for_change_tracking: true - enable_solution_for_vm_insights: true - enable_solution_for_container_insights: true - enable_sentinel: true - security_center: - config: - email_security_contact: "security_contact@replace_me" - enable_defender_for_app_services: true - enable_defender_for_arm: true - enable_defender_for_containers: true - enable_defender_for_cosmosdbs: true - enable_defender_for_cspm: true - enable_defender_for_key_vault: true - enable_defender_for_oss_databases: true - enable_defender_for_servers: true - enable_defender_for_servers_vulnerability_assessments: true - enable_defender_for_sql_servers: true - enable_defender_for_sql_server_vms: true - enable_defender_for_storage: true - advanced: - asc_export_resource_group_name: rg-asc-export-${starter_location_01} - custom_settings_by_resource_type: - azurerm_resource_group: - management: - name: rg-management-${starter_location_01} - azurerm_log_analytics_workspace: - management: - name: law-management-${starter_location_01} - azurerm_automation_account: - management: - name: aa-management-${starter_location_01} - - # Configure Private DNS Zone Resource Ids for Policy Assignments - configure_connectivity_resources: - settings: - dns: - config: - location: ${starter_location_01} - advanced: - custom_settings_by_resource_type: - azurerm_resource_group: - dns: - ${starter_location_01}: - name: rg-private-dns-${starter_location_01} - -# Connectivity settings -connectivity: - hub_and_spoke_vnet: # `avm-ptn-hubnetworking` module, add inputs as listed on the module registry where necessary. - hub_virtual_networks: - # Primary hub - primary: - name: vnet-hub-${starter_location_01} - resource_group_name: rg-connectivity-${starter_location_01} - location: ${starter_location_01} - address_space: - - 10.0.0.0/16 - firewall: - name: fw-hub-${starter_location_01} - sku_name: AZFW_VNet - sku_tier: Standard - subnet_address_prefix: 10.0.1.0/24 - zones: ${starter_location_01_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_01} - dns: - proxy_enabled: true - default_ip_configuration: - public_ip_config: - zones: ${starter_location_01_availability_zones} - name: pip-hub-fw-${starter_location_01} - ip_version: "IPv4" - virtual_network_gateway: # `avm-ptn-vnetgateway` module, add inputs as listed on the module registry where necessary. - name: vgw-hub-${starter_location_01} - subnet_address_prefix: 10.0.2.0/24 - ip_configurations: - default: - name: default - public_ip: - name: pip-hub-vgw-${starter_location_01} - zones: ${starter_location_01_availability_zones} - - # Secondary hub - secondary: - name: vnet-hub-${starter_location_02} - resource_group_name: rg-connectivity-${starter_location_02} - location: ${starter_location_02} - address_space: - - 10.1.0.0/16 - firewall: - name: fw-hub-${starter_location_02} - sku_name: AZFW_VNet - sku_tier: Standard - subnet_address_prefix: 10.1.1.0/24 - zones: ${starter_location_02_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_02} - dns: - proxy_enabled: true - default_ip_configuration: - public_ip_config: - zones: ${starter_location_02_availability_zones} - name: pip-hub-fw-${starter_location_02} - ip_version: "IPv4" - virtual_network_gateway: # `avm-ptn-vnetgateway` module, add inputs as listed on the module registry where necessary. - name: vgw-hub-${starter_location_02} - subnet_address_prefix: 10.1.2.0/24 - ip_configurations: - ipconfig1: - name: ipconfig1 - public_ip: - name: pip-hub-vgw-${starter_location_02} - zones: ${starter_location_02_availability_zones} - - private_dns: - resource_group_name: rg-private-dns-${starter_location_01} - locations: - primary: - location: ${starter_location_01} - is_primary: true # Deploys all zones - secondary: - location: ${starter_location_02} - is_primary: false # Only deploys regional zones - -# Configure root module settings -enable_telemetry: true diff --git a/templates/complete_multi_region/config-hub-and-spoke-vnet-single-region.yaml b/templates/complete_multi_region/config-hub-and-spoke-vnet-single-region.yaml deleted file mode 100644 index 7294d268..00000000 --- a/templates/complete_multi_region/config-hub-and-spoke-vnet-single-region.yaml +++ /dev/null @@ -1,129 +0,0 @@ -# This file contains templated variables to avoid repeating the same hard-coded values. -# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: -# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. -# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. -# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. -# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. -# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. -# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. ---- -management_groups: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. - - # Base variables - root_name: alz - root_id: Azure-Landing-Zones - default_location: ${starter_location_01} - subscription_id_connectivity: ${subscription_id_connectivity} - subscription_id_identity: ${subscription_id_identity} - subscription_id_management: ${subscription_id_management} - root_parent_id: ${root_parent_management_group_id} - deploy_core_landing_zones: true - deploy_corp_landing_zones: true - deploy_online_landing_zones: true - deploy_management_resources: true - deploy_connectivity_resources: false # We are using the AVM patterns for connectivity - deploy_identity_resources: true - - # Management resource settings - configure_management_resources: - location: ${starter_location_01} - settings: - log_analytics: - enabled: true - config: - retention_in_days: 50 - enable_monitoring_for_vm: true - enable_monitoring_for_vmss: true - enabled_sentinel: true - enable_solution_for_change_tracking: true - enable_solution_for_vm_insights: true - enable_solution_for_container_insights: true - enable_sentinel: true - security_center: - config: - email_security_contact: "security_contact@replace_me" - enable_defender_for_app_services: true - enable_defender_for_arm: true - enable_defender_for_containers: true - enable_defender_for_cosmosdbs: true - enable_defender_for_cspm: true - enable_defender_for_key_vault: true - enable_defender_for_oss_databases: true - enable_defender_for_servers: true - enable_defender_for_servers_vulnerability_assessments: true - enable_defender_for_sql_servers: true - enable_defender_for_sql_server_vms: true - enable_defender_for_storage: true - advanced: - asc_export_resource_group_name: rg-asc-export-${starter_location_01} - custom_settings_by_resource_type: - azurerm_resource_group: - management: - name: rg-management-${starter_location_01} - azurerm_log_analytics_workspace: - management: - name: law-management-${starter_location_01} - azurerm_automation_account: - management: - name: aa-management-${starter_location_01} - - # Configure Private DNS Zone Resource Ids for Policy Assignments - configure_connectivity_resources: - settings: - dns: - config: - location: ${starter_location_01} - advanced: - custom_settings_by_resource_type: - azurerm_resource_group: - dns: - ${starter_location_01}: - name: rg-private-dns-${starter_location_01} - -# Connectivity settings -connectivity: - hub_and_spoke_vnet: # `avm-ptn-hubnetworking` module, add inputs as listed on the module registry where necessary. - hub_virtual_networks: - # Primary hub - primary: - name: vnet-hub-${starter_location_01} - resource_group_name: rg-connectivity-${starter_location_01} - location: ${starter_location_01} - address_space: - - 10.0.0.0/16 - firewall: - name: fw-hub-${starter_location_01} - sku_name: AZFW_VNet - sku_tier: Standard - subnet_address_prefix: 10.0.1.0/24 - zones: ${starter_location_01_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_01} - dns: - proxy_enabled: true - default_ip_configuration: - public_ip_config: - zones: ${starter_location_01_availability_zones} - name: pip-hub-fw-${starter_location_01} - ip_version: "IPv4" - virtual_network_gateway: # `avm-ptn-vnetgateway` module, add inputs as listed on the module registry where necessary. - name: vgw-hub-${starter_location_01} - subnet_address_prefix: 10.0.2.0/24 - ip_configurations: - default: - name: default - public_ip: - name: pip-hub-vgw-${starter_location_01} - zones: ${starter_location_01_availability_zones} - - private_dns: - resource_group_name: rg-private-dns-${starter_location_01} - locations: - primary: - location: ${starter_location_01} - is_primary: true # Deploys all zones - -# Configure root module settings -enable_telemetry: true diff --git a/templates/complete_multi_region/config-virtual-wan-multi-region.yaml b/templates/complete_multi_region/config-virtual-wan-multi-region.yaml deleted file mode 100644 index b65f3352..00000000 --- a/templates/complete_multi_region/config-virtual-wan-multi-region.yaml +++ /dev/null @@ -1,141 +0,0 @@ -# This file contains templated variables to avoid repeating the same hard-coded values. -# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: -# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. -# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. -# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. -# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. -# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. -# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. ---- -management_groups: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. - - # Base variables - root_name: alz - root_id: Azure-Landing-Zones - default_location: ${starter_location_01} - subscription_id_connectivity: ${subscription_id_connectivity} - subscription_id_identity: ${subscription_id_identity} - subscription_id_management: ${subscription_id_management} - root_parent_id: ${root_parent_management_group_id} - deploy_core_landing_zones: true - deploy_corp_landing_zones: true - deploy_online_landing_zones: true - deploy_management_resources: true - deploy_connectivity_resources: false # We are using the AVM patterns for connectivity - deploy_identity_resources: true - - # Management resource settings - configure_management_resources: - location: ${starter_location_01} - settings: - log_analytics: - enabled: true - config: - retention_in_days: 50 - enable_monitoring_for_vm: true - enable_monitoring_for_vmss: true - enabled_sentinel: true - enable_solution_for_change_tracking: true - enable_solution_for_vm_insights: true - enable_solution_for_container_insights: true - enable_sentinel: true - security_center: - config: - email_security_contact: "security_contact@replace_me" - enable_defender_for_app_services: true - enable_defender_for_arm: true - enable_defender_for_containers: true - enable_defender_for_cosmosdbs: true - enable_defender_for_cspm: true - enable_defender_for_key_vault: true - enable_defender_for_oss_databases: true - enable_defender_for_servers: true - enable_defender_for_servers_vulnerability_assessments: true - enable_defender_for_sql_servers: true - enable_defender_for_sql_server_vms: true - enable_defender_for_storage: true - advanced: - asc_export_resource_group_name: rg-asc-export-${starter_location_01} - custom_settings_by_resource_type: - azurerm_resource_group: - management: - name: rg-management-${starter_location_01} - azurerm_log_analytics_workspace: - management: - name: law-management-${starter_location_01} - azurerm_automation_account: - management: - name: aa-management-${starter_location_01} - - # Configure Private DNS Zone Resource Ids for Policy Assignments - configure_connectivity_resources: - settings: - dns: - config: - location: ${starter_location_01} - advanced: - custom_settings_by_resource_type: - azurerm_resource_group: - dns: - ${starter_location_01}: - name: rg-private-dns-${starter_location_01} - -# Connectivity settings -connectivity: - virtual_wan: # `avm-ptn-vwan` module, add inputs as listed on the module registry where necessary. - virtual_wan_name: vwan-hub-${starter_location_01} - resource_group_name: rg-connectivity-${starter_location_01} - location: ${starter_location_01} - - virtual_hubs: - primary: - name: vnet-hub-${starter_location_01} - location: ${starter_location_01} - address_prefix: 10.0.0.0/16 - private_dns_virtual_network_name: vnet-hub-private-dns-${starter_location_01} - private_dns_virtual_network_address_space: 10.2.0.0/24 - private_dns_virtual_network_subnet_address_space: 10.2.0.0/28 - dns_resolver_name: dpr-hub-${starter_location_01} - - secondary: - name: vnet-hub-${starter_location_02} - location: ${starter_location_02} - address_prefix: 10.1.0.0/16 - private_dns_virtual_network_name: vnet-hub-private-dns-${starter_location_02} - private_dns_virtual_network_address_space: 10.3.0.0/24 - private_dns_virtual_network_subnet_address_space: 10.3.0.0/28 - dns_resolver_name: dpr-hub-${starter_location_02} - - firewalls: - primary: - virtual_hub_key: primary - name: fw-hub-${starter_location_01} - sku_name: AZFW_Hub - sku_tier: Standard - zones: ${starter_location_01_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_01} - - secondary: - virtual_hub_key: secondary - name: fw-hub-${starter_location_02} - sku_name: AZFW_Hub - sku_tier: Standard - zones: ${starter_location_02_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_02} - - private_dns: - resource_group_name: rg-private-dns-${starter_location_01} - locations: - primary: - location: ${starter_location_01} - is_primary: true # Deploys all zones - secondary: - location: ${starter_location_02} - is_primary: false # Only deploys regional zones - -# Configure root module settings -enable_telemetry: true diff --git a/templates/complete_multi_region/config-virtual-wan-single-region.yaml b/templates/complete_multi_region/config-virtual-wan-single-region.yaml deleted file mode 100644 index 9584e748..00000000 --- a/templates/complete_multi_region/config-virtual-wan-single-region.yaml +++ /dev/null @@ -1,120 +0,0 @@ -# This file contains templated variables to avoid repeating the same hard-coded values. -# Templated variables are denoted by the dollar curly braces token. The following details each templated variable that you can use: -# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. -# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. -# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. -# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. -# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. -# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. -# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. ---- -management_groups: # `caf-enterprise-scale` module, add inputs as listed on the module registry where necessary. - - # Base variables - root_name: alz - root_id: Azure-Landing-Zones - default_location: ${starter_location_01} - subscription_id_connectivity: ${subscription_id_connectivity} - subscription_id_identity: ${subscription_id_identity} - subscription_id_management: ${subscription_id_management} - root_parent_id: ${root_parent_management_group_id} - deploy_core_landing_zones: true - deploy_corp_landing_zones: true - deploy_online_landing_zones: true - deploy_management_resources: true - deploy_connectivity_resources: false # We are using the AVM patterns for connectivity - deploy_identity_resources: true - - # Management resource settings - configure_management_resources: - location: ${starter_location_01} - settings: - log_analytics: - enabled: true - config: - retention_in_days: 50 - enable_monitoring_for_vm: true - enable_monitoring_for_vmss: true - enabled_sentinel: true - enable_solution_for_change_tracking: true - enable_solution_for_vm_insights: true - enable_solution_for_container_insights: true - enable_sentinel: true - security_center: - config: - email_security_contact: "security_contact@replace_me" - enable_defender_for_app_services: true - enable_defender_for_arm: true - enable_defender_for_containers: true - enable_defender_for_cosmosdbs: true - enable_defender_for_cspm: true - enable_defender_for_key_vault: true - enable_defender_for_oss_databases: true - enable_defender_for_servers: true - enable_defender_for_servers_vulnerability_assessments: true - enable_defender_for_sql_servers: true - enable_defender_for_sql_server_vms: true - enable_defender_for_storage: true - advanced: - asc_export_resource_group_name: rg-asc-export-${starter_location_01} - custom_settings_by_resource_type: - azurerm_resource_group: - management: - name: rg-management-${starter_location_01} - azurerm_log_analytics_workspace: - management: - name: law-management-${starter_location_01} - azurerm_automation_account: - management: - name: aa-management-${starter_location_01} - - # Configure Private DNS Zone Resource Ids for Policy Assignments - configure_connectivity_resources: - settings: - dns: - config: - location: ${starter_location_01} - advanced: - custom_settings_by_resource_type: - azurerm_resource_group: - dns: - ${starter_location_01}: - name: rg-private-dns-${starter_location_01} - -# Connectivity settings -connectivity: - virtual_wan: # `avm-ptn-vwan` module, add inputs as listed on the module registry where necessary. - virtual_wan_name: vwan-hub-${starter_location_01} - resource_group_name: rg-connectivity-${starter_location_01} - location: ${starter_location_01} - - virtual_hubs: - primary: - name: vnet-hub-${starter_location_01} - location: ${starter_location_01} - address_prefix: 10.0.0.0/16 - private_dns_virtual_network_name: vnet-hub-private-dns-${starter_location_01} - private_dns_virtual_network_address_space: 10.2.0.0/24 - private_dns_virtual_network_subnet_address_space: 10.2.0.0/28 - dns_resolver_name: dpr-hub-${starter_location_01} - - firewalls: - primary: - virtual_hub_key: primary - name: fw-hub-${starter_location_01} - sku_name: AZFW_Hub - sku_tier: Standard - zones: ${starter_location_01_availability_zones} - firewall_policy: - name: fwp-hub-${starter_location_01} - - private_dns: - resource_group_name: rg-private-dns-${starter_location_01} - locations: - primary: - location: ${starter_location_01} - is_primary: true # Deploys all zones - -# Configure root module settings -enable_telemetry: true diff --git a/templates/complete_multi_region/examples/config-hub-and-spoke-vnet-multi-region.tfvars b/templates/complete_multi_region/examples/config-hub-and-spoke-vnet-multi-region.tfvars new file mode 100644 index 00000000..fea2c1cb --- /dev/null +++ b/templates/complete_multi_region/examples/config-hub-and-spoke-vnet-multi-region.tfvars @@ -0,0 +1,259 @@ +# This file contains templated variables to avoid repeating the same hard-coded values. +# Templated variables are denoted by the dollar-dollar curly braces token (e.g. $${starter_location_01}). The following details each templated variable that you can use: +# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. +# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. +# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. +# `starter_location_01_virtual_network_gateway_sku_express_route` to `starter_location_10_virtual_network_gateway_sku_express_route`: These are the default SKUs for the Express Route virtual network gateways based on the Azure locations sourced from the `starter_locations` variable. This can be used to set the SKU of the virtual network gateways. +# `starter_location_01_virtual_network_gateway_sku_vpn` to `starter_location_10_virtual_network_gateway_sku_vpn`: These are the default SKUs for the VPN virtual network gateways based on the Azure locations sourced from the `starter_locations` variable. This can be used to set the SKU of the virtual network gateways. +# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. +# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. +# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. +# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. + +management_use_avm = false +management_settings_es = { + default_location = "$${starter_location_01}" + root_parent_id = "$${root_parent_management_group_id}" + root_id = "alz" + root_name = "Azure-Landing-Zones" + subscription_id_connectivity = "$${subscription_id_connectivity}" + subscription_id_identity = "$${subscription_id_identity}" + subscription_id_management = "$${subscription_id_management}" + deploy_connectivity_resources = false + configure_connectivity_resources = { + settings = { + dns = { + config = { + location = "$${starter_location_01}" + } + } + ddos_protection_plan = { + config = { + location = "$${starter_location_01}" + } + } + } + advanced = { + custom_settings_by_resource_type = { + azurerm_resource_group = { + dns = { + ("$${starter_location_01}") = { + name = "rg-hub-dns-$${starter_location_01}" + } + } + ddos = { + ("$${starter_location_01}") = { + name = "rg-hub-ddos-$${starter_location_01}" + } + } + } + azurerm_network_ddos_protection_plan = { + ddos = { + ("$${starter_location_01}") = { + name = "ddos-hub-$${starter_location_01}" + } + } + } + } + } + } + configure_management_resources = { + location = "$${starter_location_01}" + advanced = { + asc_export_resource_group_name = "rg-management-asc-export-$${starter_location_01}" + custom_settings_by_resource_type = { + azurerm_resource_group = { + management = { + name = "rg-management-$${starter_location_01}" + } + } + } + azurerm_log_analytics_workspace = { + management = { + name = "law-management-$${starter_location_01}" + } + } + azurerm_automation_account = { + management = { + name = "aa-management-$${starter_location_01}" + } + } + } + } +} + +connectivity_type = "hub_and_spoke_vnet" + +connectivity_resource_groups = { + ddos = { + name = "rg-hub-ddos-$${starter_location_01}" + location = "$${starter_location_01}" + } + vnet_primary = { + name = "rg-hub-$${starter_location_01}" + location = "$${starter_location_01}" + } + vnet_secondary = { + name = "rg-hub-$${starter_location_02}" + location = "$${starter_location_02}" + } + dns = { + name = "rg-hub-dns-$${starter_location_01}" + location = "$${starter_location_01}" + } +} + +hub_and_spoke_vnet_settings = { + ddos_protection_plan = { + name = "ddos-hub-$${starter_location_01}" + resource_group_name = "rg-hub-ddos-$${starter_location_01}" + location = "$${starter_location_01}" + } +} + +hub_and_spoke_vnet_virtual_networks = { + primary = { + hub_virtual_network = { + name = "vnet-hub-$${starter_location_01}" + resource_group_name = "rg-hub-$${starter_location_01}" + resource_group_creation_enabled = false + location = "$${starter_location_01}" + address_space = ["10.0.0.0/16"] + subnets = { + virtual_network_gateway = { + name = "GatewaySubnet" + address_prefixes = ["10.0.1.0/24"] + assign_generated_route_table = false + } + } + firewall = { + subnet_address_prefix = "10.0.0.0/24" + 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}" + ip_version = "IPv4" + } + } + firewall_policy = { + name = "fwp-hub-$${starter_location_01}" + dns = { + proxy_enabled = true + } + } + } + } + virtual_network_gateways = { + express_route = { + location = "$${starter_location_01}" + name = "vgw-hub-expressroute-$${starter_location_01}" + type = "ExpressRoute" + 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}" + } + } + } + } + vpn = { + location = "$${starter_location_01}" + name = "vgw-hub-vpn-$${starter_location_01}" + type = "Vpn" + 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}" + } + } + } + } + } + private_dns_zones = { + resource_group_name = "rg-hub-dns-$${starter_location_01}" + is_primary = true + } + } + secondary = { + hub_virtual_network = { + name = "vnet-hub-$${starter_location_02}" + resource_group_name = "rg-hub-$${starter_location_02}" + resource_group_creation_enabled = false + location = "$${starter_location_02}" + address_space = ["10.1.0.0/16"] + subnets = { + virtual_network_gateway = { + name = "GatewaySubnet" + address_prefixes = ["10.1.1.0/24"] + assign_generated_route_table = false + } + } + firewall = { + subnet_address_prefix = "10.1.0.0/24" + name = "fw-hub-$${starter_location_02}" + sku_name = "AZFW_VNet" + sku_tier = "Standard" + zones = "$${starter_location_02_availability_zones}" + default_ip_configuration = { + public_ip_config = { + name = "pip-fw-hub-$${starter_location_02}" + zones = "$${starter_location_02_availability_zones}" + ip_version = "IPv4" + } + } + firewall_policy = { + name = "fwp-hub-$${starter_location_01}" + dns = { + proxy_enabled = true + } + } + } + } + virtual_network_gateways = { + express_route = { + location = "$${starter_location_02}" + name = "vgw-hub-expressroute-$${starter_location_02}" + type = "ExpressRoute" + sku = "$${starter_location_02_virtual_network_gateway_sku_express_route}" + ip_configurations = { + default = { + name = "ipconfig-vgw-hub-expressroute-$${starter_location_02}" + public_ip = { + name = "pip-vgw-hub-expressroute-$${starter_location_02}" + zones = "$${starter_location_02_availability_zones}" + } + } + } + } + vpn = { + location = "$${starter_location_02}" + name = "vgw-hub-vpn-$${starter_location_02}" + type = "Vpn" + sku = "$${starter_location_02_virtual_network_gateway_sku_vpn}" + ip_configurations = { + default = { + name = "ipconfig-vgw-hub-vpn-$${starter_location_02}" + public_ip = { + name = "pip-vgw-hub-vpn-$${starter_location_02}" + zones = "$${starter_location_02_availability_zones}" + } + } + } + } + } + private_dns_zones = { + resource_group_name = "rg-hub-dns-$${starter_location_01}" + is_primary = false + } + } +} diff --git a/templates/complete_multi_region/examples/config-virtual-wan-multi-region.tfvars b/templates/complete_multi_region/examples/config-virtual-wan-multi-region.tfvars new file mode 100644 index 00000000..8754997b --- /dev/null +++ b/templates/complete_multi_region/examples/config-virtual-wan-multi-region.tfvars @@ -0,0 +1,194 @@ +# This file contains templated variables to avoid repeating the same hard-coded values. +# Templated variables are denoted by the dollar-dollar curly braces token (e.g. $${starter_location_01}). The following details each templated variable that you can use: +# `starter_location_01`: This the primary an Azure location sourced from the `starter_locations` variable. This can be used to set the location of resources. +# `starter_location_02` to `starter_location_10`: These are the secondary Azure locations sourced from the `starter_locations` variable. This can be used to set the location of resources. +# `starter_location_01_availability_zones` to `starter_location_10_availability_zones`: These are the availability zones for the Azure locations sourced from the `starter_locations` variable. This can be used to set the availability zones of resources. +# `starter_location_01_virtual_network_gateway_sku_express_route` to `starter_location_10_virtual_network_gateway_sku_express_route`: These are the default SKUs for the Express Route virtual network gateways based on the Azure locations sourced from the `starter_locations` variable. This can be used to set the SKU of the virtual network gateways. +# `starter_location_01_virtual_network_gateway_sku_vpn` to `starter_location_10_virtual_network_gateway_sku_vpn`: These are the default SKUs for the VPN virtual network gateways based on the Azure locations sourced from the `starter_locations` variable. This can be used to set the SKU of the virtual network gateways. +# `root_parent_management_group_id`: This is the id of the management group that the ALZ hierarchy will be nested under. +# `subscription_id_identity`: The subscription ID of the subscription to deploy the identity resources to, sourced from the variable `subscription_id_identity`. +# `subscription_id_connectivity`: The subscription ID of the subscription to deploy the connectivity resources to, sourced from the variable `subscription_id_connectivity`. +# `subscription_id_management`: The subscription ID of the subscription to deploy the management resources to, sourced from the variable `subscription_id_management`. + +management_use_avm = false +management_settings_es = { + default_location = "$${starter_location_01}" + root_parent_id = "$${root_parent_management_group_id}" + root_id = "alz" + root_name = "Azure-Landing-Zones" + subscription_id_connectivity = "$${subscription_id_connectivity}" + subscription_id_identity = "$${subscription_id_identity}" + subscription_id_management = "$${subscription_id_management}" + deploy_connectivity_resources = false + configure_connectivity_resources = { + settings = { + dns = { + config = { + location = "$${starter_location_01}" + } + } + ddos_protection_plan = { + config = { + location = "$${starter_location_01}" + } + } + } + advanced = { + custom_settings_by_resource_type = { + azurerm_resource_group = { + dns = { + ("$${starter_location_01}") = { + name = "rg-dns-$${starter_location_01}" + } + } + ddos = { + ("$${starter_location_01}") = { + name = "rg-ddos-$${starter_location_01}" + } + } + } + azurerm_network_ddos_protection_plan = { + ddos = { + ("$${starter_location_01}") = { + name = "ddos-$${starter_location_01}" + } + } + } + } + } + } + configure_management_resources = { + location = "$${starter_location_01}" + advanced = { + asc_export_resource_group_name = "rg-management-asc-export-$${starter_location_01}" + custom_settings_by_resource_type = { + azurerm_resource_group = { + management = { + name = "rg-management-$${starter_location_01}" + } + } + } + azurerm_log_analytics_workspace = { + management = { + name = "law-management-$${starter_location_01}" + } + } + azurerm_automation_account = { + management = { + name = "aa-management-$${starter_location_01}" + } + } + } + } +} + +connectivity_type = "virtual_wan" + +connectivity_resource_groups = { + ddos = { + name = "rg-hub-ddos-$${starter_location_01}" + location = "$${starter_location_01}" + } + vwan = { + name = "rg-vwan-$${starter_location_01}" + location = "$${starter_location_01}" + } + vnet_primary = { + name = "rg-vwan-hub-$${starter_location_01}" + location = "$${starter_location_01}" + } + vnet_secondary = { + name = "rg-vwan-hub-$${starter_location_02}" + location = "$${starter_location_02}" + } + dns = { + name = "rg-hub-dns-$${starter_location_01}" + location = "$${starter_location_01}" + } +} + +virtual_wan_settings = { + name = "vwan-hub-$${starter_location_01}" + resource_group_name = "rg-vwan-$${starter_location_01}" + location = "$${starter_location_01}" + ddos_protection_plan = { + name = "ddos-hub-$${starter_location_01}" + resource_group_name = "rg-hub-ddos-$${starter_location_01}" + location = "$${starter_location_01}" + } +} + +virtual_wan_virtual_hubs = { + primary = { + hub = { + name = "vwan-hub-$${starter_location_01}" + resource_group_name = "rg-vwan-hub-$${starter_location_01}" + location = "$${starter_location_01}" + address_prefix = "10.0.0.0/16" + } + firewall = { + name = "fw-hub-$${starter_location_01}" + sku_name = "AZFW_Hub" + sku_tier = "Standard" + zones = "$${starter_location_01_availability_zones}" + firewall_policy = { + name = "fwp-hub-$${starter_location_01}" + } + } + private_dns_zones = { + resource_group_name = "rg-hub-dns-$${starter_location_01}" + is_primary = true + networking = { + virtual_network = { + name = "vnet-hub-dns-$${starter_location_01}" + resource_group_name = "rg-vwan-hub-$${starter_location_01}" + address_space = "10.10.0.0/24" + private_dns_resolver_subnet = { + name = "subnet-hub-dns-$${starter_location_01}" + address_prefix = "10.10.0.0/28" + } + } + private_dns_resolver = { + name = "pdr-hub-dns-$${starter_location_01}" + resource_group_name = "rg-vwan-hub-$${starter_location_01}" + } + } + } + } + secondary = { + hub = { + name = "vwan-hub-$${starter_location_02}" + resource_group_name = "rg-vwan-hub-$${starter_location_02}" + location = "$${starter_location_02}" + address_prefix = "10.1.0.0/16" + } + firewall = { + name = "fw-hub-$${starter_location_02}" + sku_name = "AZFW_Hub" + sku_tier = "Standard" + zones = "$${starter_location_02_availability_zones}" + firewall_policy = { + name = "fwp-hub-$${starter_location_02}" + } + } + private_dns_zones = { + resource_group_name = "rg-hub-dns-$${starter_location_01}" + is_primary = false + networking = { + virtual_network = { + name = "vnet-hub-dns-$${starter_location_02}" + resource_group_name = "rg-vwan-hub-$${starter_location_02}" + address_space = "10.11.0.0/24" + private_dns_resolver_subnet = { + name = "subnet-hub-dns-$${starter_location_02}" + address_prefix = "10.11.0.0/28" + } + } + private_dns_resolver = { + name = "pdr-hub-dns-$${starter_location_02}" + resource_group_name = "rg-vwan-hub-$${starter_location_02}" + } + } + } + } +} diff --git a/templates/complete_multi_region/locals-config.tf b/templates/complete_multi_region/locals-config.tf index 82daab9c..cd0f310b 100644 --- a/templates/complete_multi_region/locals-config.tf +++ b/templates/complete_multi_region/locals-config.tf @@ -1,42 +1,48 @@ locals { - config_file_extension = replace(lower(element(local.config_file_split, length(local.config_file_split) - 1)), local.const_yml, local.const_yaml) - config_file_name = var.configuration_file_path == "" ? "config-hub-and-spoke-vnet.yaml" : basename(var.configuration_file_path) - config_file_split = split(".", local.config_file_name) - const_yaml = "yaml" - const_yml = "yml" - - is_yaml = local.config_file_extension == local.const_yaml || local.config_file_extension == local.const_yml - config_file_content = templatefile("${path.module}/${local.config_file_name}", local.config_template_file_variables) - config = (local.is_yaml ? - yamldecode(local.config_file_content) : - jsondecode(local.config_file_content) - ) - config_template_file_variables = { - starter_location_01 = var.starter_locations[0] - starter_location_02 = try(var.starter_locations[1], null) - starter_location_03 = try(var.starter_locations[2], null) - starter_location_04 = try(var.starter_locations[3], null) - starter_location_05 = try(var.starter_locations[4], null) - starter_location_06 = try(var.starter_locations[5], null) - starter_location_07 = try(var.starter_locations[6], null) - starter_location_08 = try(var.starter_locations[7], null) - starter_location_09 = try(var.starter_locations[8], null) - starter_location_10 = try(var.starter_locations[9], null) - starter_location_01_availability_zones = jsonencode(local.regions[var.starter_locations[0]].zones) - starter_location_02_availability_zones = jsonencode(try(local.regions[var.starter_locations[1]].zones, null)) - starter_location_03_availability_zones = jsonencode(try(local.regions[var.starter_locations[2]].zones, null)) - starter_location_04_availability_zones = jsonencode(try(local.regions[var.starter_locations[3]].zones, null)) - starter_location_05_availability_zones = jsonencode(try(local.regions[var.starter_locations[4]].zones, null)) - starter_location_06_availability_zones = jsonencode(try(local.regions[var.starter_locations[5]].zones, null)) - starter_location_07_availability_zones = jsonencode(try(local.regions[var.starter_locations[6]].zones, null)) - starter_location_08_availability_zones = jsonencode(try(local.regions[var.starter_locations[7]].zones, null)) - starter_location_09_availability_zones = jsonencode(try(local.regions[var.starter_locations[8]].zones, null)) - starter_location_10_availability_zones = jsonencode(try(local.regions[var.starter_locations[9]].zones, null)) - default_postfix = var.default_postfix - root_parent_management_group_id = var.root_parent_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_parent_management_group_id - subscription_id_connectivity = var.subscription_id_connectivity - subscription_id_identity = var.subscription_id_identity - subscription_id_management = var.subscription_id_management + starter_location_01 = var.starter_locations[0] + starter_location_02 = try(var.starter_locations[1], null) + starter_location_03 = try(var.starter_locations[2], null) + starter_location_04 = try(var.starter_locations[3], null) + starter_location_05 = try(var.starter_locations[4], null) + starter_location_06 = try(var.starter_locations[5], null) + starter_location_07 = try(var.starter_locations[6], null) + starter_location_08 = try(var.starter_locations[7], null) + starter_location_09 = try(var.starter_locations[8], null) + starter_location_10 = try(var.starter_locations[9], null) + starter_location_01_availability_zones = jsonencode(local.regions[var.starter_locations[0]].zones) + starter_location_02_availability_zones = jsonencode(try(local.regions[var.starter_locations[1]].zones, null)) + starter_location_03_availability_zones = jsonencode(try(local.regions[var.starter_locations[2]].zones, null)) + starter_location_04_availability_zones = jsonencode(try(local.regions[var.starter_locations[3]].zones, null)) + starter_location_05_availability_zones = jsonencode(try(local.regions[var.starter_locations[4]].zones, null)) + starter_location_06_availability_zones = jsonencode(try(local.regions[var.starter_locations[5]].zones, null)) + starter_location_07_availability_zones = jsonencode(try(local.regions[var.starter_locations[6]].zones, null)) + starter_location_08_availability_zones = jsonencode(try(local.regions[var.starter_locations[7]].zones, null)) + starter_location_09_availability_zones = jsonencode(try(local.regions[var.starter_locations[8]].zones, null)) + starter_location_10_availability_zones = jsonencode(try(local.regions[var.starter_locations[9]].zones, null)) + starter_location_01_virtual_network_gateway_sku_express_route = local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[0]].express_route + starter_location_02_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[1]].express_route, null) + starter_location_03_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[2]].express_route, null) + starter_location_04_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[3]].express_route, null) + starter_location_05_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[4]].express_route, null) + starter_location_06_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[5]].express_route, null) + starter_location_07_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[6]].express_route, null) + starter_location_08_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[7]].express_route, null) + starter_location_09_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[8]].express_route, null) + starter_location_10_virtual_network_gateway_sku_express_route = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[9]].express_route, null) + starter_location_01_virtual_network_gateway_sku_vpn = local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[0]].vpn + starter_location_02_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[1]].vpn, null) + starter_location_03_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[2]].vpn, null) + starter_location_04_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[3]].vpn, null) + starter_location_05_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[4]].vpn, null) + starter_location_06_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[5]].vpn, null) + starter_location_07_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[6]].vpn, null) + starter_location_08_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[7]].vpn, null) + starter_location_09_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[8]].vpn, null) + starter_location_10_virtual_network_gateway_sku_vpn = try(local.hub_and_spoke_vnet_gateway_default_skus[var.starter_locations[9]].vpn, null) + root_parent_management_group_id = var.root_parent_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_parent_management_group_id + subscription_id_connectivity = var.subscription_id_connectivity + subscription_id_identity = var.subscription_id_identity + subscription_id_management = var.subscription_id_management } } diff --git a/templates/complete_multi_region/locals-hub-and-spoke-vnet.tf b/templates/complete_multi_region/locals-hub-and-spoke-vnet.tf index 066d97c3..bc6d476f 100644 --- a/templates/complete_multi_region/locals-hub-and-spoke-vnet.tf +++ b/templates/complete_multi_region/locals-hub-and-spoke-vnet.tf @@ -1,3 +1,22 @@ locals { - vnet_gateway_default_skus = { for key, value in local.module_virtual_network_gateway : key => length(local.regions[value.location].zones) == 0 ? "Standard" : "ErGw1AZ" } + hub_and_spoke_vnet_gateway_default_skus = { for key, value in local.regions : key => length(value.zones) == 0 ? { + express_route = "Standard" + vpn = "VpnGw1" + } : { + express_route = "ErGw1AZ" + vpn = "VpnGw1AZ" + } + } +} + +locals { + hub_and_spoke_vnet_settings_json = tostring(jsonencode(var.hub_and_spoke_vnet_settings)) + hub_and_spoke_vnet_settings_json_templated = templatestring(local.hub_and_spoke_vnet_settings_json, local.config_template_file_variables) + hub_and_spoke_vnet_settings_json_final = replace(replace(local.hub_and_spoke_vnet_settings_json_templated, "\"[", "["), "]\"", "]") + hub_and_spoke_vnet_settings = jsondecode(local.hub_and_spoke_vnet_settings_json_final) + + hub_and_spoke_vnet_virtual_networks_json = tostring(jsonencode(var.hub_and_spoke_vnet_virtual_networks)) + hub_and_spoke_vnet_virtual_networks_json_templated = templatestring(local.hub_and_spoke_vnet_virtual_networks_json, local.config_template_file_variables) + hub_and_spoke_vnet_virtual_networks_json_final = replace(replace(local.hub_and_spoke_vnet_virtual_networks_json_templated, "\"[", "["), "]\"", "]") + hub_and_spoke_vnet_virtual_networks = local.connectivity_hub_and_spoke_vnet_enabled ? jsondecode(local.hub_and_spoke_vnet_virtual_networks_json_final) : {} } diff --git a/templates/complete_multi_region/locals-management.tf b/templates/complete_multi_region/locals-management.tf new file mode 100644 index 00000000..9c7bf230 --- /dev/null +++ b/templates/complete_multi_region/locals-management.tf @@ -0,0 +1,13 @@ +locals { + management_settings_es_json = tostring(jsonencode(var.management_settings_es)) + management_settings_es_json_templated = templatestring(local.management_settings_es_json, local.config_template_file_variables) + management_settings_es_json_final = replace(replace(local.management_settings_es_json_templated, "\"[", "["), "]\"", "]") + management_settings_es = jsondecode(local.management_settings_es_json_final) +} + +locals { + management_settings_avm_json = tostring(jsonencode(var.management_settings_avm)) + management_settings_avm_json_templated = templatestring(local.management_settings_avm_json, local.config_template_file_variables) + management_settings_avm_json_final = replace(replace(local.management_settings_avm_json_templated, "\"[", "["), "]\"", "]") + management_settings_avm = jsondecode(local.management_settings_avm_json_final) +} diff --git a/templates/complete_multi_region/locals-private-dns.tf b/templates/complete_multi_region/locals-private-dns.tf deleted file mode 100644 index cea11f09..00000000 --- a/templates/complete_multi_region/locals-private-dns.tf +++ /dev/null @@ -1,31 +0,0 @@ -locals { - private_dns_virtual_networks_hub_and_spoke_vnet = (local.hub_networking_enabled ? - { for key, value in try(local.module_hub_and_spoke_vnet.hub_virtual_networks, {}) : key => { vnet_resource_id = module.hub_and_spoke_vnet[0].virtual_networks[key].id } } : - {} - ) - private_dns_virtual_networks_virtual_wan = (local.virtual_wan_enabled ? - { for key, value in try(local.module_virtual_wan.virtual_hubs, {}) : key => { vnet_resource_id = module.virtual_network_private_dns[key].resource_id } } : - {} - ) - private_dns_virtual_networks = merge(local.private_dns_virtual_networks_hub_and_spoke_vnet, local.private_dns_virtual_networks_virtual_wan) - private_dns_secondary_zones = { - azure_data_explorer = { - zone_name = "privatelink.{regionName}.kusto.windows.net" - } - azure_batch_account = { - zone_name = "{regionName}.privatelink.batch.azure.com" - } - azure_batch_node_mgmt = { - zone_name = "{regionName}.service.privatelink.batch.azure.com" - } - azure_aks_mgmt = { - zone_name = "privatelink.{regionName}.azmk8s.io" - } - azure_acr_data = { - zone_name = "{regionName}.data.privatelink.azurecr.io" - } - azure_backup = { - zone_name = "privatelink.{regionCode}.backup.windowsazure.com" - } - } -} diff --git a/templates/complete_multi_region/locals-resource-groups.tf b/templates/complete_multi_region/locals-resource-groups.tf new file mode 100644 index 00000000..7c20cec5 --- /dev/null +++ b/templates/complete_multi_region/locals-resource-groups.tf @@ -0,0 +1,6 @@ +locals { + connectivity_resource_groups_json = tostring(jsonencode(var.connectivity_resource_groups)) + connectivity_resource_groups_json_templated = templatestring(local.connectivity_resource_groups_json, local.config_template_file_variables) + connectivity_resource_groups_json_final = replace(replace(local.connectivity_resource_groups_json_templated, "\"[", "["), "]\"", "]") + connectivity_resource_groups = jsondecode(local.connectivity_resource_groups_json_final) +} diff --git a/templates/complete_multi_region/locals-virtual-wan.tf b/templates/complete_multi_region/locals-virtual-wan.tf index 72036c6b..83aa993d 100644 --- a/templates/complete_multi_region/locals-virtual-wan.tf +++ b/templates/complete_multi_region/locals-virtual-wan.tf @@ -1,17 +1,11 @@ locals { - virtual_wan_virtual_network_connections_input = try(local.module_virtual_wan.virtual_network_connections, {}) - virtual_wan_private_dns_virtual_network_connections = { for key, value in try(local.module_virtual_wan.virtual_hubs, {}) : "private_dns_vnet_${key}" => { - name = "private_dns_vnet_${key}" - virtual_hub_key = key - remote_virtual_network_id = module.virtual_network_private_dns[key].resource_id - } } - virtual_wan_virtual_network_connections = local.virtual_wan_enabled ? merge(local.virtual_wan_virtual_network_connections_input, local.virtual_wan_private_dns_virtual_network_connections) : {} - virtual_wan_firewalls = { for key, value in try(local.module_virtual_wan.firewalls, {}) : key => { - virtual_hub_key = value.virtual_hub_key - name = value.name - sku_name = value.sku_name - sku_tier = value.sku_tier - firewall_policy_id = module.firewall_policy[key].resource_id - tags = try(value.tags, null) - } } + virtual_wan_settings_json = tostring(jsonencode(var.virtual_wan_settings)) + virtual_wan_settings_json_templated = templatestring(local.virtual_wan_settings_json, local.config_template_file_variables) + virtual_wan_settings_json_final = replace(replace(local.virtual_wan_settings_json_templated, "\"[", "["), "]\"", "]") + virtual_wan_settings = local.connectivity_virtual_wan_enabled ? jsondecode(local.virtual_wan_settings_json_final) : null + + virtual_wan_virtual_hubs_json = tostring(jsonencode(var.virtual_wan_virtual_hubs)) + virtual_wan_virtual_hubs_json_templated = templatestring(local.virtual_wan_virtual_hubs_json, local.config_template_file_variables) + virtual_wan_virtual_hubs_json_final = replace(replace(local.virtual_wan_virtual_hubs_json_templated, "\"[", "["), "]\"", "]") + virtual_wan_virtual_hubs = local.connectivity_virtual_wan_enabled ? jsondecode(local.virtual_wan_virtual_hubs_json_final) : {} } diff --git a/templates/complete_multi_region/locals.tf b/templates/complete_multi_region/locals.tf index 4f962798..07b83c35 100644 --- a/templates/complete_multi_region/locals.tf +++ b/templates/complete_multi_region/locals.tf @@ -1,43 +1,14 @@ locals { - enable_telemetry = try(local.config.enable_telemetry, true) -} - -locals { - management_groups = try(merge(local.config.management_groups, {}), {}) -} - -locals { - hub_virtual_networks = try(merge(local.config.connectivity.hub_and_spoke_vnet.hub_virtual_networks, {}), {}) - module_hub_and_spoke_vnet = { - hub_virtual_networks = { - for key, hub_virtual_network in local.hub_virtual_networks : key => { - for argument, value in hub_virtual_network : argument => value if argument != "virtual_network_gateway" - } + const = { + connectivity = { + virtual_wan = "virtual_wan" + hub_and_spoke_vnet = "hub_and_spoke_vnet" + none = "none" } } - module_virtual_network_gateway = { - for key, hub_virtual_network in local.hub_virtual_networks : key => merge( - hub_virtual_network.virtual_network_gateway, - { - location = hub_virtual_network.location - virtual_network_id = module.hub_and_spoke_vnet[0].virtual_networks[key].id - } - ) - if can(hub_virtual_network.virtual_network_gateway) - } -} - -locals { - module_virtual_wan = try(merge(local.config.connectivity.virtual_wan, {}), {}) -} - -locals { - module_private_dns = try(merge(local.config.connectivity.private_dns, {}), {}) } locals { - management_groups_enabled = length(local.management_groups) > 0 - hub_networking_enabled = length(local.module_hub_and_spoke_vnet) > 0 - virtual_wan_enabled = length(local.module_virtual_wan) > 0 - private_dns_enabled = length(local.module_private_dns) > 0 + connectivity_virtual_wan_enabled = var.connectivity_type == local.const.connectivity.virtual_wan + connectivity_hub_and_spoke_vnet_enabled = var.connectivity_type == local.const.connectivity.hub_and_spoke_vnet } diff --git a/templates/complete_multi_region/management-groups.tf b/templates/complete_multi_region/management-groups.tf deleted file mode 100644 index b9469992..00000000 --- a/templates/complete_multi_region/management-groups.tf +++ /dev/null @@ -1,52 +0,0 @@ -module "management_groups" { - source = "Azure/caf-enterprise-scale/azurerm" - version = "6.1.0" - - count = local.management_groups_enabled ? 1 : 0 - - disable_telemetry = try(local.management_groups.disable_telemetry, !local.enable_telemetry) - default_location = try(local.management_groups.default_location, var.starter_locations[0]) - root_parent_id = try(local.management_groups.root_parent_id, data.azurerm_client_config.current.tenant_id) - archetype_config_overrides = try(local.management_groups.archetype_config_overrides, {}) - configure_connectivity_resources = try(local.management_groups.configure_connectivity_resources, {}) - configure_identity_resources = try(local.management_groups.configure_identity_resources, {}) - configure_management_resources = try(local.management_groups.configure_management_resources, {}) - create_duration_delay = try(local.management_groups.create_duration_delay, {}) - custom_landing_zones = try(local.management_groups.custom_landing_zones, {}) - custom_policy_roles = try(local.management_groups.custom_policy_roles, {}) - default_tags = try(local.management_groups.default_tags, {}) - deploy_connectivity_resources = try(local.management_groups.deploy_connectivity_resources, true) - deploy_core_landing_zones = try(local.management_groups.deploy_core_landing_zones, true) - deploy_corp_landing_zones = try(local.management_groups.deploy_corp_landing_zones, false) - deploy_demo_landing_zones = try(local.management_groups.deploy_demo_landing_zones, false) - deploy_diagnostics_for_mg = try(local.management_groups.deploy_diagnostics_for_mg, false) - deploy_identity_resources = try(local.management_groups.deploy_identity_resources, false) - deploy_management_resources = try(local.management_groups.deploy_management_resources, false) - deploy_online_landing_zones = try(local.management_groups.deploy_online_landing_zones, false) - deploy_sap_landing_zones = try(local.management_groups.deploy_sap_landing_zones, false) - destroy_duration_delay = try(local.management_groups.destroy_duration_delay, {}) - disable_base_module_tags = try(local.management_groups.disable_base_module_tags, false) - library_path = try(local.management_groups.library_path, "") - policy_non_compliance_message_default = try(local.management_groups.policy_non_compliance_message_default, "This resource {enforcementMode} be compliant with the assigned policy.") - policy_non_compliance_message_default_enabled = try(local.management_groups.policy_non_compliance_message_default_enabled, true) - policy_non_compliance_message_enabled = try(local.management_groups.policy_non_compliance_message_enabled, true) - policy_non_compliance_message_enforced_replacement = try(local.management_groups.policy_non_compliance_message_enforced_replacement, "must") - policy_non_compliance_message_enforcement_placeholder = try(local.management_groups.policy_non_compliance_message_enforcement_placeholder, "{enforcementMode}") - policy_non_compliance_message_not_enforced_replacement = try(local.management_groups.policy_non_compliance_message_not_enforced_replacement, "should") - policy_non_compliance_message_not_supported_definitions = try(local.management_groups.policy_non_compliance_message_not_supported_definitions, ["/providers/Microsoft.Authorization/policyDefinitions/1c6e92c9-99f0-4e55-9cf2-0c234dc48f99", "/providers/Microsoft.Authorization/policyDefinitions/1a5b4dca-0b6f-4cf5-907c-56316bc1bf3d", "/providers/Microsoft.Authorization/policyDefinitions/95edb821-ddaf-4404-9732-666045e056b4"]) - resource_custom_timeouts = try(local.management_groups.resource_custom_timeouts, {}) - root_id = try(local.management_groups.root_id, "alz") - root_name = try(local.management_groups.root_name, "Azure-Landing-Zones") - strict_subscription_association = try(local.management_groups.strict_subscription_association, true) - subscription_id_connectivity = try(local.management_groups.subscription_id_connectivity, var.subscription_id_connectivity) - subscription_id_identity = try(local.management_groups.subscription_id_identity, var.subscription_id_identity) - subscription_id_management = try(local.management_groups.subscription_id_management, var.subscription_id_management) - subscription_id_overrides = try(local.management_groups.subscription_id_overrides, {}) - template_file_variables = try(local.management_groups.template_file_variables, {}) - - providers = { - azurerm = azurerm - azurerm.connectivity = azurerm.connectivity - azurerm.management = azurerm.management - } -} diff --git a/templates/complete_multi_region/management.tf b/templates/complete_multi_region/management.tf new file mode 100644 index 00000000..4f41b4f1 --- /dev/null +++ b/templates/complete_multi_region/management.tf @@ -0,0 +1,29 @@ +module "management_es" { + source = "./modules/management-es" + + count = var.skip_deploy ? 0 : (var.management_use_avm ? 0 : 1) + + enable_telemetry = var.enable_telemetry + settings = local.management_settings_es + + providers = { + azurerm = azurerm + azurerm.connectivity = azurerm.connectivity + azurerm.management = azurerm.management + } +} + +module "management_avm" { + source = "./modules/management-avm" + + count = var.skip_deploy ? 0 : (var.management_use_avm ? 1 : 0) + + enable_telemetry = var.enable_telemetry + settings = local.management_settings_avm + + providers = { + azurerm = azurerm + azurerm.connectivity = azurerm.connectivity + azurerm.management = azurerm.management + } +} diff --git a/templates/complete_multi_region/modules/hub-and-spoke-vnet/locals.tf b/templates/complete_multi_region/modules/hub-and-spoke-vnet/locals.tf new file mode 100644 index 00000000..83dc56eb --- /dev/null +++ b/templates/complete_multi_region/modules/hub-and-spoke-vnet/locals.tf @@ -0,0 +1,57 @@ +locals { + hub_virtual_networks = { + for key, value in var.hub_virtual_networks : key => merge(value.hub_virtual_network, { + ddos_protection_plan_id = local.ddos_protection_plan_enabled ? module.ddos_protection_plan[0].resource.id : null + }) + } + virtual_network_gateways_express_route = { + for hub_network_key, hub_network_value in var.hub_virtual_networks : "${hub_network_key}-express-route" => { + hub_network_key = hub_network_key + virtual_network_gateway = hub_network_value.virtual_network_gateways.express_route + } if can(hub_network_value.virtual_network_gateways.express_route) + } + virtual_network_gateways_vpn = { + for hub_network_key, hub_network_value in var.hub_virtual_networks : "${hub_network_key}-vpn" => { + hub_network_key = hub_network_key + virtual_network_gateway = hub_network_value.virtual_network_gateways.vpn + } if can(hub_network_value.virtual_network_gateways.vpn) + } + virtual_network_gateways = merge(local.virtual_network_gateways_express_route, local.virtual_network_gateways_vpn) +} + +locals { + private_dns_zones = { for key, value in var.hub_virtual_networks : key => merge({ + location = value.hub_virtual_network.location + }, value.private_dns_zones) if can(value.private_dns_zones.resource_group_name) } + + private_dns_zones_virtual_network_links = { + for key, value in module.hub_and_spoke_vnet.virtual_networks : key => { + vnet_resource_id = value.id + } + } + private_dns_zones_secondary_zones = { + azure_data_explorer = { + zone_name = "privatelink.{regionName}.kusto.windows.net" + } + azure_batch_account = { + zone_name = "{regionName}.privatelink.batch.azure.com" + } + azure_batch_node_mgmt = { + zone_name = "{regionName}.service.privatelink.batch.azure.com" + } + azure_aks_mgmt = { + zone_name = "privatelink.{regionName}.azmk8s.io" + } + azure_acr_data = { + zone_name = "{regionName}.data.privatelink.azurecr.io" + } + azure_backup = { + zone_name = "privatelink.{regionCode}.backup.windowsazure.com" + } + } +} + +locals { + ddos_protection_plan = can(var.hub_and_spoke_networks_settings.ddos_protection_plan.name) ? var.hub_and_spoke_networks_settings.ddos_protection_plan : null + ddos_protection_plan_enabled = local.ddos_protection_plan != null +} diff --git a/templates/complete_multi_region/modules/hub-and-spoke-vnet/main.tf b/templates/complete_multi_region/modules/hub-and-spoke-vnet/main.tf new file mode 100644 index 00000000..bf174af7 --- /dev/null +++ b/templates/complete_multi_region/modules/hub-and-spoke-vnet/main.tf @@ -0,0 +1,69 @@ +module "hub_and_spoke_vnet" { + source = "Azure/avm-ptn-hubnetworking/azurerm" + version = "0.1.0" + + hub_virtual_networks = local.hub_virtual_networks + enable_telemetry = var.enable_telemetry +} + +module "virtual_network_gateway" { + source = "Azure/avm-ptn-vnetgateway/azurerm" + version = "0.5.0" + + for_each = local.virtual_network_gateways + + location = each.value.virtual_network_gateway.location + name = each.value.virtual_network_gateway.name + sku = each.value.virtual_network_gateway.sku + type = each.value.virtual_network_gateway.type + virtual_network_id = module.hub_and_spoke_vnet.virtual_networks[each.value.hub_network_key].id + tags = var.tags + subnet_creation_enabled = try(each.value.virtual_network_gateway.subnet_creation_enabled, false) + edge_zone = try(each.value.virtual_network_gateway.edge_zone, null) + express_route_circuits = try(each.value.virtual_network_gateway.express_route_circuits, null) + ip_configurations = try(each.value.virtual_network_gateway.ip_configurations, null) + local_network_gateways = try(each.value.virtual_network_gateway.local_network_gateways, null) + subnet_address_prefix = try(each.value.virtual_network_gateway.subnet_address_prefix, null) + vpn_active_active_enabled = try(each.value.virtual_network_gateway.vpn_active_active_enabled, null) + vpn_bgp_enabled = try(each.value.virtual_network_gateway.vpn_bgp_enabled, null) + vpn_bgp_settings = try(each.value.virtual_network_gateway.vpn_bgp_settings, null) + vpn_generation = try(each.value.virtual_network_gateway.vpn_generation, null) + vpn_point_to_site = try(each.value.virtual_network_gateway.vpn_point_to_site, null) + vpn_type = try(each.value.virtual_network_gateway.vpn_type, null) + vpn_private_ip_address_enabled = try(each.value.virtual_network_gateway.vpn_private_ip_address_enabled, null) + route_table_bgp_route_propagation_enabled = try(each.value.virtual_network_gateway.route_table_bgp_route_propagation_enabled, null) + route_table_creation_enabled = try(each.value.virtual_network_gateway.route_table_creation_enabled, null) + route_table_name = try(each.value.virtual_network_gateway.route_table_name, null) + route_table_tags = try(each.value.virtual_network_gateway.route_table_tags, null) + enable_telemetry = var.enable_telemetry + + depends_on = [ + module.hub_and_spoke_vnet + ] +} + +module "private_dns_zones" { + source = "Azure/avm-ptn-network-private-link-private-dns-zones/azurerm" + version = "0.4.0" + + for_each = local.private_dns_zones + + location = each.value.location + resource_group_name = each.value.resource_group_name + resource_group_creation_enabled = false + virtual_network_resource_ids_to_link_to = local.private_dns_zones_virtual_network_links + private_link_private_dns_zones = try(each.value.is_primary, false) ? null : local.private_dns_zones_secondary_zones + enable_telemetry = var.enable_telemetry + tags = var.tags +} + +module "ddos_protection_plan" { + source = "Azure/avm-res-network-ddosprotectionplan/azurerm" + version = "0.2.0" + + count = local.ddos_protection_plan_enabled ? 1 : 0 + + name = local.ddos_protection_plan.name + resource_group_name = local.ddos_protection_plan.resource_group_name + location = local.ddos_protection_plan.location +} diff --git a/templates/complete_multi_region/modules/hub-and-spoke-vnet/terraform.tf b/templates/complete_multi_region/modules/hub-and-spoke-vnet/terraform.tf new file mode 100644 index 00000000..d6c95626 --- /dev/null +++ b/templates/complete_multi_region/modules/hub-and-spoke-vnet/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_version = "~> 1.9" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.107" + } + azapi = { + source = "Azure/azapi" + version = "~> 1.13" + } + } +} diff --git a/templates/complete_multi_region/modules/hub-and-spoke-vnet/variables.tf b/templates/complete_multi_region/modules/hub-and-spoke-vnet/variables.tf new file mode 100644 index 00000000..0ac361f7 --- /dev/null +++ b/templates/complete_multi_region/modules/hub-and-spoke-vnet/variables.tf @@ -0,0 +1,54 @@ +variable "hub_and_spoke_networks_settings" { + type = any + default = {} + description = <. +If it is set to false, then no telemetry will be collected. +DESCRIPTION + nullable = false +} + +variable "tags" { + type = map(string) + default = null + description = "(Optional) Tags of the resource." +} diff --git a/templates/complete_multi_region/modules/management-avm/main.tf b/templates/complete_multi_region/modules/management-avm/main.tf new file mode 100644 index 00000000..3c7a73e8 --- /dev/null +++ b/templates/complete_multi_region/modules/management-avm/main.tf @@ -0,0 +1,7 @@ +# Not implemented yet +output "temp_for_linting" { + value = { + settings = var.settings + enable_telemetry = var.enable_telemetry + } +} diff --git a/templates/complete_multi_region/modules/management-avm/terraform.tf b/templates/complete_multi_region/modules/management-avm/terraform.tf new file mode 100644 index 00000000..f5314d87 --- /dev/null +++ b/templates/complete_multi_region/modules/management-avm/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_version = "~> 1.9" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.107" + configuration_aliases = [ + azurerm.connectivity, + azurerm.management, + ] + } + } +} diff --git a/templates/complete_multi_region/modules/management-avm/variables.tf b/templates/complete_multi_region/modules/management-avm/variables.tf new file mode 100644 index 00000000..06e3c150 --- /dev/null +++ b/templates/complete_multi_region/modules/management-avm/variables.tf @@ -0,0 +1,18 @@ +variable "settings" { + type = any + default = {} + description = <. +If it is set to false, then no telemetry will be collected. +DESCRIPTION + nullable = false +} diff --git a/templates/complete_multi_region/modules/management-es/main.tf b/templates/complete_multi_region/modules/management-es/main.tf new file mode 100644 index 00000000..3ea1a33a --- /dev/null +++ b/templates/complete_multi_region/modules/management-es/main.tf @@ -0,0 +1,50 @@ +module "management_groups" { + source = "Azure/caf-enterprise-scale/azurerm" + version = "6.1.0" + + disable_telemetry = !var.enable_telemetry + default_location = var.settings.default_location + root_parent_id = var.settings.root_parent_id + archetype_config_overrides = try(var.settings.archetype_config_overrides, {}) + configure_connectivity_resources = try(var.settings.configure_connectivity_resources, {}) + configure_identity_resources = try(var.settings.configure_identity_resources, {}) + configure_management_resources = try(var.settings.configure_management_resources, {}) + create_duration_delay = try(var.settings.create_duration_delay, {}) + custom_landing_zones = try(var.settings.custom_landing_zones, {}) + custom_policy_roles = try(var.settings.custom_policy_roles, {}) + default_tags = try(var.settings.default_tags, {}) + deploy_connectivity_resources = try(var.settings.deploy_connectivity_resources, false) + deploy_core_landing_zones = try(var.settings.deploy_core_landing_zones, true) + deploy_corp_landing_zones = try(var.settings.deploy_corp_landing_zones, false) + deploy_demo_landing_zones = try(var.settings.deploy_demo_landing_zones, false) + deploy_diagnostics_for_mg = try(var.settings.deploy_diagnostics_for_mg, false) + deploy_identity_resources = try(var.settings.deploy_identity_resources, false) + deploy_management_resources = try(var.settings.deploy_management_resources, false) + deploy_online_landing_zones = try(var.settings.deploy_online_landing_zones, false) + deploy_sap_landing_zones = try(var.settings.deploy_sap_landing_zones, false) + destroy_duration_delay = try(var.settings.destroy_duration_delay, {}) + disable_base_module_tags = try(var.settings.disable_base_module_tags, false) + library_path = try(var.settings.library_path, "") + policy_non_compliance_message_default = try(var.settings.policy_non_compliance_message_default, "This resource {enforcementMode} be compliant with the assigned policy.") + policy_non_compliance_message_default_enabled = try(var.settings.policy_non_compliance_message_default_enabled, true) + policy_non_compliance_message_enabled = try(var.settings.policy_non_compliance_message_enabled, true) + policy_non_compliance_message_enforced_replacement = try(var.settings.policy_non_compliance_message_enforced_replacement, "must") + policy_non_compliance_message_enforcement_placeholder = try(var.settings.policy_non_compliance_message_enforcement_placeholder, "{enforcementMode}") + policy_non_compliance_message_not_enforced_replacement = try(var.settings.policy_non_compliance_message_not_enforced_replacement, "should") + policy_non_compliance_message_not_supported_definitions = try(var.settings.policy_non_compliance_message_not_supported_definitions, ["/providers/Microsoft.Authorization/policyDefinitions/1c6e92c9-99f0-4e55-9cf2-0c234dc48f99", "/providers/Microsoft.Authorization/policyDefinitions/1a5b4dca-0b6f-4cf5-907c-56316bc1bf3d", "/providers/Microsoft.Authorization/policyDefinitions/95edb821-ddaf-4404-9732-666045e056b4"]) + resource_custom_timeouts = try(var.settings.resource_custom_timeouts, {}) + root_id = try(var.settings.root_id, "alz") + root_name = try(var.settings.root_name, "Azure-Landing-Zones") + strict_subscription_association = try(var.settings.strict_subscription_association, true) + subscription_id_connectivity = var.settings.subscription_id_connectivity + subscription_id_identity = var.settings.subscription_id_identity + subscription_id_management = var.settings.subscription_id_management + subscription_id_overrides = try(var.settings.subscription_id_overrides, {}) + template_file_variables = try(var.settings.template_file_variables, {}) + + providers = { + azurerm = azurerm + azurerm.connectivity = azurerm.connectivity + azurerm.management = azurerm.management + } +} diff --git a/templates/complete_multi_region/modules/management-es/terraform.tf b/templates/complete_multi_region/modules/management-es/terraform.tf new file mode 100644 index 00000000..f5314d87 --- /dev/null +++ b/templates/complete_multi_region/modules/management-es/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_version = "~> 1.9" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.107" + configuration_aliases = [ + azurerm.connectivity, + azurerm.management, + ] + } + } +} diff --git a/templates/complete_multi_region/modules/management-es/variables.tf b/templates/complete_multi_region/modules/management-es/variables.tf new file mode 100644 index 00000000..d97c443e --- /dev/null +++ b/templates/complete_multi_region/modules/management-es/variables.tf @@ -0,0 +1,18 @@ +variable "settings" { + type = any + default = {} + description = <. +If it is set to false, then no telemetry will be collected. +DESCRIPTION + nullable = false +} diff --git a/templates/complete_multi_region/modules/virtual-wan/locals.tf b/templates/complete_multi_region/modules/virtual-wan/locals.tf new file mode 100644 index 00000000..cea6ab29 --- /dev/null +++ b/templates/complete_multi_region/modules/virtual-wan/locals.tf @@ -0,0 +1,85 @@ +locals { + virtual_hubs = { for virtual_hub_key, virtual_hub_value in var.virtual_hubs : virtual_hub_key => virtual_hub_value.hub } +} + +locals { + virtual_network_connections_input = { for virtual_network_connection in flatten([for virtual_hub_key, virtual_hub_value in var.virtual_hubs : + [for virtual_network_connection_key, virtual_network_connection_value in try(virtual_hub_value.virtual_network_connections, {}) : { + unique_key = "${virtual_hub_key}-${virtual_network_connection_key}" + name = virtual_network_connection_value.settings.name + virtual_hub_key = virtual_hub_key + remote_virtual_network_id = virtual_network_connection_value.remote_virtual_network_id + settings = virtual_network_connection_value.settings + }] + ]) : virtual_network_connection.unique_key => { + name = virtual_network_connection.name + virtual_hub_key = virtual_network_connection.virtual_hub_key + remote_virtual_network_id = virtual_network_connection.remote_virtual_network_id + settings = virtual_network_connection.settings + } } + + virtual_network_connections_private_dns = { for key, value in local.private_dns_zones : "private_dns_vnet_${key}" => { + name = "private_dns_vnet_${key}" + virtual_hub_key = key + remote_virtual_network_id = module.virtual_network_private_dns[key].resource_id + } } + + virtual_network_connections = merge(local.virtual_network_connections_input, local.virtual_network_connections_private_dns) +} + +locals { + firewall_policies = { for virtual_hub_key, virtual_hub_value in var.virtual_hubs : virtual_hub_key => merge({ + location = try(virtual_hub_value.firewall.firewall_policy.location, virtual_hub_value.hub.location) + resource_group_name = try(virtual_hub_value.firewall.firewall_policy.resource_group_name, virtual_hub_value.hub.resource_group_name) + dns = { + servers = [module.dns_resolver[virtual_hub_key].inbound_endpoint_ips["dns"]] + proxy_enabled = true + } + }, virtual_hub_value.firewall.firewall_policy) if can(virtual_hub_value.firewall_policy) } + + firewalls = { for virtual_hub_key, virtual_hub_value in var.virtual_hubs : virtual_hub_key => merge( + { + virtual_hub_key = virtual_hub_key + location = try(virtual_hub_value.firewall.location, virtual_hub_value.hub.location) + firewall_policy_id = module.firewall_policy[virtual_hub_key].resource_id + }, virtual_hub_value.firewall) + if can(virtual_hub_value.firewall) + } +} + +locals { + private_dns_zones = { for key, value in var.virtual_hubs : key => merge({ + location = value.hub.location + }, value.private_dns_zones) if can(value.private_dns_zones.resource_group_name) } + + private_dns_zones_virtual_network_links = { + for key, value in module.virtual_network_private_dns : key => { + vnet_resource_id = value.resource_id + } + } + private_dns_zones_secondary_zones = { + azure_data_explorer = { + zone_name = "privatelink.{regionName}.kusto.windows.net" + } + azure_batch_account = { + zone_name = "{regionName}.privatelink.batch.azure.com" + } + azure_batch_node_mgmt = { + zone_name = "{regionName}.service.privatelink.batch.azure.com" + } + azure_aks_mgmt = { + zone_name = "privatelink.{regionName}.azmk8s.io" + } + azure_acr_data = { + zone_name = "{regionName}.data.privatelink.azurecr.io" + } + azure_backup = { + zone_name = "privatelink.{regionCode}.backup.windowsazure.com" + } + } +} + +locals { + ddos_protection_plan = can(var.virtual_wan_settings.ddos_protection_plan.name) ? var.virtual_wan_settings.ddos_protection_plan : null + ddos_protection_plan_enabled = local.ddos_protection_plan != null +} diff --git a/templates/complete_multi_region/modules/virtual-wan/main.tf b/templates/complete_multi_region/modules/virtual-wan/main.tf new file mode 100644 index 00000000..2af39487 --- /dev/null +++ b/templates/complete_multi_region/modules/virtual-wan/main.tf @@ -0,0 +1,123 @@ +module "firewall_policy" { + source = "Azure/avm-res-network-firewallpolicy/azurerm" + version = "0.2.3" + + for_each = local.firewall_policies + + name = each.value.name + location = each.value.location + resource_group_name = each.value.resource_group_name + firewall_policy_sku = try(each.value.sku, "Standard") + firewall_policy_auto_learn_private_ranges_enabled = try(each.value.auto_learn_private_ranges_enabled, null) + firewall_policy_base_policy_id = try(each.value.base_policy_id, null) + firewall_policy_dns = each.value.dns + firewall_policy_threat_intelligence_mode = try(each.value.threat_intelligence_mode, "Alert") + firewall_policy_private_ip_ranges = try(each.value.private_ip_ranges, null) + firewall_policy_threat_intelligence_allowlist = try(each.value.threat_intelligence_allowlist, null) + tags = try(each.value.tags, null) + enable_telemetry = var.enable_telemetry +} + +module "virtual_wan" { + source = "Azure/avm-ptn-virtualwan/azurerm" + version = "0.5.0" + + allow_branch_to_branch_traffic = try(var.virtual_wan_settings.allow_branch_to_branch_traffic, null) + disable_vpn_encryption = try(var.virtual_wan_settings.disable_vpn_encryption, false) + er_circuit_connections = try(var.virtual_wan_settings.er_circuit_connections, {}) + expressroute_gateways = try(var.virtual_wan_settings.expressroute_gateways, {}) + firewalls = local.firewalls + office365_local_breakout_category = try(var.virtual_wan_settings.office365_local_breakout_category, null) + location = var.virtual_wan_settings.location + p2s_gateway_vpn_server_configurations = try(var.virtual_wan_settings.p2s_gateway_vpn_server_configurations, {}) + p2s_gateways = try(var.virtual_wan_settings.p2s_gateways, {}) + resource_group_name = var.virtual_wan_settings.resource_group_name + create_resource_group = false + virtual_hubs = local.virtual_hubs + virtual_network_connections = local.virtual_network_connections + virtual_wan_name = var.virtual_wan_settings.name + type = try(var.virtual_wan_settings.type, null) + routing_intents = try(var.virtual_wan_settings.routing_intents, null) + resource_group_tags = try(var.virtual_wan_settings.resource_group_tags, null) + virtual_wan_tags = try(var.virtual_wan_settings.virtual_wan_tags, null) + vpn_gateways = try(var.virtual_wan_settings.vpn_gateways, {}) + vpn_site_connections = try(var.virtual_wan_settings.vpn_site_connections, {}) + vpn_sites = try(var.virtual_wan_settings.vpn_sites, null) + tags = try(var.virtual_wan_settings.tags, null) + enable_telemetry = var.enable_telemetry +} + +module "virtual_network_private_dns" { + source = "Azure/avm-res-network-virtualnetwork/azurerm" + version = "0.4.0" + + for_each = local.private_dns_zones + + address_space = [each.value.networking.virtual_network.address_space] + location = each.value.location + name = each.value.networking.virtual_network.name + resource_group_name = each.value.networking.virtual_network.resource_group_name + enable_telemetry = var.enable_telemetry + ddos_protection_plan = local.ddos_protection_plan_enabled ? { + id = module.ddos_protection_plan[0].resource.id + enable = true + } : null + subnets = { + dns = { + address_prefix = each.value.networking.virtual_network.private_dns_resolver_subnet.address_prefix + name = each.value.networking.virtual_network.private_dns_resolver_subnet.name + delegation = [{ + name = "Microsoft.Network.dnsResolvers" + service_delegation = { + name = "Microsoft.Network/dnsResolvers" + #actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + }] + } + } +} + +module "dns_resolver" { + source = "Azure/avm-res-network-dnsresolver/azurerm" + version = "0.2.1" + + for_each = local.private_dns_zones + + location = each.value.location + name = each.value.networking.private_dns_resolver.name + resource_group_name = each.value.networking.private_dns_resolver.resource_group_name + virtual_network_resource_id = module.virtual_network_private_dns[each.key].resource_id + enable_telemetry = var.enable_telemetry + inbound_endpoints = { + dns = { + name = "dns" + subnet_name = module.virtual_network_private_dns[each.key].subnets.dns.name + } + } +} + +module "private_dns_zones" { + source = "Azure/avm-ptn-network-private-link-private-dns-zones/azurerm" + version = "0.4.0" + + for_each = local.private_dns_zones + + location = each.value.location + resource_group_name = each.value.resource_group_name + resource_group_creation_enabled = false + virtual_network_resource_ids_to_link_to = local.private_dns_zones_virtual_network_links + private_link_private_dns_zones = try(each.value.is_primary, false) ? null : local.private_dns_zones_secondary_zones + enable_telemetry = var.enable_telemetry + tags = var.tags +} + +module "ddos_protection_plan" { + source = "Azure/avm-res-network-ddosprotectionplan/azurerm" + version = "0.2.0" + + count = local.ddos_protection_plan_enabled ? 1 : 0 + + name = local.ddos_protection_plan.name + resource_group_name = local.ddos_protection_plan.resource_group_name + location = local.ddos_protection_plan.location +} diff --git a/templates/complete_multi_region/modules/virtual-wan/terraform.tf b/templates/complete_multi_region/modules/virtual-wan/terraform.tf new file mode 100644 index 00000000..d6c95626 --- /dev/null +++ b/templates/complete_multi_region/modules/virtual-wan/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_version = "~> 1.9" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.107" + } + azapi = { + source = "Azure/azapi" + version = "~> 1.13" + } + } +} diff --git a/templates/complete_multi_region/modules/virtual-wan/variables.tf b/templates/complete_multi_region/modules/virtual-wan/variables.tf new file mode 100644 index 00000000..e7f861f7 --- /dev/null +++ b/templates/complete_multi_region/modules/virtual-wan/variables.tf @@ -0,0 +1,84 @@ +variable "virtual_wan_settings" { + type = any + default = {} + description = <. +If it is set to false, then no telemetry will be collected. +DESCRIPTION + nullable = false +} + +variable "tags" { + type = map(string) + default = null + description = "(Optional) Tags of the resource." +} diff --git a/templates/complete_multi_region/networking-hub-and-spoke-vnet.tf b/templates/complete_multi_region/networking-hub-and-spoke-vnet.tf index 932a6b63..dee3d4ab 100644 --- a/templates/complete_multi_region/networking-hub-and-spoke-vnet.tf +++ b/templates/complete_multi_region/networking-hub-and-spoke-vnet.tf @@ -1,58 +1,19 @@ module "hub_and_spoke_vnet" { - source = "Azure/avm-ptn-hubnetworking/azurerm" - version = "0.1.0" + source = "./modules/hub-and-spoke-vnet" - count = length(local.hub_virtual_networks) > 0 ? 1 : 0 + count = !var.skip_deploy && local.connectivity_hub_and_spoke_vnet_enabled ? 1 : 0 - hub_virtual_networks = local.module_hub_and_spoke_vnet.hub_virtual_networks - enable_telemetry = try(local.module_hub_and_spoke_vnet.enable_telemetry, local.enable_telemetry) + hub_and_spoke_networks_settings = local.hub_and_spoke_vnet_settings + hub_virtual_networks = local.hub_and_spoke_vnet_virtual_networks + enable_telemetry = var.enable_telemetry providers = { azurerm = azurerm.connectivity } depends_on = [ - module.management_groups - ] -} - -module "virtual_network_gateway" { - source = "Azure/avm-ptn-vnetgateway/azurerm" - version = "0.3.1" - - for_each = local.module_virtual_network_gateway - - location = each.value.location - name = each.value.name - sku = try(each.value.sku, null) == null ? local.vnet_gateway_default_skus[each.key] : each.value.sku - type = try(each.value.type, null) - virtual_network_id = each.value.virtual_network_id - default_tags = try(each.value.default_tags, null) - subnet_creation_enabled = try(each.value.subnet_creation_enabled, null) - edge_zone = try(each.value.edge_zone, null) - express_route_circuits = try(each.value.express_route_circuits, null) - ip_configurations = try(each.value.ip_configurations, null) - local_network_gateways = try(each.value.local_network_gateways, null) - subnet_address_prefix = try(each.value.subnet_address_prefix, null) - tags = try(each.value.tags, null) - vpn_active_active_enabled = try(each.value.vpn_active_active_enabled, null) - vpn_bgp_enabled = try(each.value.vpn_bgp_enabled, null) - vpn_bgp_settings = try(each.value.vpn_bgp_settings, null) - vpn_generation = try(each.value.vpn_generation, null) - vpn_point_to_site = try(each.value.vpn_point_to_site, null) - vpn_type = try(each.value.vpn_type, null) - vpn_private_ip_address_enabled = try(each.value.vpn_private_ip_address_enabled, null) - route_table_bgp_route_propagation_enabled = try(each.value.route_table_bgp_route_propagation_enabled, null) - route_table_creation_enabled = try(each.value.route_table_creation_enabled, null) - route_table_name = try(each.value.route_table_name, null) - route_table_tags = try(each.value.route_table_tags, null) - enable_telemetry = try(each.value.enable_telemetry, local.enable_telemetry) - - providers = { - azurerm = azurerm.connectivity - } - - depends_on = [ - module.hub_and_spoke_vnet + module.management_es, + module.management_avm, + module.resource_groups ] } diff --git a/templates/complete_multi_region/networking-private-dns.tf b/templates/complete_multi_region/networking-private-dns.tf deleted file mode 100644 index dc5bb509..00000000 --- a/templates/complete_multi_region/networking-private-dns.tf +++ /dev/null @@ -1,34 +0,0 @@ -module "private_dns_zones_resource_group" { - source = "Azure/avm-res-resources-resourcegroup/azurerm" - version = "0.1.0" - - count = local.private_dns_enabled ? 1 : 0 - - name = try(local.module_private_dns.resource_group_name, "rg-private-dns-${var.starter_locations[0]}") - location = try(local.module_private_dns.location, [for location in local.module_private_dns.locations : location if location.is_primary][0].location) - enable_telemetry = try(local.module_private_dns.enable_telemetry, local.enable_telemetry) - - providers = { - azurerm = azurerm.connectivity - } -} - -module "private_dns_zones" { - source = "Azure/avm-ptn-network-private-link-private-dns-zones/azurerm" - version = "0.4.0" - - for_each = local.private_dns_enabled ? try(local.module_private_dns.locations, {}) : {} - - location = each.value.location - resource_group_name = module.private_dns_zones_resource_group[0].name - resource_group_creation_enabled = false - virtual_network_resource_ids_to_link_to = local.private_dns_virtual_networks - private_link_private_dns_zones = each.value.is_primary ? null : local.private_dns_secondary_zones - enable_telemetry = try(local.module_private_dns.enable_telemetry, local.enable_telemetry) - - depends_on = [module.private_dns_zones_resource_group] - - providers = { - azurerm = azurerm.connectivity - } -} diff --git a/templates/complete_multi_region/networking-virtual-wan.tf b/templates/complete_multi_region/networking-virtual-wan.tf index 50baa653..cb6392ac 100644 --- a/templates/complete_multi_region/networking-virtual-wan.tf +++ b/templates/complete_multi_region/networking-virtual-wan.tf @@ -1,142 +1,19 @@ -module "virtual_wan_resource_group" { - source = "Azure/avm-res-resources-resourcegroup/azurerm" - version = "0.1.0" - - count = local.virtual_wan_enabled ? 1 : 0 - - name = try(local.module_virtual_wan.resource_group_name, "rg-connectivity-${var.starter_locations[0]}") - location = try(local.module_virtual_wan.location, var.starter_locations[0]) - enable_telemetry = try(local.module_virtual_wan.enable_telemetry, local.enable_telemetry) - - providers = { - azurerm = azurerm.connectivity - } -} - -module "firewall_policy" { - source = "Azure/avm-res-network-firewallpolicy/azurerm" - version = "0.2.3" - - for_each = local.virtual_wan_enabled ? try(local.module_virtual_wan.firewalls, {}) : {} - - name = each.value.firewall_policy.name - location = try(each.value.firewall_policy.location, try(local.module_virtual_wan.location, var.starter_locations[0])) - resource_group_name = try(local.module_virtual_wan.resource_group_name, module.virtual_wan_resource_group[0].name) - firewall_policy_sku = try(each.value.firewall_policy.sku, "Standard") - firewall_policy_auto_learn_private_ranges_enabled = try(each.value.firewall_policy.auto_learn_private_ranges_enabled, null) - firewall_policy_base_policy_id = try(each.value.firewall_policy.base_policy_id, null) - firewall_policy_dns = try(each.value.firewall_policy.dns, { - servers = [module.dns_resolver[each.value.virtual_hub_key].inbound_endpoint_ips["dns"]] - proxy_enabled = true - }) - firewall_policy_threat_intelligence_mode = try(each.value.firewall_policy.threat_intelligence_mode, "Alert") - firewall_policy_private_ip_ranges = try(each.value.firewall_policy.private_ip_ranges, null) - firewall_policy_threat_intelligence_allowlist = try(each.value.firewall_policy.threat_intelligence_allowlist, null) - tags = try(each.value.firewall_policy.tags, null) - enable_telemetry = try(local.module_virtual_wan.enable_telemetry, local.enable_telemetry) - - depends_on = [ - module.virtual_wan_resource_group - ] - - providers = { - azurerm = azurerm.connectivity - } -} - module "virtual_wan" { - source = "Azure/avm-ptn-virtualwan/azurerm" - version = "0.5.0" + source = "./modules/virtual-wan" - count = local.virtual_wan_enabled ? 1 : 0 + count = !var.skip_deploy && local.connectivity_virtual_wan_enabled ? 1 : 0 - allow_branch_to_branch_traffic = try(local.module_virtual_wan.allow_branch_to_branch_traffic, null) - create_resource_group = try(local.module_virtual_wan.create_resource_group, false) - disable_vpn_encryption = try(local.module_virtual_wan.disable_vpn_encryption, false) - er_circuit_connections = try(local.module_virtual_wan.er_circuit_connections, {}) - expressroute_gateways = try(local.module_virtual_wan.expressroute_gateways, {}) - firewalls = local.virtual_wan_firewalls - office365_local_breakout_category = try(local.module_virtual_wan.office365_local_breakout_category, null) - location = try(local.module_virtual_wan.location, null) - p2s_gateway_vpn_server_configurations = try(local.module_virtual_wan.p2s_gateway_vpn_server_configurations, {}) - p2s_gateways = try(local.module_virtual_wan.p2s_gateways, {}) - resource_group_name = try(local.module_virtual_wan.resource_group_name, module.virtual_wan_resource_group[0].name) - virtual_hubs = try(local.module_virtual_wan.virtual_hubs, null) - virtual_network_connections = local.virtual_wan_virtual_network_connections - virtual_wan_name = try(local.module_virtual_wan.virtual_wan_name, null) - type = try(local.module_virtual_wan.type, null) - routing_intents = try(local.module_virtual_wan.routing_intents, null) - resource_group_tags = try(local.module_virtual_wan.resource_group_tags, null) - virtual_wan_tags = try(local.module_virtual_wan.virtual_wan_tags, null) - vpn_gateways = try(local.module_virtual_wan.vpn_gateways, {}) - vpn_site_connections = try(local.module_virtual_wan.vpn_site_connections, {}) - vpn_sites = try(local.module_virtual_wan.vpn_sites, null) - tags = try(local.module_virtual_wan.tags, null) - enable_telemetry = try(local.module_virtual_wan.enable_telemetry, local.enable_telemetry) + virtual_wan_settings = local.virtual_wan_settings + virtual_hubs = local.virtual_wan_virtual_hubs + enable_telemetry = var.enable_telemetry providers = { azurerm = azurerm.connectivity } depends_on = [ - module.management_groups, - module.virtual_wan_resource_group + module.management_es, + module.management_avm, + module.resource_groups ] } - -module "virtual_network_private_dns" { - source = "Azure/avm-res-network-virtualnetwork/azurerm" - version = "0.4.0" - - for_each = local.virtual_wan_enabled ? try(local.module_virtual_wan.virtual_hubs, {}) : {} - - address_space = [try(each.value.private_dns_virtual_network_address_space, null)] - location = try(each.value.location, var.starter_locations[0]) - name = try(each.value.private_dns_virtual_network_name, "vnet-private-dns-${each.value.location}") - resource_group_name = try(local.module_virtual_wan.resource_group_name, module.virtual_wan_resource_group[0].name) - enable_telemetry = try(local.module_virtual_wan.enable_telemetry, local.enable_telemetry) - subnets = { - dns = { - address_prefix = try(each.value.private_dns_virtual_network_subnet_address_space, null) - name = try(each.value.private_dns_virtual_network_subnet_name, "subnet-dns") - delegation = [{ - name = "Microsoft.Network.dnsResolvers" - service_delegation = { - name = "Microsoft.Network/dnsResolvers" - #actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] - } - }] - } - } - - depends_on = [module.virtual_wan_resource_group] - - providers = { - azurerm = azurerm.connectivity - } -} - -module "dns_resolver" { - source = "Azure/avm-res-network-dnsresolver/azurerm" - version = "0.2.1" - - for_each = local.virtual_wan_enabled ? try(local.module_virtual_wan.virtual_hubs, {}) : {} - - location = try(each.value.location, var.starter_locations[0]) - name = try(each.value.dns_resolver_name, "dpr-hub-${each.value.location}") - resource_group_name = try(local.module_virtual_wan.resource_group_name, module.virtual_wan_resource_group[0].name) - virtual_network_resource_id = module.virtual_network_private_dns[each.key].resource_id - enable_telemetry = try(local.module_virtual_wan.enable_telemetry, local.enable_telemetry) - inbound_endpoints = { - dns = { - name = "dns" - subnet_name = module.virtual_network_private_dns[each.key].subnets.dns.name - } - } - - depends_on = [module.virtual_wan_resource_group] - - providers = { - azurerm = azurerm.connectivity - } -} diff --git a/templates/complete_multi_region/outputs.tf b/templates/complete_multi_region/outputs.tf deleted file mode 100644 index 2d69b0d6..00000000 --- a/templates/complete_multi_region/outputs.tf +++ /dev/null @@ -1,12 +0,0 @@ -# output "transformed_config_file" { -# value = local.config_file_content -# } - -output "firewall_ip_addresses" { - value = (local.hub_networking_enabled ? - { for key, value in try(module.hub_and_spoke_vnet[0].firewalls, {}) : key => value.private_ip_address } : - (local.virtual_wan_enabled ? - { for key, value in try(module.virtual_wan[0].fw, {}) : key => value.name } : {} - ) - ) # TODO: Output vWAN firewall IP addresses -} diff --git a/templates/complete_multi_region/resource-groups.tf b/templates/complete_multi_region/resource-groups.tf new file mode 100644 index 00000000..e7698e25 --- /dev/null +++ b/templates/complete_multi_region/resource-groups.tf @@ -0,0 +1,14 @@ +module "resource_groups" { + source = "Azure/avm-res-resources-resourcegroup/azurerm" + version = "0.1.0" + + for_each = var.skip_deploy ? {} : local.connectivity_resource_groups + + name = each.value.name + location = each.value.location + enable_telemetry = var.enable_telemetry + + providers = { + azurerm = azurerm.connectivity + } +} diff --git a/templates/complete_multi_region/terraform.tf b/templates/complete_multi_region/terraform.tf index 788d0588..79898cab 100644 --- a/templates/complete_multi_region/terraform.tf +++ b/templates/complete_multi_region/terraform.tf @@ -1,5 +1,5 @@ terraform { - required_version = "~> 1.8" + required_version = "~> 1.9" required_providers { azurerm = { source = "hashicorp/azurerm" @@ -9,6 +9,10 @@ terraform { source = "Azure/azapi" version = "~> 1.13" } + local = { + source = "hashicorp/local" + version = "~> 2.5" + } } # backend "azurerm" {} } diff --git a/templates/complete_multi_region/variables-connectivity.tf b/templates/complete_multi_region/variables-connectivity.tf new file mode 100644 index 00000000..e3c4afdd --- /dev/null +++ b/templates/complete_multi_region/variables-connectivity.tf @@ -0,0 +1,25 @@ +variable "connectivity_type" { + type = string + description = "The type of network connectivity technology to use for the private DNS zones" + default = "hub_and_spoke_vnet" + validation { + condition = contains(values(local.const.connectivity), var.connectivity_type) + error_message = "The connectivity type must be either 'hub_and_spoke_vnet', 'virtual_wan' or 'none'" + } +} + +variable "connectivity_resource_groups" { + type = map(object({ + name = string + location = string + })) + description = <