terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = ">= 4.46" } } required_version = ">= 1.0.0" } provider "azurerm" { subscription_id = var.subscription_id features {} } resource "azurerm_resource_group" "rg" { name = "${var.prefix}-rg" location = var.location } resource "azurerm_virtual_network" "vnet" { name = "${var.prefix}-vnet" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location address_space = var.vnet_address_space } # IMPORTANT: GatewaySubnet must be named "GatewaySubnet" resource "azurerm_subnet" "gateway_subnet" { name = "GatewaySubnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.gateway_subnet_address_prefixes } resource "azurerm_public_ip" "vpn_gateway_pip" { name = "${var.prefix}-vpn-gw-pip" resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location allocation_method = "Static" sku = "Standard" } data "local_sensitive_file" "root_certificate" { filename = "${path.module}/certificates/vpn-root.crt" } resource "azurerm_virtual_network_gateway" "vpn_gw" { name = "${var.prefix}-vpngw" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name type = "Vpn" vpn_type = "RouteBased" sku = var.vpn_gateway_sku ip_configuration { name = "vpngw-ipcfg" public_ip_address_id = azurerm_public_ip.vpn_gateway_pip.id subnet_id = azurerm_subnet.gateway_subnet.id } # Point-to-site configuration using certificate auth vpn_client_configuration { address_space = var.vpn_client_address_space root_certificate { name = var.root_certificate_name public_cert_data = data.local_sensitive_file.root_certificate.content } } } resource "azurerm_subnet" "workload_subnet" { name = "${var.prefix}-workload-subnet" resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet.name address_prefixes = var.workload_subnet_address_prefixes } resource "azurerm_network_security_group" "vm_nsg" { name = "${var.prefix}-vm-nsg" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name # Allow RDP from VPN client address pool security_rule { name = "Allow-RDP-From-VPN" priority = 100 direction = "Inbound" access = "Allow" protocol = "Tcp" source_port_range = "*" destination_port_range = "3389" source_address_prefixes = var.vpn_client_address_space destination_address_prefix = "*" } } resource "azurerm_network_interface" "vm_nic" { name = "${var.prefix}-vm-nic" location = azurerm_resource_group.rg.location resource_group_name = azurerm_resource_group.rg.name ip_configuration { name = "internal" subnet_id = azurerm_subnet.workload_subnet.id private_ip_address_allocation = "Dynamic" } } resource "azurerm_network_interface_security_group_association" "vm_nsg_assoc" { network_interface_id = azurerm_network_interface.vm_nic.id network_security_group_id = azurerm_network_security_group.vm_nsg.id } resource "random_password" "admin_password" { length = 16 special = false } resource "azurerm_windows_virtual_machine" "vm" { name = "${var.prefix}-winvm" computer_name = var.prefix resource_group_name = azurerm_resource_group.rg.name location = azurerm_resource_group.rg.location size = "Standard_NG8ads_V620_v1" admin_username = var.vm_admin_username admin_password = random_password.admin_password.result network_interface_ids = [ azurerm_network_interface.vm_nic.id ] os_disk { caching = "ReadWrite" storage_account_type = "Premium_LRS" } source_image_reference { publisher = "MicrosoftWindowsServer" offer = "WindowsServer" sku = "2019-Datacenter" version = "latest" } }