diff --git a/docs/guides/peering-azure.md b/docs/guides/peering-azure.md index 2d6023ba9..47ab0711a 100644 --- a/docs/guides/peering-azure.md +++ b/docs/guides/peering-azure.md @@ -107,25 +107,26 @@ resource "azurerm_role_assignment" "assignment" { } ``` -## Peer an Azure VNet to an HVN - Gateway support +## Peer an Azure VNet to an HVN - Network Virtual Appliance (NVA) support -The following example shows how to connect Azure workloads to HCP HVNs which require [Hub-spoke network topology](https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli) utilizing an Azure VPN Gateway. +The following example shows how to connect Azure workloads to HCP HVNs which require [Hub-spoke network topology](https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli) utilizing an Azure Network Virtual Appliance. --> **Note:** Azure Hub/Spoke architecture support is in private beta. Please contact [HashiCorp support](https://support.hashicorp.com/hc/en-us) for details. +-> **Note:** Azure Hub/Spoke architecture support is in private beta. Please refer to the Azure HVN [Hub and spoke options](https://developer.hashicorp.com/hcp/docs/hcp/network/hvn-azure/hub-spoke-options) documentation for more information. Notable aspects of this configuration: -* When the `use_remote_gatways` parameter of the `hcp_azure_peering_connection` resource is set to `true`, the peering link from customer VNet to HVN is set with `AllowGatewayTransit` to `true`. +* An Azure Firewall is used as the Network Virtual Appliance (NVA). +* A "Spoke" Virtual Network is included and peered to the "Hub" Virtual Network. ```terraform terraform { required_providers { hcp = { source = "hashicorp/hcp" - version = "~> 0.78.0" + version = "~> 0.102.0" } azurerm = { source = "hashicorp/azurerm" - version = "=3.0.0" + version = "~>4.14.0" } } } @@ -149,6 +150,7 @@ locals { short_uid = format("%.10s", local.uid) subscription_id = var.subscription_id tenant_id = var.tenant_id + cidr = "172.25.16.0/20" } resource "random_uuid" "uuid" {} @@ -157,7 +159,7 @@ resource "hcp_hvn" "hvn" { hvn_id = "hvn-${local.short_uid}" cloud_provider = "azure" region = "eastus" - cidr_block = "172.25.16.0/20" + cidr_block = local.cidr } resource "hcp_azure_peering_connection" "peering" { @@ -169,8 +171,8 @@ resource "hcp_azure_peering_connection" "peering" { peer_resource_group_name = azurerm_resource_group.rg.name peer_vnet_region = "eastus" - allow_forwarded_traffic = false - use_remote_gateways = true + allow_forwarded_traffic = true + use_remote_gateways = false } // This data source is the same as the resource above, but waits for the connection @@ -186,11 +188,12 @@ data "hcp_azure_peering_connection" "peering" { resource "hcp_hvn_route" "route" { hvn_route_id = "route-${local.short_uid}" hvn_link = hcp_hvn.hvn.self_link - destination_cidr = "172.31.0.0/16" + destination_cidr = azurerm_virtual_network.spoke.address_space[0] target_link = data.hcp_azure_peering_connection.peering.self_link azure_config { - next_hop_type = "VIRTUAL_NETWORK_GATEWAY" + next_hop_type = "VIRTUAL_APPLIANCE" + next_hop_ip_address = azurerm_firewall.firewall.ip_configuration[0].private_ip_address } } @@ -209,40 +212,131 @@ resource "azurerm_virtual_network" "vnet" { ] } -resource "azurerm_subnet" "subnet" { - name = "GatewaySubnet" +resource "azurerm_subnet" "spoke" { + name = "subnet-spoke-${local.short_uid}" resource_group_name = azurerm_resource_group.rg.name - virtual_network_name = azurerm_virtual_network.vnet.name + virtual_network_name = azurerm_virtual_network.spoke.name address_prefixes = [ - "10.0.1.0/24" + "10.1.0.0/24" ] } -resource "azurerm_public_ip" "ip" { - name = "ip-${local.short_uid}" +resource "azurerm_virtual_network" "spoke" { + name = "vnet-spoke-${local.short_uid}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name - allocation_method = "Dynamic" + + address_space = [ + "10.1.0.0/16" + ] } -resource "azurerm_virtual_network_gateway" "gateway" { - name = "gateway-${local.short_uid}" +resource "azurerm_route_table" "spoke" { + name = "rtab-spoke-${local.short_uid}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + + disable_bgp_route_propagation = false +} + +resource "azurerm_subnet_route_table_association" "spoke" { + subnet_id = azurerm_subnet.spoke.id + route_table_id = azurerm_route_table.spoke.id +} + +resource "azurerm_route" "spoke" { + name = "route-spoke-${local.short_uid}" + resource_group_name = azurerm_resource_group.rg.name + route_table_name = azurerm_route_table.spoke.name + + address_prefix = local.cidr + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = azurerm_firewall.firewall.ip_configuration[0].private_ip_address +} + +resource "azurerm_subnet" "firewall" { + name = "AzureFirewallSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + + address_prefixes = [ + "10.0.255.0/24" + ] +} + +resource "azurerm_firewall" "firewall" { + name = "firewall-${local.short_uid}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name - type = "Vpn" - vpn_type = "RouteBased" - enable_bgp = false // Explicit; defaults to false - sku = "Basic" + + sku_name = "AZFW_VNet" + sku_tier = "Standard" ip_configuration { - name = "ipconf-${local.short_uid}" - public_ip_address_id = azurerm_public_ip.ip.id - private_ip_address_allocation = "Dynamic" - subnet_id = azurerm_subnet.subnet.id + name = "firewall-conf-${local.short_uid}" + subnet_id = azurerm_subnet.firewall.id + public_ip_address_id = azurerm_public_ip.firewall.id + } +} + + +resource "azurerm_public_ip" "firewall" { + name = "firewall-ip-${local.short_uid}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + allocation_method = "Static" + sku = "Standard" +} + +resource "azurerm_firewall_network_rule_collection" "firewall" { + name = "firewall-collection-${local.short_uid}" + resource_group_name = azurerm_resource_group.rg.name + azure_firewall_name = azurerm_firewall.firewall.name + priority = 100 + action = "Allow" + + rule { + name = "HNVtoSpoke" + protocols = ["Any"] + source_addresses = [hcp_hvn.hvn.cidr_block] + destination_addresses = azurerm_virtual_network.spoke.address_space + destination_ports = ["*"] + } + + rule { + name = "SpokeToHVN" + protocols = ["Any"] + source_addresses = azurerm_virtual_network.spoke.address_space + destination_addresses = [hcp_hvn.hvn.cidr_block] + destination_ports = ["*"] } } +resource "azurerm_virtual_network_peering" "firewall_spoketohub" { + name = "peering-sth-${local.short_uid}" + resource_group_name = azurerm_resource_group.rg.name + + virtual_network_name = azurerm_virtual_network.spoke.name + remote_virtual_network_id = azurerm_virtual_network.vnet.id + allow_virtual_network_access = true + allow_forwarded_traffic = true + allow_gateway_transit = false + use_remote_gateways = false +} + +resource "azurerm_virtual_network_peering" "firewall_hubtospoke" { + name = "peering-hts-${local.short_uid}" + resource_group_name = azurerm_resource_group.rg.name + + virtual_network_name = azurerm_virtual_network.vnet.name + remote_virtual_network_id = azurerm_virtual_network.spoke.id + allow_virtual_network_access = true + allow_forwarded_traffic = false + allow_gateway_transit = false + use_remote_gateways = false +} + // The principal deploying the `azuread_service_principal` resource below requires // API Permissions as described here: https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal. // The principal deploying the `azurerm_role_definition` and `azurerm_role_assigment` @@ -270,32 +364,31 @@ resource "azurerm_role_definition" "definition" { } resource "azurerm_role_assignment" "assignment" { - principal_id = azuread_service_principal.principal.id + principal_id = azuread_service_principal.principal.object_id scope = azurerm_virtual_network.vnet.id role_definition_id = azurerm_role_definition.definition.role_definition_resource_id } ``` -## Peer an Azure VNet to an HVN - Network Virtual Appliance (NVA) support +## Peer an Azure VNet to an HVN - Gateway support -The following example shows how to connect Azure workloads to HCP HVNs which require [Hub-spoke network topology](https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli) utilizing an Azure Network Virtual Appliance. +The following example shows how to connect Azure workloads to HCP HVNs which require [Hub-spoke network topology](https://learn.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli) utilizing an Azure VPN Gateway. --> **Note:** Azure Hub/Spoke architecture support is in private beta. Please contact [HashiCorp support](https://support.hashicorp.com/hc/en-us) for details. +-> **Note:** Azure Hub/Spoke architecture support is in private beta. Please refer to the Azure HVN [Hub and spoke options](https://developer.hashicorp.com/hcp/docs/hcp/network/hvn-azure/hub-spoke-options) documentation for more information. Notable aspects of this configuration: -* An Azure Firewall is used as the Network Virtual Appliance (NVA). -* A "Spoke" Virtual Network is included and peered to the "Hub" Virtual Network. +* When the `use_remote_gatways` parameter of the `hcp_azure_peering_connection` resource is set to `true`, the peering link from customer VNet to HVN is set with `AllowGatewayTransit` to `true`. ```terraform terraform { required_providers { hcp = { source = "hashicorp/hcp" - version = "~> 0.78.0" + version = "~> 0.102.0" } azurerm = { source = "hashicorp/azurerm" - version = "=3.0.0" + version = "~>4.14.0" } } } @@ -319,7 +412,6 @@ locals { short_uid = format("%.10s", local.uid) subscription_id = var.subscription_id tenant_id = var.tenant_id - cidr = "172.25.16.0/20" } resource "random_uuid" "uuid" {} @@ -328,7 +420,7 @@ resource "hcp_hvn" "hvn" { hvn_id = "hvn-${local.short_uid}" cloud_provider = "azure" region = "eastus" - cidr_block = local.cidr + cidr_block = "172.25.16.0/20" } resource "hcp_azure_peering_connection" "peering" { @@ -341,7 +433,7 @@ resource "hcp_azure_peering_connection" "peering" { peer_vnet_region = "eastus" allow_forwarded_traffic = true - use_remote_gateways = false + use_remote_gateways = true } // This data source is the same as the resource above, but waits for the connection @@ -357,12 +449,11 @@ data "hcp_azure_peering_connection" "peering" { resource "hcp_hvn_route" "route" { hvn_route_id = "route-${local.short_uid}" hvn_link = hcp_hvn.hvn.self_link - destination_cidr = azurerm_virtual_network.spoke.address_space[0] + destination_cidr = "172.31.0.0/16" target_link = data.hcp_azure_peering_connection.peering.self_link azure_config { - next_hop_type = "VIRTUAL_APPLIANCE" - next_hop_ip_address = azurerm_firewall.firewall.ip_configuration[0].private_ip_address + next_hop_type = "VIRTUAL_NETWORK_GATEWAY" } } @@ -381,131 +472,40 @@ resource "azurerm_virtual_network" "vnet" { ] } -resource "azurerm_subnet" "spoke" { - name = "subnet-spoke-${local.short_uid}" - resource_group_name = azurerm_resource_group.rg.name - virtual_network_name = azurerm_virtual_network.spoke.name - - address_prefixes = [ - "10.1.0.0/24" - ] -} - -resource "azurerm_virtual_network" "spoke" { - name = "vnet-spoke-${local.short_uid}" - location = azurerm_resource_group.rg.location - resource_group_name = azurerm_resource_group.rg.name - - address_space = [ - "10.1.0.0/16" - ] -} - -resource "azurerm_route_table" "spoke" { - name = "rtab-spoke-${local.short_uid}" - location = azurerm_resource_group.rg.location - resource_group_name = azurerm_resource_group.rg.name - - disable_bgp_route_propagation = false -} - -resource "azurerm_subnet_route_table_association" "spoke" { - subnet_id = azurerm_subnet.spoke.id - route_table_id = azurerm_route_table.spoke.id -} - -resource "azurerm_route" "spoke" { - name = "route-spoke-${local.short_uid}" - resource_group_name = azurerm_resource_group.rg.name - route_table_name = azurerm_route_table.spoke.name - - address_prefix = local.cidr - next_hop_type = "VirtualAppliance" - next_hop_in_ip_address = azurerm_firewall.firewall.ip_configuration[0].private_ip_address -} - -resource "azurerm_subnet" "firewall" { - name = "AzureFirewallSubnet" +resource "azurerm_subnet" "subnet" { + name = "GatewaySubnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = [ - "10.0.255.0/24" + "10.0.1.0/24" ] } -resource "azurerm_firewall" "firewall" { - name = "firewall-${local.short_uid}" +resource "azurerm_public_ip" "ip" { + name = "ip-${local.short_uid}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name - - sku_name = "AZFW_VNet" - sku_tier = "Standard" - - ip_configuration { - name = "firewall-conf-${local.short_uid}" - subnet_id = azurerm_subnet.firewall.id - public_ip_address_id = azurerm_public_ip.firewall.id - } + allocation_method = "Dynamic" } - -resource "azurerm_public_ip" "firewall" { - name = "firewall-ip-${local.short_uid}" +resource "azurerm_virtual_network_gateway" "gateway" { + name = "gateway-${local.short_uid}" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name - allocation_method = "Static" - sku = "Standard" -} - -resource "azurerm_firewall_network_rule_collection" "firewall" { - name = "firewall-collection-${local.short_uid}" - resource_group_name = azurerm_resource_group.rg.name - azure_firewall_name = azurerm_firewall.firewall.name - priority = 100 - action = "Allow" - - rule { - name = "HNVtoSpoke" - protocols = ["Any"] - source_addresses = [hcp_hvn.hvn.cidr_block] - destination_addresses = azurerm_virtual_network.spoke.address_space - destination_ports = ["*"] - } + type = "Vpn" + vpn_type = "RouteBased" + enable_bgp = false // Explicit; defaults to false + sku = "Basic" - rule { - name = "SpokeToHVN" - protocols = ["Any"] - source_addresses = azurerm_virtual_network.spoke.address_space - destination_addresses = [hcp_hvn.hvn.cidr_block] - destination_ports = ["*"] + ip_configuration { + name = "ipconf-${local.short_uid}" + public_ip_address_id = azurerm_public_ip.ip.id + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.subnet.id } } -resource "azurerm_virtual_network_peering" "firewall_spoketohub" { - name = "peering-sth-${local.short_uid}" - resource_group_name = azurerm_resource_group.rg.name - - virtual_network_name = azurerm_virtual_network.spoke.name - remote_virtual_network_id = azurerm_virtual_network.vnet.id - allow_virtual_network_access = true - allow_forwarded_traffic = true - allow_gateway_transit = false - use_remote_gateways = false -} - -resource "azurerm_virtual_network_peering" "firewall_hubtospoke" { - name = "peering-hts-${local.short_uid}" - resource_group_name = azurerm_resource_group.rg.name - - virtual_network_name = azurerm_virtual_network.vnet.name - remote_virtual_network_id = azurerm_virtual_network.spoke.id - allow_virtual_network_access = true - allow_forwarded_traffic = false - allow_gateway_transit = false - use_remote_gateways = false -} - // The principal deploying the `azuread_service_principal` resource below requires // API Permissions as described here: https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal. // The principal deploying the `azurerm_role_definition` and `azurerm_role_assigment` @@ -533,7 +533,7 @@ resource "azurerm_role_definition" "definition" { } resource "azurerm_role_assignment" "assignment" { - principal_id = azuread_service_principal.principal.id + principal_id = azuread_service_principal.principal.object_id scope = azurerm_virtual_network.vnet.id role_definition_id = azurerm_role_definition.definition.role_definition_resource_id }