diff --git a/google-cloud-secure-web-proxy-cloud-run/README.md b/google-cloud-secure-web-proxy-cloud-run/README.md new file mode 100644 index 0000000..79b55da --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/README.md @@ -0,0 +1,3 @@ +# Use transparent Secure Web Proxy together with Cloud Run + +Content for the LinkedIn Article which appeared here diff --git a/google-cloud-secure-web-proxy-cloud-run/config.auto.tfvars b/google-cloud-secure-web-proxy-cloud-run/config.auto.tfvars new file mode 100644 index 0000000..0891876 --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/config.auto.tfvars @@ -0,0 +1,11 @@ +project_id = "" # Insert your project ID here + +project_services = [ + "compute.googleapis.com", + "iam.googleapis.com", + "monitoring.googleapis.com", + "logging.googleapis.com", + "networksecurity.googleapis.com", # Necessary to create Secure Web Proxy + "networkservices.googleapis.com", # Necessary to create Secure Web Proxy + "run.googleapis.com", +] diff --git a/google-cloud-secure-web-proxy-cloud-run/infra/cloud_run.tf b/google-cloud-secure-web-proxy-cloud-run/infra/cloud_run.tf new file mode 100644 index 0000000..8cd070b --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/infra/cloud_run.tf @@ -0,0 +1,29 @@ +resource "google_cloud_run_v2_service" "main" { + project = var.project_id + name = "run-svc" + location = "europe-west3" + deletion_protection = false + + template { + containers { + image = "nginx:alpine" + name = "main-nginx-srv" + ports { + container_port = "80" + } + } + containers { + image = "alpine/curl:latest" + name = "sidecar-curler" + command = ["/bin/sh", "-c", "while true; do sleep 10; curl -v https://www.oktoberfest.de; done"] + } + vpc_access { + network_interfaces { + network = module.vpc_spoke.network_name + subnetwork = module.vpc_spoke.subnets["europe-west3/sub-cloudrun-ew3"].name + tags = ["proxy-routed"] + } + egress = "ALL_TRAFFIC" + } + } +} diff --git a/google-cloud-secure-web-proxy-cloud-run/infra/network.tf b/google-cloud-secure-web-proxy-cloud-run/infra/network.tf new file mode 100644 index 0000000..c55bac6 --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/infra/network.tf @@ -0,0 +1,55 @@ +module "vpc_egress" { + source = "terraform-google-modules/network/google" + version = "~> 9.1" + + project_id = var.project_id + network_name = "net-central-egress" + routing_mode = "GLOBAL" + + subnets = [ + { + subnet_name = "sub-swp" + subnet_ip = "10.1.0.0/24" + subnet_region = "europe-west3" + subnet_private_access = false + }, + { + subnet_name = "sub-swp-proxy-only" + subnet_region = "europe-west3" + subnet_ip = "10.1.1.0/24" + purpose = "REGIONAL_MANAGED_PROXY" + role = "ACTIVE" + }, + ] +} + +module "vpc_spoke" { + source = "terraform-google-modules/network/google" + version = "~> 9.1" + + project_id = var.project_id + network_name = "net-spoke" + routing_mode = "GLOBAL" + + subnets = [ + { + subnet_name = "sub-cloudrun-ew3" + subnet_ip = "10.5.0.0/16" + subnet_region = "europe-west3" + subnet_private_access = true + }, + ] +} + +# Peer both networks +resource "google_compute_network_peering" "spoke_to_egress" { + name = "spoke-to-egress" + network = module.vpc_spoke.network_self_link + peer_network = module.vpc_egress.network_self_link +} + +resource "google_compute_network_peering" "egress_to_spoke" { + name = "egress-to-spoke" + network = module.vpc_egress.network_self_link + peer_network = module.vpc_spoke.network_self_link +} diff --git a/google-cloud-secure-web-proxy-cloud-run/infra/proxy.tf b/google-cloud-secure-web-proxy-cloud-run/infra/proxy.tf new file mode 100644 index 0000000..453a7ab --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/infra/proxy.tf @@ -0,0 +1,43 @@ +resource "google_network_security_gateway_security_policy" "swp_pol" { + project = var.project_id + name = "swp-pol" + location = "europe-west3" +} + +resource "google_network_security_gateway_security_policy_rule" "swp_rule_allow" { + project = var.project_id + name = "swp-rule-allow-domains" + location = "europe-west3" + gateway_security_policy = google_network_security_gateway_security_policy.swp_pol.name + description = "Allow oktoberfest.de and google.com" + enabled = true + priority = 1 + session_matcher = "host().contains('oktoberfest.de') || host().contains('google.com')" + basic_profile = "ALLOW" +} + +resource "google_network_services_gateway" "swp" { + name = "swp-test" + project = var.project_id + location = "europe-west3" + addresses = ["10.1.0.10"] # Set IP at which the proxy is accessible + type = "SECURE_WEB_GATEWAY" # SECURE_WEB_GATEWAY represents the Secure Web Proxy instance + routing_mode = "NEXT_HOP_ROUTING_MODE" # Configure as transparent proxy to use as next hop + ports = [80, 443] # Allow HTTP(S) ports + gateway_security_policy = google_network_security_gateway_security_policy.swp_pol.id # Attach policy + network = module.vpc_egress.network_id + subnetwork = module.vpc_egress.subnets["europe-west3/sub-swp"].id + scope = "custom-swp-scope1" + delete_swg_autogen_router_on_destroy = true +} + +# Set proxy as next hop for all traffic +resource "google_compute_route" "proxy_transparent" { + project = var.project_id + name = "swp-transparent-route" + dest_range = "0.0.0.0/0" + network = module.vpc_spoke.network_name + next_hop_ilb = "10.1.0.10" + priority = 100 + tags = ["proxy-routed"] +} diff --git a/google-cloud-secure-web-proxy-cloud-run/infra/variables.tf b/google-cloud-secure-web-proxy-cloud-run/infra/variables.tf new file mode 100644 index 0000000..1d1236c --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/infra/variables.tf @@ -0,0 +1,4 @@ +variable "project_id" { + type = string + description = "The GCP project ID" +} diff --git a/google-cloud-secure-web-proxy-cloud-run/main.tf b/google-cloud-secure-web-proxy-cloud-run/main.tf new file mode 100644 index 0000000..38a705d --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/main.tf @@ -0,0 +1,13 @@ +resource "google_project_service" "main" { + for_each = var.project_services + project = var.project_id + service = each.value + disable_dependent_services = true +} + +module "infra" { + source = "./infra" + project_id = var.project_id + + depends_on = [google_project_service.main] +} diff --git a/google-cloud-secure-web-proxy-cloud-run/terraform.tf b/google-cloud-secure-web-proxy-cloud-run/terraform.tf new file mode 100644 index 0000000..90a2c04 --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/terraform.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 6.0" + } + } +} + +provider "google" { + +} diff --git a/google-cloud-secure-web-proxy-cloud-run/variables.tf b/google-cloud-secure-web-proxy-cloud-run/variables.tf new file mode 100644 index 0000000..999a965 --- /dev/null +++ b/google-cloud-secure-web-proxy-cloud-run/variables.tf @@ -0,0 +1,9 @@ +variable "project_id" { + description = "GCP project ID" + type = string +} + +variable "project_services" { + description = "GCP project enabled services" + type = set(string) +}