diff --git a/gcp/modules/tiles_tlog/network.tf b/gcp/modules/tiles_tlog/network.tf index 7117bb0..fff6ff7 100644 --- a/gcp/modules/tiles_tlog/network.tf +++ b/gcp/modules/tiles_tlog/network.tf @@ -115,6 +115,70 @@ data "google_compute_network_endpoint_group" "k8s_grpc_neg" { zone = each.key } +resource "google_compute_security_policy" "k8s_http_grpc_security_policy" { + name = "${var.shard_name}-k8s-http-grpc-security-policy" + project = var.project_id + type = "CLOUD_ARMOR" + + rule { + action = "deny(502)" + priority = "1" + + match { + expr { + expression = "int(request.headers['content-length']) > 8388608" + } + } + description = "Block all incoming write requests > 8MB" + } + + rule { + action = "throttle" + priority = "10" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + rate_limit_options { + enforce_on_key = "IP" + conform_action = "allow" + exceed_action = "deny(429)" + rate_limit_threshold { + count = var.http_grpc_qpm_rate_limit + interval_sec = "60" + } + } + description = "Rate limit all HTTP write traffic by client IP" + } + + rule { + action = "allow" + priority = "2147483647" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + description = "default rule" + } + + advanced_options_config { + json_parsing = "STANDARD" + json_custom_config { + content_types = ["application/json"] + } + } + + adaptive_protection_config { + layer_7_ddos_defense_config { + enable = var.enable_adaptive_protection + } + } +} + resource "google_compute_backend_service" "k8s_http_backend_service" { count = var.freeze_shard ? 0 : 1 name = "${var.shard_name}-${var.dns_subdomain_name}-k8s-neg-backend-service" @@ -138,6 +202,10 @@ resource "google_compute_backend_service" "k8s_http_backend_service" { } } + depends_on = [google_compute_security_policy.k8s_http_grpc_security_policy] + + security_policy = google_compute_security_policy.k8s_http_grpc_security_policy.self_link + log_config { enable = var.enable_backend_service_logging } @@ -166,15 +234,66 @@ resource "google_compute_backend_service" "k8s_grpc_backend_service" { } } + depends_on = [google_compute_security_policy.k8s_http_grpc_security_policy] + + security_policy = google_compute_security_policy.k8s_http_grpc_security_policy.self_link + log_config { enable = var.enable_backend_service_logging } } +resource "google_compute_security_policy" "bucket_security_policy" { + name = "${var.shard_name}-bucket-security-policy" + project = var.project_id + type = "CLOUD_ARMOR_EDGE" + + rule { + action = "throttle" + priority = "10" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + rate_limit_options { + enforce_on_key = "IP" + conform_action = "allow" + exceed_action = "deny(429)" + rate_limit_threshold { + count = var.bucket_qpm_rate_limit + interval_sec = "60" + } + } + description = "Rate limit all read traffic by client IP" + } + + rule { + action = "allow" + priority = "2147483647" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + description = "default rule" + } + + adaptive_protection_config { + layer_7_ddos_defense_config { + enable = var.enable_adaptive_protection + } + } +} + resource "google_compute_backend_bucket" "tessera_backend_bucket" { name = "${var.shard_name}-${var.bucket_name_suffix}" project = var.project_id + depends_on = [google_storage_bucket.tessera_store, google_compute_security_policy.bucket_security_policy] + bucket_name = google_storage_bucket.tessera_store.name enable_cdn = var.enable_cdn @@ -182,7 +301,7 @@ resource "google_compute_backend_bucket" "tessera_backend_bucket" { cache_mode = "USE_ORIGIN_HEADERS" } - depends_on = [google_storage_bucket.tessera_store] + edge_security_policy = google_compute_security_policy.bucket_security_policy.self_link lifecycle { prevent_destroy = true diff --git a/gcp/modules/tiles_tlog/variables.tf b/gcp/modules/tiles_tlog/variables.tf index 7f64c8e..3fd9da4 100644 --- a/gcp/modules/tiles_tlog/variables.tf +++ b/gcp/modules/tiles_tlog/variables.tf @@ -226,6 +226,24 @@ variable "enable_backend_service_logging" { default = true } +variable "http_grpc_qpm_rate_limit" { + description = "count of write requests per minute allowed to HTTP and gRPC backends" + type = number + default = 600 // 10 QPS +} + +variable "bucket_qpm_rate_limit" { + description = "count of read requests per minute allowed to the GCS bucket" + type = number + default = 30000 // 500 QPS +} + +variable "enable_adaptive_protection" { + description = "whether to enable layer 7 DDoS adaptive protection" + type = bool + default = true +} + variable "spanner_timeseries_role_id" { description = "name of the project role for managing timeseries entries for Spanner - role must include permissions `monitoring.timeSeries.create` and `monitoring.timeSeries.list`" type = string