diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl index 135f90f..3453806 100755 --- a/terraform/.terraform.lock.hcl +++ b/terraform/.terraform.lock.hcl @@ -73,3 +73,21 @@ provider "registry.terraform.io/hashicorp/random" { "zh:fbdd0684e62563d3ac33425b0ac9439d543a3942465f4b26582bcfabcb149515", ] } + +provider "registry.terraform.io/hashicorp/tls" { + version = "3.0.0" + constraints = ">= 3.0.0" + hashes = [ + "h1:LtCEW5v1E5Eo49+kQOsKHRYf9Hc8ZR0jTpK+mXszPHs=", + "zh:05eac573a1fe53227bcc6b01daf6ddf0b73456f97f56f316f1b3114a4771e175", + "zh:09390dad764c76f0fd59cae4dad296e3e39487e06de3a4bc0df73916c6bb2f17", + "zh:142d0bc4722ab088b7ca124b0eb44206b9d100f51035c162d50ef552e09813d0", + "zh:2c391743dd20f43329c0d0d49dec7827970d788115593c0e32a57050c0a85337", + "zh:525b12fc87369c0e6d347afe6c77668aebf56cfa078bb0f1f01cc2ee01ac7016", + "zh:5583d81b7a05c6d49a4c445e1ee62e82facb07bb9204998a836b7b522a51db8d", + "zh:925e3acc70e18ed1cd296d337fc3e0ca43ac6f5bf2e660f24de750c7754f91aa", + "zh:a291457d25b207fd28fb4fad9209ebb591e25cfc507ca1cb0fb8b2e255be1969", + "zh:bbf9e2718752aebfbd7c6b8e196eb2e52730b66befed2ea1954f9ff1c199295e", + "zh:f4b333c467ae02c1a238ac57465fe66405f6e2a6cfeb4eded9bc321c5652a1bf", + ] +} diff --git a/terraform/bot.tf b/terraform/bot.tf index c0dc5bf..a6bf2ba 100644 --- a/terraform/bot.tf +++ b/terraform/bot.tf @@ -83,7 +83,6 @@ resource "google_compute_instance" "bot" { gce-container-declaration = local.containerMetadataWithSecrets image = local.container.image environment = var.environment_tag - google-logging-enabled = "true" } labels = { diff --git a/terraform/cloudflare-origin-cert.tf b/terraform/cloudflare-origin-cert.tf new file mode 100644 index 0000000..d88647e --- /dev/null +++ b/terraform/cloudflare-origin-cert.tf @@ -0,0 +1,20 @@ +resource "tls_private_key" "tls_pk" { + algorithm = "RSA" +} + +resource "tls_cert_request" "web_csr" { + key_algorithm = tls_private_key.tls_pk.algorithm + private_key_pem = tls_private_key.tls_pk.private_key_pem + + subject { + common_name = "web-${var.environment_tag}.roleypoly.com" + organization = "Roleypoly" + } +} + +resource "cloudflare_origin_ca_certificate" "web" { + csr = tls_cert_request.web_csr.cert_request_pem + hostnames = ["web-${var.environment_tag}.roleypoly.com"] + request_type = "origin-rsa" + requested_validity = 365 * 15 +} \ No newline at end of file diff --git a/terraform/providers.tf b/terraform/providers.tf index 9c712bf..817dd58 100644 --- a/terraform/providers.tf +++ b/terraform/providers.tf @@ -25,6 +25,11 @@ terraform { version = ">=3.0.0" source = "hashicorp/null" } + + tls = { + version = ">=3.0.0" + source = "hashicorp/tls" + } } backend "gcs" { @@ -37,6 +42,11 @@ variable "cloudflare_api_token" { sensitive = true } +variable "cloudflare_origin_ca_key" { + type = string + sensitive = true +} + variable "cloudflare_account_id" { type = string sensitive = true @@ -48,8 +58,9 @@ variable "cloudflare_zone_id" { } provider "cloudflare" { - api_token = var.cloudflare_api_token - account_id = var.cloudflare_account_id + api_token = var.cloudflare_api_token + account_id = var.cloudflare_account_id + api_user_service_key = var.cloudflare_origin_ca_key } variable "gcp_project" { diff --git a/terraform/variables.tf b/terraform/variables.tf index 749b690..84d15ff 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -70,7 +70,7 @@ variable "bot_instance_size" { } variable "bot_tag" { - type = string - default = "" + type = string + default = "" description = ":tag or @sha265: of ghcr.io/roleypoly/bot" } \ No newline at end of file diff --git a/terraform/weblb.tf b/terraform/weblb.tf index 978a351..81ff1b0 100644 --- a/terraform/weblb.tf +++ b/terraform/weblb.tf @@ -1,3 +1,11 @@ +// Maps all requests to the backend service +resource "google_compute_url_map" "web_lb" { + name = "lb-um-web-${var.environment_tag}" + + default_service = google_compute_backend_service.web_lb.id +} + +// Regional load balancer resource "google_compute_backend_service" "web_lb" { name = "lb-rbes-web-${var.environment_tag}" @@ -9,30 +17,56 @@ resource "google_compute_backend_service" "web_lb" { } } -resource "google_compute_url_map" "web_lb" { - name = "lb-um-web-${var.environment_tag}" +// Origin TLS cert from Cloudflare +resource "google_compute_ssl_certificate" "origin_tls" { + name_prefix = "cf-origin-web-${var.environment_tag}-" + private_key = tls_private_key.tls_pk.private_key_pem + certificate = cloudflare_origin_ca_certificate.web.certificate - default_service = google_compute_backend_service.web_lb.id + lifecycle { + create_before_destroy = true + } } -resource "google_compute_target_http_proxy" "web_lb" { - name = "lb-http-web-${var.environment_tag}" - url_map = google_compute_url_map.web_lb.id +// HTTPS proxy +resource "google_compute_target_https_proxy" "web_lb" { + name = "lb-http-web-${var.environment_tag}" + url_map = google_compute_url_map.web_lb.id + ssl_certificates = [google_compute_ssl_certificate.origin_tls.id] } +// Static IPs, Anycast resource "google_compute_global_address" "web_lb-ipv4" { name = "lb-ga-web-ipv4-${var.environment_tag}" ip_version = "IPV4" } +resource "google_compute_global_address" "web_lb-ipv6" { + name = "lb-ga-web-ipv6-${var.environment_tag}" + ip_version = "IPV6" +} + +// Forwarding rules (if request on 443, send to proxy) resource "google_compute_global_forwarding_rule" "web_lb-ipv4" { provider = google-beta name = "lb-fr-web-ipv4-${var.environment_tag}" - target = google_compute_target_http_proxy.web_lb.self_link - port_range = "80" - ip_version = "IPV4" + target = google_compute_target_https_proxy.web_lb.self_link + port_range = "443" + ip_address = google_compute_global_address.web_lb-ipv4.address } + + +resource "google_compute_global_forwarding_rule" "web_lb-ipv6" { + provider = google-beta + + name = "lb-fr-web-ipv6-${var.environment_tag}" + target = google_compute_target_https_proxy.web_lb.self_link + port_range = "443" + ip_address = google_compute_global_address.web_lb-ipv6.address +} + +// Cloudflare DNS records resource "cloudflare_record" "web-ipv4" { zone_id = var.cloudflare_zone_id name = "web-${var.environment_tag}" @@ -40,18 +74,6 @@ resource "cloudflare_record" "web-ipv4" { value = google_compute_global_forwarding_rule.web_lb-ipv4.ip_address proxied = true } -resource "google_compute_global_address" "web_lb-ipv6" { - name = "lb-ga-web-ipv6-${var.environment_tag}" - ip_version = "IPV6" -} -resource "google_compute_global_forwarding_rule" "web_lb-ipv6" { - provider = google-beta - - name = "lb-fr-web-ipv6-${var.environment_tag}" - target = google_compute_target_http_proxy.web_lb.self_link - port_range = "80" - ip_address = google_compute_global_address.web_lb-ipv6.address -} resource "cloudflare_record" "web-ipv6" { zone_id = var.cloudflare_zone_id @@ -61,6 +83,7 @@ resource "cloudflare_record" "web-ipv6" { proxied = true } +// Regional groups so the backend service knows what it can route to for a given region resource "google_compute_region_network_endpoint_group" "web_lb" { provider = google-beta for_each = toset(var.ui_regions)