For our connection to the Euronet Sandbox we have implemented IPsec VPN in the safi-env-x-sharedvpc
project.
VPN Implementation:
The VPN is implemented trough terraform with the use of HCV for secret management.
The terraform can be found in the tf-environments folder, and is being run from the safi-env
workspaces.
The necessary secrets can be found in the vault, they are different per environment but for brave they can be found here.
locals { udp_rules = { udp500 = "500" udp4500 = "4500" } } #Create the Public IP for the Gateway resource "google_compute_address" "vpn-public-ip" { provider = google-beta.sharedvpc name = "${local.prefix}-${var.env_name}-vpn-public-ip" } #Create the VPN Gateway resource "google_compute_vpn_gateway" "vpn-gateway" { provider = google-beta.sharedvpc name = "${local.prefix}-${var.env_name}-vpn-gateway" network = google_compute_network.shared_vpc.id } #Create tunnel between Safi and Euronet resource "google_compute_vpn_tunnel" "euronet-tunnel" { provider = google-beta.sharedvpc name = "${local.prefix}-${var.env_name}-euronet-tunnel" peer_ip = data.vault_generic_secret.euronet.data["euronet_peer_ip"] shared_secret = data.vault_generic_secret.euronet.data["euronet_shared_key"] local_traffic_selector = [local.curr_env.projects["applications"].k8s.secondary_ranges["euronet-pods"]] remote_traffic_selector = [data.vault_generic_secret.euronet.data["euronet_remote_subnet"]] target_vpn_gateway = google_compute_vpn_gateway.vpn-gateway.id depends_on = [ google_compute_forwarding_rule.forwarding_esp, google_compute_forwarding_rule.forwarding_udp ] } #Forwarding Rules for VPN resource "google_compute_forwarding_rule" "forwarding_esp" { provider = google-beta.sharedvpc name = "${local.prefix}-${var.env_name}-firewall-rule-esp" ip_protocol = "ESP" ip_address = google_compute_address.vpn-public-ip.address target = google_compute_vpn_gateway.vpn-gateway.id } resource "google_compute_forwarding_rule" "forwarding_udp" { provider = google-beta.sharedvpc for_each = local.udp_rules name = "${local.prefix}-${var.env_name}-firewall-rule-${each.key}" ip_protocol = "UDP" port_range = each.value ip_address = google_compute_address.vpn-public-ip.address target = google_compute_vpn_gateway.vpn-gateway.id } #Create a Route that points towards Euronet Subnets resource "google_compute_route" "euronet-route" { provider = google-beta.sharedvpc name = "euronet-route" network = google_compute_network.shared_vpc.id dest_range = data.vault_generic_secret.euronet.data["euronet_remote_subnet"] priority = 1000 next_hop_vpn_tunnel = google_compute_vpn_tunnel.euronet-tunnel.id } #Firwall rules for Safi to Euronet Traffic resource "google_compute_firewall" "euronet-rules" { provider = google.sharedvpc name = "${local.prefix}-${var.env_name}-euronet-vpn" description = "Managed by vpn.tf don't modify in console" network = google_compute_network.shared_vpc.id direction = "EGRESS" destination_ranges = [data.vault_generic_secret.euronet.data["euronet_remote_subnet"]] allow { protocol = "tcp" ports = [ "443", #Euronet Provided Port ] } } data "vault_generic_secret" "euronet" { path = format("secret/%s/vpn/euronet", var.env_name) }
GKE and Kubernetes Configuration:
The next requirement for Euronet other than to use IPSec VPN was the network size limit we got from them, which was at max /24 network, for this we have created a specific node-pool to which we deploy all things that have to have access to the sandbox.
The node_pool is configured in applications-project in applications_gke.tf
resource "google_container_node_pool" "standard-2vcpu-8gb_vpn" { provider = google-beta.applications name_prefix = "euronet-gtw-" location = var.google_region cluster = module.gke_shared_vpc_applications.cluster.name node_count = 1 max_pods_per_node = 32 network_config { pod_range = "gke-euronet-pods-range" } node_config { preemptible = false machine_type = "n2-standard-2" labels = { "cloud.google.com/gke-role" = "euronet-gateway" } workload_metadata_config { mode = "GKE_METADATA" } taint { key = "safi_nodegroup_class" value = "euronet_gateway" effect = "NO_SCHEDULE" } service_account = module.gke_shared_vpc_applications.service_account.email oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"] tags = ["${local.prefix}-${var.env_name}-vpn-applications-node-pool"] } autoscaling { min_node_count = 0 max_node_count = 4 } lifecycle { ignore_changes = [ node_count, ] create_before_destroy = true } }
We then use tolerations, affinity and antiaffinity to deploy the necessary services and only those to this specific node pool:
tolerations: - key: "safi_nodegroup_class" operator: "Equal" value: "euronet_gateway" effect: "NoSchedule" affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cloud.google.com/gke-role operator: In values: - euronet-gateway podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app operator: In values: - euronet-gateway topologyKey: topology.kubernetes.io/zone