############################################################################### # Networking Module — Main # Deploys: Resource Groups, VNets, Subnets, NSGs, NAT Gateway, Peerings ############################################################################### locals { prefix = "${var.project}-${var.environment}" } # ============================================================================= # Resource Groups (D1 Task 2) # ============================================================================= resource "azurerm_resource_group" "network" { name = "rg-${local.prefix}-network" location = var.location tags = var.tags } resource "azurerm_resource_group" "databricks" { name = "rg-${local.prefix}-databricks" location = var.location tags = var.tags } resource "azurerm_resource_group" "storage" { name = "rg-${local.prefix}-storage" location = var.location tags = var.tags } resource "azurerm_resource_group" "governance" { name = "rg-${local.prefix}-governance" location = var.location tags = var.tags } resource "azurerm_resource_group" "keyvault" { name = "rg-${local.prefix}-keyvault" location = var.location tags = var.tags } resource "azurerm_resource_group" "monitoring" { name = "rg-${local.prefix}-monitoring" location = var.location tags = var.tags } # ============================================================================= # Main MDP VNet (D1 Task 3) # ============================================================================= resource "azurerm_virtual_network" "main" { name = "vnet-${local.prefix}" location = var.location resource_group_name = azurerm_resource_group.network.name address_space = [var.vnet_cidr] tags = var.tags } # --- Databricks Host Subnet --- resource "azurerm_subnet" "dbx_host" { name = "snet-${local.prefix}-dbx-host" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = [var.dbx_host_subnet_cidr] delegation { name = "databricks-host" service_delegation { name = "Microsoft.Databricks/workspaces" actions = [ "Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action", ] } } } # --- Databricks Container Subnet --- resource "azurerm_subnet" "dbx_container" { name = "snet-${local.prefix}-dbx-container" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = [var.dbx_container_subnet_cidr] delegation { name = "databricks-container" service_delegation { name = "Microsoft.Databricks/workspaces" actions = [ "Microsoft.Network/virtualNetworks/subnets/join/action", "Microsoft.Network/virtualNetworks/subnets/prepareNetworkPolicies/action", "Microsoft.Network/virtualNetworks/subnets/unprepareNetworkPolicies/action", ] } } } # --- Private Endpoints Subnet --- resource "azurerm_subnet" "private_endpoints" { name = "snet-${local.prefix}-pe" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = [var.private_endpoints_subnet_cidr] private_endpoint_network_policies = "Enabled" } # ============================================================================= # Transit VNet (Front-End Private Link) # ============================================================================= resource "azurerm_virtual_network" "transit" { name = "vnet-${local.prefix}-transit" location = var.location resource_group_name = azurerm_resource_group.network.name address_space = [var.transit_vnet_cidr] tags = var.tags } resource "azurerm_subnet" "transit" { name = "snet-${local.prefix}-transit" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.transit.name address_prefixes = [var.transit_subnet_cidr] private_endpoint_network_policies = "Enabled" } # ============================================================================= # VNet Peerings # ============================================================================= # Main VNet <-> Transit VNet resource "azurerm_virtual_network_peering" "main_to_transit" { name = "peer-main-to-transit" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.main.name remote_virtual_network_id = azurerm_virtual_network.transit.id allow_forwarded_traffic = true } resource "azurerm_virtual_network_peering" "transit_to_main" { name = "peer-transit-to-main" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.transit.name remote_virtual_network_id = azurerm_virtual_network.main.id allow_forwarded_traffic = true } # Main VNet <-> Hub VNet (if provided) resource "azurerm_virtual_network_peering" "main_to_hub" { count = var.hub_vnet_id != "" ? 1 : 0 name = "peer-main-to-hub" resource_group_name = azurerm_resource_group.network.name virtual_network_name = azurerm_virtual_network.main.name remote_virtual_network_id = var.hub_vnet_id allow_forwarded_traffic = true allow_gateway_transit = false use_remote_gateways = true } # ============================================================================= # NAT Gateway (stable egress IPs for Databricks subnets) # ============================================================================= resource "azurerm_public_ip" "nat" { name = "pip-${local.prefix}-nat" location = var.location resource_group_name = azurerm_resource_group.network.name allocation_method = "Static" sku = "Standard" tags = var.tags } resource "azurerm_nat_gateway" "main" { name = "natgw-${local.prefix}" location = var.location resource_group_name = azurerm_resource_group.network.name sku_name = "Standard" idle_timeout_in_minutes = 10 tags = var.tags } resource "azurerm_nat_gateway_public_ip_association" "main" { nat_gateway_id = azurerm_nat_gateway.main.id public_ip_address_id = azurerm_public_ip.nat.id } resource "azurerm_subnet_nat_gateway_association" "dbx_host" { subnet_id = azurerm_subnet.dbx_host.id nat_gateway_id = azurerm_nat_gateway.main.id } resource "azurerm_subnet_nat_gateway_association" "dbx_container" { subnet_id = azurerm_subnet.dbx_container.id nat_gateway_id = azurerm_nat_gateway.main.id } # ============================================================================= # NSGs — Databricks Subnets (see Phase 0 plan §3 NSG Rule Set) # ============================================================================= resource "azurerm_network_security_group" "dbx" { name = "nsg-${local.prefix}-dbx" location = var.location resource_group_name = azurerm_resource_group.network.name tags = var.tags # --- Inbound --- security_rule { name = "AllowDatabricksControlPlaneInbound" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "AzureDatabricks" destination_address_prefix = "*" } security_rule { name = "AllowHostToContainer" priority = 200 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = var.dbx_host_subnet_cidr destination_address_prefix = var.dbx_container_subnet_cidr } security_rule { name = "AllowContainerToHost" priority = 201 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = var.dbx_container_subnet_cidr destination_address_prefix = var.dbx_host_subnet_cidr } security_rule { name = "DenyAllInbound" priority = 4096 direction = "Inbound" access = "Deny" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } # --- Outbound --- security_rule { name = "AllowDatabricksControlPlaneOutbound" priority = 100 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = "AzureDatabricks" } security_rule { name = "AllowSqlOutbound" priority = 110 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3306" source_address_prefix = "*" destination_address_prefix = "Sql" } security_rule { name = "AllowStorageOutbound" priority = 120 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = "Storage" } security_rule { name = "AllowEventHubOutbound" priority = 130 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "9093" source_address_prefix = "*" destination_address_prefix = "EventHub" } security_rule { name = "AllowPrivateEndpoints" priority = 200 direction = "Outbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = var.private_endpoints_subnet_cidr } security_rule { name = "DenyInternetOutbound" priority = 4096 direction = "Outbound" access = "Deny" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "Internet" } } # --- Associate NSG to both Databricks subnets --- resource "azurerm_subnet_network_security_group_association" "dbx_host" { subnet_id = azurerm_subnet.dbx_host.id network_security_group_id = azurerm_network_security_group.dbx.id } resource "azurerm_subnet_network_security_group_association" "dbx_container" { subnet_id = azurerm_subnet.dbx_container.id network_security_group_id = azurerm_network_security_group.dbx.id } # ============================================================================= # Private DNS Zones # ============================================================================= resource "azurerm_private_dns_zone" "databricks" { name = "privatelink.azuredatabricks.net" resource_group_name = azurerm_resource_group.network.name tags = var.tags } resource "azurerm_private_dns_zone" "dfs" { name = "privatelink.dfs.core.windows.net" resource_group_name = azurerm_resource_group.network.name tags = var.tags } resource "azurerm_private_dns_zone" "vault" { name = "privatelink.vaultcore.azure.net" resource_group_name = azurerm_resource_group.network.name tags = var.tags } resource "azurerm_private_dns_zone" "purview" { name = "privatelink.purview.azure.com" resource_group_name = azurerm_resource_group.network.name tags = var.tags } # --- Link DNS zones to VNets --- resource "azurerm_private_dns_zone_virtual_network_link" "databricks_main" { name = "link-dbx-main" resource_group_name = azurerm_resource_group.network.name private_dns_zone_name = azurerm_private_dns_zone.databricks.name virtual_network_id = azurerm_virtual_network.main.id } resource "azurerm_private_dns_zone_virtual_network_link" "databricks_transit" { name = "link-dbx-transit" resource_group_name = azurerm_resource_group.network.name private_dns_zone_name = azurerm_private_dns_zone.databricks.name virtual_network_id = azurerm_virtual_network.transit.id } resource "azurerm_private_dns_zone_virtual_network_link" "dfs_main" { name = "link-dfs-main" resource_group_name = azurerm_resource_group.network.name private_dns_zone_name = azurerm_private_dns_zone.dfs.name virtual_network_id = azurerm_virtual_network.main.id } resource "azurerm_private_dns_zone_virtual_network_link" "vault_main" { name = "link-vault-main" resource_group_name = azurerm_resource_group.network.name private_dns_zone_name = azurerm_private_dns_zone.vault.name virtual_network_id = azurerm_virtual_network.main.id } resource "azurerm_private_dns_zone_virtual_network_link" "purview_main" { name = "link-purview-main" resource_group_name = azurerm_resource_group.network.name private_dns_zone_name = azurerm_private_dns_zone.purview.name virtual_network_id = azurerm_virtual_network.main.id }