commit 72404852388cfd576d5c520a6538765fd4407327 Author: Jona Heitzer Date: Thu Oct 2 18:07:55 2025 +0200 First try, fuck vpn gateways diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..428b142 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +certificates/ +.terraform +.terraform.* +*.tfstate +*.tfstate.backup +.DS_Store diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..b539452 --- /dev/null +++ b/main.tf @@ -0,0 +1,149 @@ +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" + } +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..271f99d --- /dev/null +++ b/outputs.tf @@ -0,0 +1,8 @@ +output "windows_vm_private_ip" { + value = azurerm_network_interface.vm_nic.private_ip_address +} + +output "vm_admin_password" { + sensitive = true + value = random_password.admin_password.result +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..0ef598b --- /dev/null +++ b/variables.tf @@ -0,0 +1,59 @@ +variable "subscription_id" { + description = "Subscription ID of the subscription for gaming related stuff" + type = string + default = "90aed1cc-9b7f-4d3d-b2b9-b3654b49835e" +} + +variable "prefix" { + description = "Prefix for gaming related ressources" + type = string + default = "wa5p-gaming" +} + +variable "location" { + description = "Locatino for gaming related ressources, should be as close as possible for low latency" + type = string + default = "westeurope" +} + +variable "vnet_address_space" { + description = "List of IP nets for gaming vnet" + type = list(string) + default = ["10.0.1.0/24"] +} + +variable "gateway_subnet_address_prefixes" { + description = "IP prexixes for vpn gateway subnet (currently only one allowed)" + type = list(string) + default = ["10.0.1.0/25"] +} + +variable "vpn_gateway_sku" { + description = "SKU of VPN gateway" + type = string + default = "VpnGw1" +} + +variable "vpn_client_address_space" { + description = "Private IP addresses to be assigned to the connecting clients, must not overlap with any other assignment (in cloud or on premise)" + type = list(string) + default = ["10.123.1.0/24"] +} + +variable "root_certificate_name" { + description = "Name of the root certificate used for vpn authentication (CN in generation command)" + type = string + default = "p2s-root-01" +} + +variable "workload_subnet_address_prefixes" { + description = "IP subnet address prefixes for workload subnet, must be in same vnet as gateway subnet" + type = list(string) + default = ["10.0.1.128/25"] +} + +variable "vm_admin_username" { + description = "VM admin username, password will be generated randomly" + type = string + default = "jona" +}