diff --git a/.gitignore b/.gitignore index 7183dd8..7bb98a5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .terraform* *.tfstate *.tfstate.backup +*.tfplan +*.tfplan.* diff --git a/main.tf b/main.tf index f784541..a1ba692 100644 --- a/main.tf +++ b/main.tf @@ -14,15 +14,153 @@ provider "google" { zone = "europe-central2-b" } -data "google_project" "project" { - project_id = "network-getting-started" +# Networks +resource "google_compute_network" "vpc_hub" { + name = "dom-lab-hub" + auto_create_subnetworks = false } -resource "google_compute_instance" "vm_1" { - name = "tftest-vm" - machine_type = "e2-micro" +resource "google_compute_subnetwork" "net_hub" { + name = "hub" + region = "europe-central2" + ip_cidr_range = var.hub_cidr + network = google_compute_network.vpc_hub.id +} + +resource "google_compute_network" "vpc_spoke" { + name = "dom-lab-spoke" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "net_spoke" { + name = "spoke" + region = "europe-central2" + ip_cidr_range = var.spoke_cidr + network = google_compute_network.vpc_spoke.id +} + +# Peering +resource "google_compute_network_peering" "hub_to_spoke" { + name = "hub-to-spoke" + network = google_compute_network.vpc_hub.id + peer_network = google_compute_network.vpc_spoke.id + + export_custom_routes = true + import_custom_routes = false +} + +resource "google_compute_network_peering" "spoke_to_hub" { + name = "spoke-to-hub" + network = google_compute_network.vpc_spoke.id + peer_network = google_compute_network.vpc_hub.id + + export_custom_routes = false + import_custom_routes = true +} + +# Cloud NAT +resource "google_compute_router" "hub_cloud_router" { + name = "hub-cr" + network = google_compute_network.vpc_hub.id + region = "europe-central2" +} + +resource "google_compute_router_nat" "hub_nat" { + name = "hub-nat" + region = "europe-central2" + router = google_compute_router.hub_cloud_router.name + nat_ip_allocate_option = "AUTO_ONLY" + source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" +} + +resource "google_compute_router" "spoke_cloud_router" { + name = "spoke-cr" + network = google_compute_network.vpc_spoke.id + region = "europe-central2" +} + +resource "google_compute_router_nat" "spoke_nat" { + name = "spoke-nat" + region = "europe-central2" + router = google_compute_router.spoke_cloud_router.name + nat_ip_allocate_option = "AUTO_ONLY" + source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" +} + +# Cloud VPN +resource "google_compute_vpn_gateway" "gw" { + name = "vpn-1" + network = google_compute_network.vpc_hub.id +} + +resource "google_compute_address" "gw_ip" { + name = "vpn-1-ip" + address_type = "EXTERNAL" +} + +output "vpn_gw_ip" { + value = google_compute_address.gw_ip.address +} + +resource "google_compute_forwarding_rule" "gw_fw_esp" { + name = "fwd-esp" + ip_protocol = "ESP" + ip_address = google_compute_address.gw_ip.address + target = google_compute_vpn_gateway.gw.id +} + +resource "google_compute_forwarding_rule" "gw_fw_udp_500" { + name = "fwd-udp-500" + ip_protocol = "UDP" + ip_address = google_compute_address.gw_ip.address + port_range = "500" + target = google_compute_vpn_gateway.gw.id +} + +resource "google_compute_forwarding_rule" "gw_fw_udp_4500" { + name = "fwd-udp-4500" + ip_protocol = "UDP" + ip_address = google_compute_address.gw_ip.address + port_range = "4500" + target = google_compute_vpn_gateway.gw.id +} + +resource "google_compute_vpn_tunnel" "to_lazurowa" { + name = "to-lazurowa" + target_vpn_gateway = google_compute_vpn_gateway.gw.id + + shared_secret = var.shared_secret + peer_ip = var.peer_ip + ike_version = 2 + + local_traffic_selector = [ + var.hub_cidr, + var.spoke_cidr, + "35.199.192.0/19" + ] + + remote_traffic_selector = var.on_prem_selectors + + depends_on = [ + google_compute_forwarding_rule.gw_fw_esp, + google_compute_forwarding_rule.gw_fw_udp_500, + google_compute_forwarding_rule.gw_fw_udp_4500 + ] +} + +resource "google_compute_route" "rt_to_on_prem" { + count = length(var.on_prem_selectors) + name = "to-on-prem-${count.index + 1}" + network = "dom-lab-hub" + dest_range = var.on_prem_selectors[count.index] + next_hop_vpn_tunnel = google_compute_vpn_tunnel.to_lazurowa.id +} + +resource "google_compute_instance" "vm_hub" { + name = "vm-hub" + machine_type = "e2-micro" can_ip_forward = false - description = "Terraform test instance" + description = "A VM in the hub network" boot_disk { initialize_params { @@ -31,11 +169,43 @@ resource "google_compute_instance" "vm_1" { } network_interface { - network = "dom-lab-vpc" - subnetwork = "pl-hub" + network = "dom-lab-hub" + subnetwork = "hub" } metadata = { ssh-keys = "${var.ssh[0].public_key} ${var.ssh[0].ssh_user}" } } + +output "vm_hub_ip" { + value = google_compute_instance.vm_hub.network_interface[0].network_ip +} + +resource "google_compute_instance" "vm_spoke" { + name = "vm-spoke" + machine_type = "e2-micro" + can_ip_forward = false + description = "A VM in the spoke network" + # project = "spoke-network" + + boot_disk { + initialize_params { + image = "debian-cloud/debian-12" + } + } + + network_interface { + network = "dom-lab-spoke" + subnetwork = "spoke" + # subnetwork_project = "spoke-network" + } + + metadata = { + ssh-keys = "${var.ssh[0].public_key} ${var.ssh[0].ssh_user}" + } +} + +output "vm_spoke_ip" { + value = google_compute_instance.vm_spoke.network_interface[0].network_ip +} diff --git a/variables.tf b/variables.tf index 201ddff..50703a7 100644 --- a/variables.tf +++ b/variables.tf @@ -4,4 +4,37 @@ variable "ssh" { public_key = string ssh_user = string })) + default = [{ + public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID1Z96CGdoNnbazs89cdnDLDdju6UtuKAZctEAmnEaAC" + ssh_user = "slawek@1password" + }] +} + +variable "shared_secret" { + description = "Shared secret for the VPN tunnel" + type = string + sensitive = true +} + +variable "peer_ip" { + description = "IP address of the peer VPN gateway" + type = string +} + +variable "hub_cidr" { + description = "Hub CIDR block" + type = string + default = "192.168.16.0/24" +} + +variable "spoke_cidr" { + description = "Spoke CIDR block" + type = string + default = "192.168.17.0/24" +} + +variable "on_prem_selectors" { + type = list(string) + default = ["192.168.2.0/24", "192.168.10.0/24"] + description = "On-premise traffic selectors" }