From 960238611072352df55df83e6ac54ae146884013 Mon Sep 17 00:00:00 2001 From: Jakub Novak Date: Mon, 21 Oct 2024 16:24:30 -0700 Subject: [PATCH] Add cloud armor policies --- .terraform.lock.hcl | 82 +++++++------- Makefile | 9 +- main.tf | 4 +- packages/api/main.tf | 2 +- packages/cluster/network/main.tf | 189 +++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 45 deletions(-) diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index b65ab8f3e..269bd6759 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -44,61 +44,61 @@ provider "registry.terraform.io/hashicorp/consul" { } provider "registry.terraform.io/hashicorp/external" { - version = "2.3.3" + version = "2.3.4" hashes = [ - "h1:gShzO1rJtADK9tDZMvMgjciVAzsBh39LNjtThCwX1Hg=", - "zh:03d81462f9578ec91ce8e26f887e34151eda0e100f57e9772dbea86363588239", - "zh:37ec2a20f6a3ec3a0fd95d3f3de26da6cb9534b30488bc45723e118a0911c0d8", - "zh:4eb5b119179539f2749ce9de0e1b9629d025990f062f4f4dddc161562bb89d37", - "zh:5a31bb58414f41bee5e09b939012df5b88654120b0238a89dfd6691ba197619a", - "zh:6221a05e52a6a2d4f520ffe7cbc741f4f6080e0855061b0ed54e8be4a84eb9b7", + "h1:cCabxnWQ5fX1lS7ZqgUzsvWmKZw9FA7NRxAZ94vcTcc=", + "zh:037fd82cd86227359bc010672cd174235e2d337601d4686f526d0f53c87447cb", + "zh:0ea1db63d6173d01f2fa8eb8989f0809a55135a0d8d424b08ba5dabad73095fa", + "zh:17a4d0a306566f2e45778fbac48744b6fd9c958aaa359e79f144c6358cb93af0", + "zh:298e5408ab17fd2e90d2cd6d406c6d02344fe610de5b7dae943a58b958e76691", + "zh:38ecfd29ee0785fd93164812dcbe0664ebbe5417473f3b2658087ca5a0286ecb", + "zh:59f6a6f31acf66f4ea3667a555a70eba5d406c6e6d93c2c641b81d63261eeace", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8bb068496b4679bef625e4710d9f3432e301c3a56602271f04e60eadf7f8a94c", - "zh:94742aa5378bab626ce34f79bcef6a373e4f86ea7a8b762e9f71270a899e0d00", - "zh:a485831b5a525cd8f40e8982fa37da40ff70b1ae092c8b755fcde123f0b1238d", - "zh:a647ff16d071eabcabd87ea8183eb90a775a0294ddd735d742075d62fff09193", - "zh:b74710c5954aaa3faf262c18d36a8c2407862d9f842c63e7fa92fa4de3d29df6", - "zh:fa73d83edc92af2e551857594c2232ba6a9e3603ad34b0a5940865202c08d8d7", + "zh:ad0279dfd09d713db0c18469f585e58d04748ca72d9ada83883492e0dd13bd58", + "zh:c69f66fd21f5e2c8ecf7ca68d9091c40f19ad913aef21e3ce23836e91b8cbb5f", + "zh:d4a56f8c48aa86fc8e0c233d56850f5783f322d6336f3bf1916e293246b6b5d4", + "zh:f2b394ebd4af33f343835517e80fc876f79361f4688220833bc3c77655dd2202", + "zh:f31982f29f12834e5d21e010856eddd19d59cd8f449adf470655bfd19354377e", ] } provider "registry.terraform.io/hashicorp/google" { - version = "5.25.0" - constraints = ">= 4.50.0, 5.25.0, < 6.0.0" + version = "5.31.0" + constraints = ">= 4.50.0, 5.31.0, < 6.0.0" hashes = [ - "h1:l9oedcgAeLuI96Xkh6YsTGFKi7eJUxkGtKJO8V3VviM=", - "zh:0138a0434b86799c1a6a69e159e658071757609e9373e3fc25257a0efe6319b8", - "zh:0ebaa939848142064a4f18b5114d8389c2280baf9b92422f4873db64b150ecb9", - "zh:107121f58c85a77148eaefbec1bee6c74cfc6df7b3c3767816f0fdfc1a944856", - "zh:1fc277bcd2bd28b782f563bb2107d2a592a2ae86261b8c0a724a139c8993b5e2", - "zh:47c7aa8323c7530b5c553dfb9dae0870e52f6960f629dd68697b0f30c082a6bc", - "zh:588adf7f56732f7ac420c8ac47d22168a4992a307f02d7075fab9698a877c8f9", - "zh:7a0516082632a7b4f5ab60ac2ce292a7a57b93c735144bff2b6bb3b9d9fb00bf", - "zh:9c383db001ec8a68375ca46355f04fa651d6ad7653119de9430aaf82a758aa3e", - "zh:be35b6861196b8b71574e99e20dacaf1a7db9ca26559db997011fc0808f86009", - "zh:dbb9b49f9bf9c352e8bdf6ab920b2e1467ee16646422c5d3f7b5339b92d43ca1", - "zh:f3ecd9032629da3f774031fe50d4b4c43b90ec8bba171695775d56d15bf1099a", + "h1:q3xMw4s8/0yP7EiIzcULyANOMF/b/f/gRpACOQi+wCE=", + "zh:19f68d33a25c1d79dccb90ddf990e971943eef1de0272858a94e88571bd5792b", + "zh:2d65f3c99171c4ff4a7b28d2b2752f1da3303c94ec04279c655dd11743c86da7", + "zh:34097f7f24deb51d70097fd7a39b241c00c3da19ce0fabfb1623564fd6fec489", + "zh:3ec28324c262d0f026a7f5ebb7c3fe2ff3f0b80abe231650dc665b9b71393239", + "zh:8dc9263bf5ce4b2923ef3ff5fe40273eaeea670e1d7a410b4cccb51afc25691e", + "zh:9d745f410c4fd908d36ae5f5ec397dab1b272a84998e0a1a235ea2937321d11c", + "zh:b8acf6bb34278749f9032b32353b3609017f76cb166f27ee409b7b81bd7cbaa7", + "zh:bf622c05dce5ae0154afe5482aaee29aa86f1dfb83e1150185f255704632955f", + "zh:c302140b8bc2d4cc68c0ac33b0095cef979203ac8f911038535a8f2f4460f069", + "zh:dbfc1059858424f968e59ab2f801f120b0240045543256580a666506921255d1", + "zh:e54eb9bd55a88e556205f26e03cda9001ca26a2f8277bba5399911292b937e85", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", ] } provider "registry.terraform.io/hashicorp/google-beta" { - version = "5.25.0" - constraints = ">= 4.50.0, 5.25.0, < 6.0.0" + version = "5.31.0" + constraints = ">= 4.50.0, 5.31.0, < 6.0.0" hashes = [ - "h1:Mv3mcVqxIwydpgrxPIygBgA/lohis8JAKLQmHHpDjRc=", - "zh:026a603108b644f7ec49ed1449f888dc81fad03ed1fa5f9438ce8fa5cf24fd61", - "zh:23c5f0825b022a90bc112ab2404f38d4f6d274d3e311c664c48e2ec47581fb44", - "zh:310920543ed8d9bac667ecf59f1e9f9ec51f8f9fae300ca4cffa535037267394", - "zh:3d36ba55035a30676f58520c361fd48dae7b52a18f442beb6df18eb0454446a6", - "zh:43d4a3208c4d8d0077a09b41750ef5a2d2fd73e6d6146c045562eb7d4f93e22a", - "zh:4af9a74184578295b972780912c17f339856c2463ff19b6ce4e41ae95ec306f3", - "zh:6dd52843632a3852c99fa72987d7431cbf616a44bf18a75fe0fba5b0ef926bbe", - "zh:850361c1affafacf37640f7b5564f928d2faff13b944dbacc633c6d7ea937ab1", - "zh:e8436bb4ab745e6a40dba5e588c1c78012daf8829a7e22cfba4db5959306ec45", - "zh:f5461262023eb54882ab17541240241e1d343e50f11144f9c4f8db1603fb622f", + "h1:sIXAK1wOIAa7JI4Rrud730rDC3C1+WJl73HOZym7uag=", + "zh:11b968dcc9ff336bc39809acb551aca6b385a987953225f1c29170bc85e81a6c", + "zh:2f62f0ef17257002d49e1960ec96ffee9ebd6463464d06708a7fa88812e1cf7b", + "zh:3a9e41ee9bb4ef152b2a33b6594a425b707b4162ba895a676521cc9a889e5fe4", + "zh:54a4e3069f271fd26d754974638e474ae043ae3ac3641f20af6b3e03e4ea59a9", + "zh:693fe6422de6e4e92b22ba068f74cdde9f511f5c44c21cbc9f230dc84f0e6032", + "zh:6a8470581da507637c41775d85196838fd4c2180e8f9cf8a4534110fad12a3b8", + "zh:85f3053c36c31954ba63ca533899f626755fbe5a0aff3d7e933f528ca78cf125", + "zh:905894711185a1e5719be16f59661d32e05273d82db85deafa1911f1d72d90e5", + "zh:91b53cf9548fae4faeea140b361c0f70735be096bd4ce6feff49f49f48e76b3d", + "zh:9323ec53602ce118502256b102c28bcdd8ccfc2e4674964c4ace65f32aa958ae", + "zh:f307ca2b7818b2edfcdc07082ac31ec25eca3e2800b71aed3c36668fa4a55aa3", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", - "zh:ff114643711f72ae03ae24e3bdbd118d360c38364b7d482006141d05ab4d9696", ] } diff --git a/Makefile b/Makefile index ff69d391a..b7fa0812b 100644 --- a/Makefile +++ b/Makefile @@ -122,4 +122,11 @@ switch-env: @ printf "Switching from `tput setaf 1``tput bold`$(shell cat .last_used_env)`tput sgr0` to `tput setaf 2``tput bold`$(ENV)`tput sgr0`\n\n" @ echo $(ENV) > .last_used_env @ . .env.${ENV} - terraform init -input=false -reconfigure -backend-config="bucket=${TERRAFORM_STATE_BUCKET}" + terraform init -input=false -upgrade -reconfigure -backend-config="bucket=${TERRAFORM_STATE_BUCKET}" + +# Shortcut to importing resources into Terraform state (e.g. after creating resources manually or switching between different branches for the same environment) +.PHONY: import +import: + @ printf "Importing resources for env: `tput setaf 2``tput bold`$(ENV)`tput sgr0`\n\n" + ./scripts/confirm.sh $(ENV) + $(tf_vars) terraform import $(TARGET) $(ID) diff --git a/main.tf b/main.tf index 155ef9797..843720b04 100644 --- a/main.tf +++ b/main.tf @@ -10,11 +10,11 @@ terraform { } google = { source = "hashicorp/google" - version = "5.25.0" + version = "5.31.0" } google-beta = { source = "hashicorp/google-beta" - version = "5.25.0" + version = "5.31.0" } cloudflare = { source = "cloudflare/cloudflare" diff --git a/packages/api/main.tf b/packages/api/main.tf index 2698b120a..517cc4bdc 100644 --- a/packages/api/main.tf +++ b/packages/api/main.tf @@ -6,7 +6,7 @@ terraform { } google = { source = "hashicorp/google" - version = "5.25.0" + version = "5.31.0" } random = { source = "hashicorp/random" diff --git a/packages/cluster/network/main.tf b/packages/cluster/network/main.tf index d62417366..65f9f6bf0 100644 --- a/packages/cluster/network/main.tf +++ b/packages/cluster/network/main.tf @@ -273,6 +273,8 @@ resource "google_compute_backend_service" "default" { load_balancing_scheme = "EXTERNAL_MANAGED" health_checks = [google_compute_health_check.default[each.key].self_link] + security_policy = google_compute_security_policy.default[each.key].self_link + log_config { enable = true } @@ -339,6 +341,23 @@ resource "google_compute_health_check" "default" { } } + +resource "google_compute_security_policy" "default" { + provider = google-beta + for_each = local.health_checked_backends + name = "${var.prefix}${each.key}" + + dynamic "adaptive_protection_config" { + for_each = each.key == "api" ? [true] : [] + + content { + layer_7_ddos_defense_config { + enable = true + } + } + } +} + resource "google_compute_firewall" "default-hc" { name = "${var.prefix}load-balancer-hc" network = var.network_name @@ -383,6 +402,7 @@ module "gce_lb_http_logs" { affinity_cookie_ttl_sec = null custom_request_headers = null custom_response_headers = null + security_policy = google_compute_security_policy.disable-bots-log-collector.self_link health_check = { check_interval_sec = null @@ -453,3 +473,172 @@ resource "google_compute_firewall" "orch_firewall_egress" { direction = "EGRESS" target_tags = [var.cluster_tag_name] } + + +# Security policy +resource "google_compute_security_policy_rule" "api-throttling-api-key" { + security_policy = google_compute_security_policy.default["api"].name + provider = google-beta + action = "throttle" + priority = "300" + match { + expr { + expression = "request.path == \"/sandboxes\" && request.method == \"POST\"" + } + } + + rate_limit_options { + conform_action = "allow" + exceed_action = "deny(429)" + + enforce_on_key_configs { + enforce_on_key_name = "X-API-Key" + enforce_on_key_type = "HTTP_HEADER" + } + + rate_limit_threshold { + count = 50 + interval_sec = 30 + } + } + + description = "Sandbox creation per API key" +} + + +resource "google_compute_security_policy_rule" "api-throttling-ip" { + security_policy = google_compute_security_policy.default["api"].name + provider = google-beta + action = "throttle" + priority = "500" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + + rate_limit_options { + conform_action = "allow" + exceed_action = "deny(429)" + + enforce_on_key = "" + + enforce_on_key_configs { + enforce_on_key_type = "IP" + } + + rate_limit_threshold { + count = 2000 + interval_sec = 60 + } + } + + description = "Requests to API from IP address" +} + +resource "google_compute_security_policy_rule" "sandbox-throttling-host" { + security_policy = google_compute_security_policy.default["session"].name + provider = google-beta + description = "WS envd connection requests per sandbox" + + action = "throttle" + priority = "300" + match { + expr { + expression = "request.path == \"/ws\"" + } + } + + rate_limit_options { + conform_action = "allow" + exceed_action = "deny(429)" + + enforce_on_key_configs { + enforce_on_key_name = "host" + enforce_on_key_type = "HTTP_HEADER" + } + + rate_limit_threshold { + count = 40 + interval_sec = 30 + } + } +} + +resource "google_compute_security_policy_rule" "sandbox-throttling-ip" { + security_policy = google_compute_security_policy.default["session"].name + provider = google-beta + action = "throttle" + priority = "500" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + + rate_limit_options { + conform_action = "allow" + exceed_action = "deny(429)" + + enforce_on_key = "" + + enforce_on_key_configs { + enforce_on_key_type = "IP" + } + + rate_limit_threshold { + count = 2000 + interval_sec = 60 + } + } + + description = "Requests to sandboxes from IP address" +} + +resource "google_compute_security_policy_rule" "disable-consul" { + security_policy = google_compute_security_policy.default["consul"].name + provider = google-beta + action = "deny(403)" + priority = "1" + description = "Disable all requests to Consul" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } +} + + + +resource "google_compute_security_policy" "disable-bots-log-collector" { + name = "disable-bots-log-collector" + provider = google-beta + + rule { + action = "allow" + priority = "300" + match { + expr { + expression = "request.path == \"/\" && request.method == \"POST\"" + } + } + + description = "Allow POST requests to / (collecting logs)" + } + + rule { + action = "deny(403)" + priority = "2147483647" + description = "Default rule, higher priority overrides it" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + } +} +