diff --git a/templates/complete_vnext/config.yaml b/templates/complete_vnext/config.yaml new file mode 100644 index 00000000..6b5c657d --- /dev/null +++ b/templates/complete_vnext/config.yaml @@ -0,0 +1,92 @@ +# 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: +# `default_postfix`: This is a string sourced from the variable `default_postfix`. This can be used to append to resource names for consistency. +# `default_location`: This is an Azure location sourced from the `default_location` variable. This can be used to set the location of resources. +# `root_management_group_id`: This is ID of the top level managemrnt group that you will build your hierarchy under. This is primarily used to set the root management group `parent`. +# `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: + automation_account_name: aa-${default_postfix} + location: ${default_location} + log_analytics_workspace_name: law-${default_postfix} + resource_group_name: rg-management-${default_postfix} + +management_groups: + root: # `key`: the unique identifier for the management group within the Terraform Module this is used in the `parent` field to build the hierarchy + id: root-${default_postfix} # `id`: the id the management group will be created with in Azure + display_name: Intermediate Root # `display_name`: the name the management group will be created with in Azure + parent: ${root_management_group_id} # `parent`: for the root management group this should be the id of the tenant root management group or your chosen root management group + base_archetype: root # `archetype`: the archetype to use for this management group + landing-zones: + id: landing-zones-${default_postfix} + display_name: Landing Zones + parent: root # Note that `parent` refers to the `key` of it's parent as opposed to the `id` which can be different + base_archetype: landing_zones + platform: + id: platform-${default_postfix} + display_name: Platform + parent: root + base_archetype: platform + identity: + id: identity-${default_postfix} + display_name: Identity + parent: platform + base_archetype: identity + subscriptions: + - ${subscription_id_identity} + connectivity: + id: connectivity-${default_postfix} + display_name: Connectivity + parent: platform + base_archetype: connectivity + subscriptions: + - ${subscription_id_connectivity} + management: + id: management-${default_postfix} + display_name: Management + parent: platform + base_archetype: management + subscriptions: + - ${subscription_id_management} + corp: + id: corp-${default_postfix} + display_name: Corp + parent: landing-zones + base_archetype: corp + online: + id: online-${default_postfix} + display_name: Online + parent: landing-zones + base_archetype: online + sandboxes: + id: sandboxes-${default_postfix} + display_name: Sandboxes + parent: root + base_archetype: sandboxes + decommissioned: + id: decommissioned-${default_postfix} + display_name: Decommissioned + parent: root + base_archetype: decommissioned + +connectivity: + hub_networking: # `hubnetworking` module, add inputs as listed on the module registry where necessary. + hub_virtual_networks: + primary: + name: vnet-hub-${default_postfix} + resource_group_name: rg-connectivity-${default_postfix} + location: ${default_location} + address_space: + - 10.0.0.0/16 + firewall: + name: fw-hub-${default_postfix} + sku_name: AZFW_VNet + sku_tier: Standard + subnet_address_prefix: 10.0.1.0/24 + virtual_network_gateway: # `vnet-gateway` module, add inputs as listed on the module registry where necessary. + name: vgw-hub-${default_postfix} + sku: VpnGw1 + type: Vpn + subnet_address_prefix: 10.0.2.0/24 diff --git a/templates/complete_vnext/data.tf b/templates/complete_vnext/data.tf new file mode 100644 index 00000000..cee07df2 --- /dev/null +++ b/templates/complete_vnext/data.tf @@ -0,0 +1 @@ +data "azurerm_client_config" "current" {} diff --git a/templates/complete_vnext/locals.tf b/templates/complete_vnext/locals.tf new file mode 100644 index 00000000..bb4468d2 --- /dev/null +++ b/templates/complete_vnext/locals.tf @@ -0,0 +1,33 @@ +locals { + root_management_group_id = var.root_management_group_id == "" ? data.azurerm_client_config.current.tenant_id : var.root_management_group_id + + base_config_replacements = { + default_location = var.default_location + default_postfix = var.default_postfix + root_management_group_id = local.root_management_group_id + subscription_id_connectivity = var.subscription_id_connectivity + subscription_id_identity = var.subscription_id_identity + subscription_id_management = var.subscription_id_management + } + + initial_config = yamldecode(templatefile("${path.module}/config.yaml", local.base_config_replacements)) + + management = local.initial_config.management + connectivity = local.initial_config.connectivity + + hub_virtual_networks = { + for k, v in local.connectivity.hub_networking.hub_virtual_networks : k => { + for k2, v2 in v : k2 => v2 if k2 != "virtual_network_gateway" + } + } + virtual_network_gateways = { + for k, v in local.connectivity.hub_networking.hub_virtual_networks : k => merge( + v.virtual_network_gateway, + { + location = v.location + virtual_network_name = v.name + virtual_network_resource_group_name = v.resource_group_name + } + ) + } +} diff --git a/templates/complete_vnext/locals_management_groups.tf b/templates/complete_vnext/locals_management_groups.tf new file mode 100644 index 00000000..02353859 --- /dev/null +++ b/templates/complete_vnext/locals_management_groups.tf @@ -0,0 +1,23 @@ +locals { + management_groups = local.initial_config.management_groups + + management_groups_layer_1 = { for k, v in local.management_groups : k => v if v.parent == local.root_management_group_id } + management_groups_layer_2 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_1), v.parent) } + management_groups_layer_3 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_2), v.parent) } + management_groups_layer_4 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_3), v.parent) } + management_groups_layer_5 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_4), v.parent) } + management_groups_layer_6 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_5), v.parent) } + management_groups_layer_7 = { for k, v in local.management_groups : k => v if contains(keys(local.management_groups_layer_6), v.parent) } +} + +output "test" { + value = { + management_groups_layer_1 = local.management_groups_layer_1 + management_groups_layer_2 = local.management_groups_layer_2 + management_groups_layer_3 = local.management_groups_layer_3 + management_groups_layer_4 = local.management_groups_layer_4 + management_groups_layer_5 = local.management_groups_layer_5 + management_groups_layer_6 = local.management_groups_layer_6 + management_groups_layer_7 = local.management_groups_layer_7 + } +} diff --git a/templates/complete_vnext/main.tf b/templates/complete_vnext/main.tf new file mode 100644 index 00000000..29cbb129 --- /dev/null +++ b/templates/complete_vnext/main.tf @@ -0,0 +1,56 @@ +module "management_resources" { + source = "Azure/alz-management/azurerm" + version = "~> 0.1.5" + providers = { + azurerm = azurerm.management + } + automation_account_name = try(local.management.automation_account_name, "") + location = try(local.management.location, "") + log_analytics_workspace_name = try(local.management.log_analytics_workspace_name, "") + resource_group_name = try(local.management.resource_group_name, "") +} + +module "hub_networking" { + source = "Azure/hubnetworking/azurerm" + version = "~> 1.1.0" + providers = { + azurerm = azurerm.connectivity + } + count = length(local.hub_virtual_networks) > 0 ? 1 : 0 + + hub_virtual_networks = length(local.hub_virtual_networks) > 0 ? local.hub_virtual_networks : null +} + +module "vnet_gateway" { + source = "Azure/vnet-gateway/azurerm" + version = "~> 0.1.2" + providers = { + azurerm = azurerm.connectivity + } + + for_each = local.virtual_network_gateways + + location = each.value.location + name = each.value.name + sku = each.value.sku + subnet_address_prefix = each.value.subnet_address_prefix + type = each.value.type + virtual_network_name = each.value.virtual_network_name + virtual_network_resource_group_name = each.value.virtual_network_resource_group_name + default_tags = try(each.value.default_tags, 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) + 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) + + depends_on = [ + module.hub_networking + ] +} diff --git a/templates/complete_vnext/management_groups.tf b/templates/complete_vnext/management_groups.tf new file mode 100644 index 00000000..9e2a046e --- /dev/null +++ b/templates/complete_vnext/management_groups.tf @@ -0,0 +1,90 @@ +module "management_groups_layer_1" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_1 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = each.value.parent + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_2" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_2 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_1[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_3" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_3 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_2[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_4" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_4 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_3[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_5" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_5 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_4[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_6" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_6 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_5[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} + +module "management_groups_layer_7" { + source = "Azure/avm-ptn-alz/azurerm" + version = "~> 0.4.1" + for_each = local.management_groups_layer_7 + id = each.value.id + display_name = try(each.value.display_name, each.value.id) + parent_id = module.management_groups_layer_6[each.value.parent].management_group_name + base_archetype = each.value.base_archetype + default_location = var.default_location + default_log_analytics_workspace_id = module.management_resources.log_analytics_workspace.id + subscription_ids = try(each.value.subscriptions, []) +} diff --git a/templates/complete_vnext/variables.tf b/templates/complete_vnext/variables.tf new file mode 100644 index 00000000..44d09aca --- /dev/null +++ b/templates/complete_vnext/variables.tf @@ -0,0 +1,31 @@ +variable "default_location" { + description = "The location for Azure resources. (e.g 'uksouth')|1|azure_location" + type = string +} + +variable "default_postfix" { + description = "The default postfix for Azure resources. (e.g 'landing-zone')|2|azure_name" + type = string + default = "landing-zone" +} + +variable "root_management_group_id" { + description = "The identifier of the Tenant Root Management Group, if left blank will use the tenant id. (e.g '00000000-0000-0000-0000-000000000000')|3|azure_name" + type = string + default = "" +} + +variable "subscription_id_connectivity" { + description = "The identifier of the Connectivity Subscription. (e.g '00000000-0000-0000-0000-000000000000')|4|azure_subscription_id" + type = string +} + +variable "subscription_id_identity" { + description = "The identifier of the Identity Subscription. (e.g '00000000-0000-0000-0000-000000000000')|5|azure_subscription_id" + type = string +} + +variable "subscription_id_management" { + description = "The identifier of the Management Subscription. (e.g 00000000-0000-0000-0000-000000000000)|6|azure_subscription_id" + type = string +} diff --git a/templates/complete_vnext/versions.tf b/templates/complete_vnext/versions.tf new file mode 100644 index 00000000..ad1242b2 --- /dev/null +++ b/templates/complete_vnext/versions.tf @@ -0,0 +1,23 @@ +terraform { + required_version = ">= 1.5" + required_providers { + azurerm = ">= 3.79.0" + } + # backend "azurerm" {} +} + +provider "azurerm" { + features {} +} + +provider "azurerm" { + alias = "management" + subscription_id = var.subscription_id_management + features {} +} + +provider "azurerm" { + alias = "connectivity" + subscription_id = var.subscription_id_connectivity + features {} +} diff --git a/templates/hubnetworking/versions.tf b/templates/hubnetworking/versions.tf index 42ac4482..a2b0ab44 100644 --- a/templates/hubnetworking/versions.tf +++ b/templates/hubnetworking/versions.tf @@ -24,3 +24,9 @@ provider "azurerm" { subscription_id = var.subscription_id_connectivity features {} } + +provider "azurerm" { + alias = "identity" + subscription_id = var.subscription_id_identity + features {} +}