# Networking Module for Azure # Creates VNet, subnets, NSGs, and Application Gateway # Virtual Network resource "azurerm_virtual_network" "main" { name = "${var.cluster_name}-vnet" address_space = ["10.0.0.0/16"] location = var.location resource_group_name = var.resource_group_name tags = merge(var.tags, { Purpose = "Networking" }) } # Subnet for AKS resource "azurerm_subnet" "aks" { name = "${var.cluster_name}-aks-subnet" resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.1.0/24"] # Required for AKS service_endpoints = ["Microsoft.Storage", "Microsoft.KeyVault"] } # Subnet for validators (private) resource "azurerm_subnet" "validators" { name = "${var.cluster_name}-validators-subnet" resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.2.0/24"] # No service endpoints for private subnet } # Subnet for sentries (public P2P) resource "azurerm_subnet" "sentries" { name = "${var.cluster_name}-sentries-subnet" resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.3.0/24"] } # Subnet for RPC nodes (DMZ) resource "azurerm_subnet" "rpc" { name = "${var.cluster_name}-rpc-subnet" resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.4.0/24"] service_endpoints = ["Microsoft.Storage"] } # Subnet for Application Gateway resource "azurerm_subnet" "appgateway" { name = "${var.cluster_name}-appgateway-subnet" resource_group_name = var.resource_group_name virtual_network_name = azurerm_virtual_network.main.name address_prefixes = ["10.0.5.0/24"] } # Network Security Group for validators (private, no public access) resource "azurerm_network_security_group" "validators" { name = "${var.cluster_name}-validators-nsg" location = var.location resource_group_name = var.resource_group_name # Allow internal communication only security_rule { name = "AllowInternal" priority = 1000 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "10.0.0.0/16" destination_address_prefix = "*" } # Deny all other traffic security_rule { name = "DenyAll" priority = 4096 direction = "Inbound" access = "Deny" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "*" destination_address_prefix = "*" } tags = merge(var.tags, { Purpose = "Validators-NSG" }) } # Network Security Group for sentries (P2P port 30303) resource "azurerm_network_security_group" "sentries" { name = "${var.cluster_name}-sentries-nsg" location = var.location resource_group_name = var.resource_group_name # Allow P2P (30303 TCP/UDP) security_rule { name = "AllowP2P" priority = 1000 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "30303" source_address_prefix = "*" destination_address_prefix = "*" } security_rule { name = "AllowP2PUDP" priority = 1001 direction = "Inbound" access = "Allow" protocol = "Udp" source_port_range = "*" destination_port_range = "30303" source_address_prefix = "*" destination_address_prefix = "*" } # Allow internal communication security_rule { name = "AllowInternal" priority = 2000 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "10.0.0.0/16" destination_address_prefix = "*" } tags = merge(var.tags, { Purpose = "Sentries-NSG" }) } # Network Security Group for RPC (HTTPS only) resource "azurerm_network_security_group" "rpc" { name = "${var.cluster_name}-rpc-nsg" location = var.location resource_group_name = var.resource_group_name # Allow HTTPS (443) security_rule { name = "AllowHTTPS" priority = 1000 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "443" source_address_prefix = "*" destination_address_prefix = "*" } # Allow HTTP (for redirect to HTTPS) security_rule { name = "AllowHTTP" priority = 1001 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "80" source_address_prefix = "*" destination_address_prefix = "*" } # Allow internal communication security_rule { name = "AllowInternal" priority = 2000 direction = "Inbound" access = "Allow" protocol = "*" source_port_range = "*" destination_port_range = "*" source_address_prefix = "10.0.0.0/16" destination_address_prefix = "*" } tags = merge(var.tags, { Purpose = "RPC-NSG" }) } # Associate NSGs with subnets resource "azurerm_subnet_network_security_group_association" "validators" { subnet_id = azurerm_subnet.validators.id network_security_group_id = azurerm_network_security_group.validators.id } resource "azurerm_subnet_network_security_group_association" "sentries" { subnet_id = azurerm_subnet.sentries.id network_security_group_id = azurerm_network_security_group.sentries.id } resource "azurerm_subnet_network_security_group_association" "rpc" { subnet_id = azurerm_subnet.rpc.id network_security_group_id = azurerm_network_security_group.rpc.id } # Public IP for Application Gateway resource "azurerm_public_ip" "appgateway" { name = "${var.cluster_name}-appgateway-ip" location = var.location resource_group_name = var.resource_group_name allocation_method = "Static" sku = "Standard" tags = merge(var.tags, { Purpose = "Application-Gateway-IP" }) } # Application Gateway (simplified - full config would include backend pools, listeners, etc.) resource "azurerm_application_gateway" "main" { name = "${var.cluster_name}-appgateway" resource_group_name = var.resource_group_name location = var.location sku { name = "WAF_v2" tier = "WAF_v2" capacity = 2 } gateway_ip_configuration { name = "appGatewayIpConfig" subnet_id = azurerm_subnet.appgateway.id } frontend_port { name = "http" port = 80 } frontend_port { name = "https" port = 443 } frontend_ip_configuration { name = "appGatewayFrontendIP" public_ip_address_id = azurerm_public_ip.appgateway.id } # SSL Policy (required for WAF_v2) ssl_policy { policy_type = "Predefined" policy_name = "AppGwSslPolicy20220101" # Modern TLS policy } # WAF configuration waf_configuration { enabled = true firewall_mode = "Prevention" rule_set_type = "OWASP" rule_set_version = "3.2" file_upload_limit_mb = 100 request_body_check = true max_request_body_size_kb = 128 } # Minimal required blocks - will be configured after AKS deployment backend_address_pool { name = "default-backend-pool" # Backend IPs will be added after AKS services are deployed } backend_http_settings { name = "default-http-settings" cookie_based_affinity = "Disabled" port = 80 protocol = "Http" request_timeout = 20 } http_listener { name = "default-listener" frontend_ip_configuration_name = "appGatewayFrontendIP" frontend_port_name = "http" protocol = "Http" } request_routing_rule { name = "default-routing-rule" rule_type = "Basic" priority = 100 http_listener_name = "default-listener" backend_address_pool_name = "default-backend-pool" backend_http_settings_name = "default-http-settings" } # Note: Backend pools, HTTP settings, probes, listeners, and routing rules # should be reconfigured after AKS deployment when service IPs are known. # Use Azure CLI or Terraform to update these resources after initial deployment. # # For production, consider using Azure Application Gateway Ingress Controller (AGIC) # which automatically configures the Application Gateway based on Kubernetes ingress resources. tags = merge(var.tags, { Purpose = "Application-Gateway" }) } # Outputs are defined in outputs.tf