diff --git a/README.md b/README.md index 7d26fd7..9a4d4d7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Cloud Armor Terraform Module -This module makes it easy to setup [Cloud Armor global Security Policy](https://cloud.google.com/armor/docs/cloud-armor-overview#security_policies) with Security rules. You can attach the global Security Policy policy to backend services exposed by the following load balancer types: +This module makes it easy to setup [Cloud Armor global Security Policy](https://cloud.google.com/armor/docs/security-policy-overview#expandable-1) with Security rules. You can attach the global Security policy to the backend services exposed by the following load balancer types: - Global external Application Load Balancer (HTTP/HTTPS) - Classic Application Load Balancer (HTTP/HTTPS) - Global external proxy Network Load Balancer (TCP/SSL) diff --git a/modules/advanced-network-ddos-protection/README.md b/modules/advanced-network-ddos-protection/README.md index 8e2611b..76490ea 100644 --- a/modules/advanced-network-ddos-protection/README.md +++ b/modules/advanced-network-ddos-protection/README.md @@ -18,8 +18,8 @@ module "advanced_network_ddos_protection" { source = "GoogleCloudPlatform/cloud-armor/google//modules/advanced-network-ddos-protection" version = "~> 2.2" - project_id = var.project_id - adv_ddos_policy_regions = ["us-central1", "us-east1"] + project_id = var.project_id + regions = ["us-central1", "us-east1"] } ``` @@ -29,13 +29,13 @@ module "advanced_network_ddos_protection" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| ddos\_protection\_config | Configuration for Google Cloud Armor DDOS Proctection Config. 1) ADVANCED: additional protections for Managed Protection Plus subscribers 2) ADVANCED\_PREVIEW: flag to enable the security policy in preview mode | `string` | `"ADVANCED"` | no | +| ddos\_protection\_config | Configuration for Google Cloud Armor DDOS Proctection Config. 1) ADVANCED: additional protections for Managed Protection Plus subscribers 2) ADVANCED\_PREVIEW: enable the security policy in preview mode | `string` | `"ADVANCED"` | no | | network\_edge\_security\_service\_description | description of edge security service for advanced network ddos protection | `string` | `"edge security service for advanced network ddos protection"` | no | | network\_edge\_security\_service\_name | Name of network edge security service resource for advanced network ddos protection | `string` | `"adv-network-ddos-protection"` | no | | policy\_description | An optional description of advanced network ddos protection security policy | `string` | `"CA Advance DDoS protection"` | no | | policy\_name | Name of the advanced network ddos protection security policy. Name must be 1-63 characters long and match the regular expression a-z? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash | `string` | `"adv-network-ddos-protection"` | no | | project\_id | The project in which the resource belongs. | `string` | n/a | yes | -| regions | The regions in which enable advanced network DDoS protection | `list(string)` | n/a | yes | +| regions | The regions in which advanced network DDoS protection will be activated | `list(string)` | n/a | yes | ## Outputs diff --git a/modules/advanced-network-ddos-protection/variables.tf b/modules/advanced-network-ddos-protection/variables.tf index b26162a..6207ca0 100644 --- a/modules/advanced-network-ddos-protection/variables.tf +++ b/modules/advanced-network-ddos-protection/variables.tf @@ -20,12 +20,12 @@ variable "project_id" { } variable "regions" { - description = "The regions in which enable advanced network DDoS protection" + description = "The regions in which advanced network DDoS protection will be activated" type = list(string) } variable "ddos_protection_config" { - description = "Configuration for Google Cloud Armor DDOS Proctection Config. 1) ADVANCED: additional protections for Managed Protection Plus subscribers 2) ADVANCED_PREVIEW: flag to enable the security policy in preview mode" + description = "Configuration for Google Cloud Armor DDOS Proctection Config. 1) ADVANCED: additional protections for Managed Protection Plus subscribers 2) ADVANCED_PREVIEW: enable the security policy in preview mode" type = string default = "ADVANCED" } diff --git a/modules/network-edge-security-policy/README.md b/modules/network-edge-security-policy/README.md index 4820b1c..5d296bd 100644 --- a/modules/network-edge-security-policy/README.md +++ b/modules/network-edge-security-policy/README.md @@ -125,7 +125,7 @@ resource "google_compute_region_backend_service" "backend" { | policy\_rules | Policy Rules |
list(object({| `null` | no | | policy\_user\_defined\_fields | Definitions of user-defined fields for CLOUD\_ARMOR\_NETWORK policies. A user-defined field consists of up to 4 bytes extracted from a fixed offset in the packet, relative to the IPv4, IPv6, TCP, or UDP header, with an optional mask to select certain bits |
priority = number
action = string
preview = optional(bool)
description = optional(string)
ip_protocols = optional(list(string))
src_ip_ranges = optional(list(string))
src_asns = optional(list(string))
src_region_codes = optional(list(string))
src_ports = optional(list(string))
dest_ports = optional(list(string))
dest_ip_ranges = optional(list(string))
user_defined_fields = optional(list(object({
name = optional(string)
values = optional(list(string))
})))
}))
list(object({| `null` | no | | project\_id | The project in which the resource belongs. | `string` | n/a | yes | -| region | The region in which enablesecurity policy is created | `string` | n/a | yes | +| region | The region in which security policy is created | `string` | n/a | yes | ## Outputs diff --git a/modules/network-edge-security-policy/variables.tf b/modules/network-edge-security-policy/variables.tf index 03528d6..0cf0309 100644 --- a/modules/network-edge-security-policy/variables.tf +++ b/modules/network-edge-security-policy/variables.tf @@ -20,7 +20,7 @@ variable "project_id" { } variable "region" { - description = "The region in which enablesecurity policy is created" + description = "The region in which security policy is created" type = string } diff --git a/modules/regional-backend-security-policy/README.md b/modules/regional-backend-security-policy/README.md new file mode 100644 index 0000000..57af1e5 --- /dev/null +++ b/modules/regional-backend-security-policy/README.md @@ -0,0 +1,238 @@ +# Cloud Armor Terraform Module for Network Edge Security Policy +This module creates [network edge security policy](https://cloud.google.com/armor/docs/network-edge-policies) in specified region. Network edge security policy is only availalable to projects enrolled in [Cloud Armor Enterprise](https://cloud.google.com/armor/docs/armor-enterprise-overview) with [Advanced network DDoS protection](https://cloud.google.com/armor/docs/advanced-network-ddos#activate-advanced-ddos-protection) enabled. You can use [this sub-module](../advanced-network-ddos-protection/) to enable `advanced network ddos protection `. + +You can attch network edge security policy to backend services of [external passthrough Network Load Balancers](https://cloud.google.com/load-balancing/docs/network). Network edge security policy supports [byte offset filtering](https://cloud.google.com/armor/docs/network-edge-policies#byte-offset). This module creates security policy of type `CLOUD_ARMOR_NETWORK` optionally attach security policy rules to the policy. + +## Module Format + +``` +module "network_edge_security_policy" { + source = "GoogleCloudPlatform/cloud-armor/google//modules/network-edge-security-policy" + version = "~> 2.2" + + project_id = var.project_id + region = "us-central1" + policy_name = "test-nw-edge-security-policy" + + policy_user_defined_fields = [ + {}, + {}, + ] + + policy_rules = [ + {}, + {}, + ] +} +``` + +`policy_rules` details and Sample Code for each type of rule is available [here](#Rules) + +## Usage +There are examples included in the [examples](https://github.com/GoogleCloudPlatform/terraform-google-cloud-armor/tree/main/examples) folder but simple usage is as follows: + + +``` +module "network_edge_security_policy" { + source = "GoogleCloudPlatform/cloud-armor/google//modules/network-edge-security-policy" + version = "~> 2.0" + + project_id = var.project_id + region = "us-central1" + policy_name = "test-nw-edge-security-policy" + + policy_user_defined_fields = [ + { + name = "SIG1_AT_0" + base = "UDP" + offset = 8 + size = 2 + mask = "0x8F00" + }, + { + name = "SIG2_AT_8" + base = "TCP" + offset = 16 + size = 4 + mask = "0xFFFFFFFF" + }, + ] + + policy_rules = [ + { + priority = 100 + action = "deny" + preview = true + description = "custom rule 100" + src_ip_ranges = ["10.10.0.0/16"] + src_asns = [15169] + src_region_codes = ["AU"] + ip_protocols = ["TCP"] + src_ports = [80] + dest_ports = ["8080"] + dest_ip_ranges = ["10.100.0.0/16"] + user_defined_fields = [ + { + name = "SIG1_AT_0" + values = ["0x8F00"] + }, + ] + }, + { + priority = 200 + action = "deny" + preview = false + priority = 200 + src_asns = [15269] + dest_ports = ["80"] + dest_ip_ranges = ["10.100.0.0/16"] + }, + ] +} + +## Backnd service to attach the security policy +resource "google_compute_region_backend_service" "backend" { + provider = google-beta + + ## Attach Cloud Armor policy to the backend service + security_policy = module.network_edge_security_policy.security_policy.self_link + + project = var.project_id + name = "ca-website-backend-svc" + region = local.primary_region + load_balancing_scheme = "EXTERNAL" + health_checks = [google_compute_region_health_check.default.id] + backend { + group = google_compute_instance_group.ca_vm_1_ig.self_link + } + + log_config { + enable = true + sample_rate = 0.5 + } +} + +``` + + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| custom\_rules | Custome security rules |
name = optional(string)
base = string
offset = optional(number)
size = optional(number)
mask = optional(string)
}))
map(object({| `{}` | no | +| policy\_description | An optional description of advanced network ddos protection security policy | `string` | `"CA Advance DDoS protection"` | no | +| policy\_name | Name of the advanced network ddos protection security policy. Name must be 1-63 characters long and match the regular expression a-z? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash | `string` | `"adv-network-ddos-protection"` | no | +| pre\_configured\_rules | Map of pre-configured rules with Sensitivity levels. preconfigured\_waf\_config\_exclusion is obsolete and available for backward compatibility. Use preconfigured\_waf\_config\_exclusions which allows multiple exclusions |
action = string
priority = number
description = optional(string)
preview = optional(bool, false)
expression = string
redirect_type = optional(string, null)
redirect_target = optional(string, null)
rate_limit_options = optional(object({
enforce_on_key = optional(string)
enforce_on_key_name = optional(string)
enforce_on_key_configs = optional(list(object({
enforce_on_key_name = optional(string)
enforce_on_key_type = optional(string)
})))
exceed_action = optional(string)
rate_limit_http_request_count = optional(number)
rate_limit_http_request_interval_sec = optional(number)
ban_duration_sec = optional(number)
ban_http_request_count = optional(number)
ban_http_request_interval_sec = optional(number)
}),
{})
header_action = optional(list(object({
header_name = optional(string)
header_value = optional(string)
})), [])
preconfigured_waf_config_exclusions = optional(map(object({
target_rule_set = string
target_rule_ids = optional(list(string), [])
request_header = optional(list(object({
operator = string
value = optional(string)
})))
request_cookie = optional(list(object({
operator = string
value = optional(string)
})))
request_uri = optional(list(object({
operator = string
value = optional(string)
})))
request_query_param = optional(list(object({
operator = string
value = optional(string)
})))
})), null)
}))
map(object({| `{}` | no | +| project\_id | The project in which the resource belongs. | `string` | n/a | yes | +| region | The region in which security policy is created | `string` | n/a | yes | +| security\_rules | Map of Security rules with list of IP addresses to block or unblock. |
action = string
priority = number
description = optional(string)
preview = optional(bool, false)
redirect_type = optional(string, null)
redirect_target = optional(string, null)
target_rule_set = string
sensitivity_level = optional(number, 4)
include_target_rule_ids = optional(list(string), [])
exclude_target_rule_ids = optional(list(string), [])
rate_limit_options = optional(object({
enforce_on_key = optional(string)
enforce_on_key_name = optional(string)
enforce_on_key_configs = optional(list(object({
enforce_on_key_name = optional(string)
enforce_on_key_type = optional(string)
})))
exceed_action = optional(string)
rate_limit_http_request_count = optional(number)
rate_limit_http_request_interval_sec = optional(number)
ban_duration_sec = optional(number)
ban_http_request_count = optional(number)
ban_http_request_interval_sec = optional(number)
}), {})
header_action = optional(list(object({
header_name = optional(string)
header_value = optional(string)
})), [])
preconfigured_waf_config_exclusions = optional(map(object({
target_rule_set = string
target_rule_ids = optional(list(string), [])
request_header = optional(list(object({
operator = string
value = optional(string)
})))
request_cookie = optional(list(object({
operator = string
value = optional(string)
})))
request_uri = optional(list(object({
operator = string
value = optional(string)
})))
request_query_param = optional(list(object({
operator = string
value = optional(string)
})))
})), null)
}))
map(object({| `{}` | no | +| type | Type indicates the intended use of the security policy. Possible values are CLOUD\_ARMOR and CLOUD\_ARMOR\_EDGE. | `string` | `"CLOUD_ARMOR"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| security\_policy | Regional network Security policy created | + + + +## policy_user_defined_fields + +Definitions of user-defined fields for CLOUD_ARMOR_NETWORK policies. A user-defined field consists of up to 4 bytes extracted from a fixed offset in the packet, relative to the IPv4, IPv6, TCP, or UDP header, with an optional mask to select certain bits. Rules may then specify matching values for these fields + +- `name`: (Optional) The name of this field. Must be unique within the policy +- `base`: (Required) The base relative to which 'offset' is measured. Possible values are: + - `IPV4`: Points to the beginning of the IPv4 header + - `IPV6`: Points to the beginning of the IPv6 header + - `TCP`: Points to the beginning of the TCP header, skipping over any IPv4 options or IPv6 extension headers. Not present for non-first fragments + - `UDP`: Points to the beginning of the UDP header, skipping over any IPv4 options or IPv6 extension headers. Not present for non-first fragments. Possible values are: IPV4, IPV6, TCP, UDP +- `offset`: (Optional) Offset of the first byte of the field (in network byte order) relative to 'base' +- `size`: (Optional) Size of the field in bytes. Valid values: 1-4 +- `mask`: (Optional) If specified, apply this mask (bitwise AND) to the field to ignore bits before matching. Encoded as a hexadecimal number (starting with "0x"). The last byte of the field (in network byte order) corresponds to the least significant byte of the mask + + +## policy_rules + +`policy_rules` is a list of objects with following parameters: +- `priority`: An integer indicating the priority of a rule in the list. The priority must be a positive value between 0 and 2147483647. Rules are evaluated from highest to lowest priority where 0 is the highest priority and 2147483647 is the lowest priority +- `action`: The Action to perform when the rule is matched. The following are the valid actions: + - allow: allow access to target + - deny(STATUS): deny access to target, returns the HTTP response code specified. Valid values for STATUS are 403, 404, and 502 +- `preview`: If set to true, the specified action is not enforced +- `description`: An optional description of this resource. Provide this property when you create the resource +- `src_ip_ranges`: list of source IPv4/IPv6 addresses or CIDR prefixes, in standard text format +- `src_asns`: list of BGP Autonomous System Number associated with the source IP address +- `src_region_codes`: list of Two-letter ISO 3166-1 alpha-2 country code associated with the source IP address +- `ip_protocols`: list of IPv4 protocol / IPv6 next header (after extension headers). Each element can be an 8-bit unsigned decimal number (e.g. "6"), range (e.g. "253-254"), or one of the following protocol names: "tcp", "udp", "icmp", "esp", "ah", "ipip", or "sctp" +- `src_ports`: Source port numbers for TCP/UDP/SCTP. Each element can be a 16-bit unsigned decimal number (e.g. "80") or range (e.g. "0-1023") +- `dest_ports`: Destination port numbers for TCP/UDP/SCTP. Each element can be a 16-bit unsigned decimal number (e.g. "80") or range (e.g. "0-1023") +- `dest_ip_ranges`: Destination IPv4/IPv6 addresses or CIDR prefixes, in standard text format +- `user_defined_fields`:User-defined fields. Each element names a defined field and lists the matching values for that field. Support following fields: + - `name`: Name of the user-defined field, as given in the definition + - `values`: Matching values of the field. Each element can be a 32-bit unsigned decimal or hexadecimal (starting with "0x") number (e.g. "64") or range (e.g. "0x400-0x7ff") + +### Format: + +``` +[ + { + priority = 100 + action = "deny" + preview = true + description = "custom rule 100" + src_ip_ranges = ["10.10.0.0/16"] + src_asns = [15169] + src_region_codes = ["AU"] + ip_protocols = ["TCP"] + src_ports = [80] + dest_ports = ["8080"] + dest_ip_ranges = ["10.100.0.0/16"] + user_defined_fields = [ + {}, + ] + }, +] +``` + + +### Sample: + +``` + policy_rules = [ + { + priority = 100 + action = "deny" + preview = true + description = "custom rule 100" + src_ip_ranges = ["10.10.0.0/16"] + src_asns = [15169] + src_region_codes = ["AU"] + ip_protocols = ["TCP"] + src_ports = [80] + dest_ports = ["8080"] + dest_ip_ranges = ["10.100.0.0/16"] + user_defined_fields = [ + { + name = "SIG1_AT_0" + values = ["0x8F00"] + }, + ] + }, + { + priority = 200 + action = "deny" + preview = false + priority = 200 + src_asns = [15269] + dest_ports = ["80"] + dest_ip_ranges = ["10.100.0.0/16"] + }, + ] +``` + +## policy_rules.user_defined_fields +User-defined fields. Each element names a defined field and lists the matching values for that field + +- `name`: (Optional) Name of the user-defined field, as given in the definition +- `values`: (Optional) Matching values of the field. Each element can be a 32-bit unsigned decimal or hexadecimal (starting with "0x") number (e.g. "64") or range (e.g. "0x400-0x7ff") diff --git a/modules/regional-backend-security-policy/main.tf b/modules/regional-backend-security-policy/main.tf new file mode 100644 index 0000000..2a99400 --- /dev/null +++ b/modules/regional-backend-security-policy/main.tf @@ -0,0 +1,83 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +### Adding custom rules to network dge security policies requires advanced network DDoS protection to be enabled in the region. + +resource "google_compute_region_security_policy" "security_policy" { + provider = google-beta + project = var.project_id + name = var.policy_name + description = var.policy_description + type = var.type + region = var.region +} + +resource "google_compute_region_security_policy_rule" "security_rules" { + provider = google-beta + for_each = var.security_rules == null ? {} : { for x in var.security_rules : x.priority => x } + project = var.project_id + region = var.region + security_policy = google_compute_region_security_policy.security_policy.name + + action = rule.value["action"] + priority = rule.value["priority"] + preview = rule.value["preview"] + description = rule.value["description"] + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = rule.value["src_ip_ranges"] + } + } + + ### Rate limit. Execute only if Action is "rate_based_ban" or "throttle" + dynamic "rate_limit_options" { + for_each = rule.value["action"] == "rate_based_ban" || rule.value["action"] == "throttle" ? ["rate_limits"] : [] + content { + conform_action = "allow" + ban_duration_sec = rule.value["action"] == "rate_based_ban" ? lookup(rule.value["rate_limit_options"], "ban_duration_sec") : null + exceed_action = lookup(rule.value["rate_limit_options"], "exceed_action") + enforce_on_key = lookup(rule.value["rate_limit_options"], "enforce_on_key_configs") == null ? lookup(rule.value["rate_limit_options"], "enforce_on_key", null) : "" + enforce_on_key_name = lookup(rule.value["rate_limit_options"], "enforce_on_key_configs") == null ? lookup(rule.value["rate_limit_options"], "enforce_on_key_name", null) : null + + dynamic "enforce_on_key_configs" { + for_each = lookup(rule.value["rate_limit_options"], "enforce_on_key_configs") == null ? {} : { for x in lookup(rule.value["rate_limit_options"], "enforce_on_key_configs") : x.enforce_on_key_type => x } + content { + enforce_on_key_type = enforce_on_key_configs.value.enforce_on_key_type + enforce_on_key_name = enforce_on_key_configs.value.enforce_on_key_name + } + } + + ## Required for all rate limit options + dynamic "rate_limit_threshold" { + for_each = rule.value["action"] == "rate_based_ban" || rule.value["action"] == "throttle" ? ["rate_limit_options"] : [] + content { + count = rule.value["rate_limit_options"].rate_limit_http_request_count + interval_sec = rule.value["rate_limit_options"].rate_limit_http_request_interval_sec + } + } + + ## Optional. Can be provided for for rate based ban. Not needed for throttle + dynamic "ban_threshold" { + for_each = rule.value["action"] == "rate_based_ban" && lookup(rule.value["rate_limit_options"], "ban_http_request_count", null) != null && lookup(rule.value["rate_limit_options"], "ban_http_request_interval_sec", null) != null ? ["ban_threshold"] : [] + content { + count = lookup(rule.value["rate_limit_options"], "ban_http_request_count") + interval_sec = lookup(rule.value["rate_limit_options"], "ban_http_request_interval_sec") + } + } + } + } +} diff --git a/modules/regional-backend-security-policy/outputs.tf b/modules/regional-backend-security-policy/outputs.tf new file mode 100644 index 0000000..be002d8 --- /dev/null +++ b/modules/regional-backend-security-policy/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +output "security_policy" { + value = google_compute_region_security_policy.security_policy + description = "Regional network Security policy created" +} + +# output "policy_rules" { +# value = google_compute_region_security_policy_rule.policy_rules +# description = "Security policy rules created" +# } diff --git a/modules/regional-backend-security-policy/variables.tf b/modules/regional-backend-security-policy/variables.tf new file mode 100644 index 0000000..4da1ac3 --- /dev/null +++ b/modules/regional-backend-security-policy/variables.tf @@ -0,0 +1,214 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +variable "project_id" { + description = "The project in which the resource belongs." + type = string +} + +variable "region" { + description = "The region in which security policy is created" + type = string +} + +variable "policy_name" { + description = "Name of the advanced network ddos protection security policy. Name must be 1-63 characters long and match the regular expression a-z? which means the first character must be a lowercase letter, and all following characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash" + type = string + default = "adv-network-ddos-protection" +} + +variable "type" { + description = "Type indicates the intended use of the security policy. Possible values are CLOUD_ARMOR and CLOUD_ARMOR_EDGE." + type = string + default = "CLOUD_ARMOR" +} + +variable "policy_description" { + description = "An optional description of advanced network ddos protection security policy" + type = string + default = "CA Advance DDoS protection" +} + +# variable "policy_rules" { +# description = "Policy Rules" +# type = list(object({ +# priority = number +# action = string +# preview = optional(bool) +# description = optional(string) +# ip_protocols = optional(list(string)) +# src_ip_ranges = optional(list(string)) +# src_asns = optional(list(string)) +# src_region_codes = optional(list(string)) +# src_ports = optional(list(string)) +# dest_ports = optional(list(string)) +# dest_ip_ranges = optional(list(string)) + +# user_defined_fields = optional(list(object({ +# name = optional(string) +# values = optional(list(string)) +# }))) +# })) +# default = null +# } + +variable "pre_configured_rules" { + description = "Map of pre-configured rules with Sensitivity levels. preconfigured_waf_config_exclusion is obsolete and available for backward compatibility. Use preconfigured_waf_config_exclusions which allows multiple exclusions" + type = map(object({ + action = string + priority = number + description = optional(string) + preview = optional(bool, false) + redirect_type = optional(string, null) + redirect_target = optional(string, null) + target_rule_set = string + sensitivity_level = optional(number, 4) + include_target_rule_ids = optional(list(string), []) + exclude_target_rule_ids = optional(list(string), []) + rate_limit_options = optional(object({ + enforce_on_key = optional(string) + enforce_on_key_name = optional(string) + enforce_on_key_configs = optional(list(object({ + enforce_on_key_name = optional(string) + enforce_on_key_type = optional(string) + }))) + exceed_action = optional(string) + rate_limit_http_request_count = optional(number) + rate_limit_http_request_interval_sec = optional(number) + ban_duration_sec = optional(number) + ban_http_request_count = optional(number) + ban_http_request_interval_sec = optional(number) + }), {}) + + header_action = optional(list(object({ + header_name = optional(string) + header_value = optional(string) + })), []) + + preconfigured_waf_config_exclusions = optional(map(object({ + target_rule_set = string + target_rule_ids = optional(list(string), []) + request_header = optional(list(object({ + operator = string + value = optional(string) + }))) + request_cookie = optional(list(object({ + operator = string + value = optional(string) + }))) + request_uri = optional(list(object({ + operator = string + value = optional(string) + }))) + request_query_param = optional(list(object({ + operator = string + value = optional(string) + }))) + })), null) + + })) + + default = {} +} + +variable "security_rules" { + description = "Map of Security rules with list of IP addresses to block or unblock." + type = map(object({ + action = string + priority = number + description = optional(string) + preview = optional(bool, false) + redirect_type = optional(string, null) + redirect_target = optional(string, null) + src_ip_ranges = list(string) + rate_limit_options = optional(object({ + enforce_on_key = optional(string) + enforce_on_key_name = optional(string) + enforce_on_key_configs = optional(list(object({ + enforce_on_key_name = optional(string) + enforce_on_key_type = optional(string) + }))) + exceed_action = optional(string) + rate_limit_http_request_count = optional(number) + rate_limit_http_request_interval_sec = optional(number) + ban_duration_sec = optional(number) + ban_http_request_count = optional(number) + ban_http_request_interval_sec = optional(number) + }), + {}) + header_action = optional(list(object({ + header_name = optional(string) + header_value = optional(string) + })), []) + })) + + default = {} +} + +variable "custom_rules" { + description = "Custome security rules" + type = map(object({ + action = string + priority = number + description = optional(string) + preview = optional(bool, false) + expression = string + redirect_type = optional(string, null) + redirect_target = optional(string, null) + rate_limit_options = optional(object({ + enforce_on_key = optional(string) + enforce_on_key_name = optional(string) + enforce_on_key_configs = optional(list(object({ + enforce_on_key_name = optional(string) + enforce_on_key_type = optional(string) + }))) + exceed_action = optional(string) + rate_limit_http_request_count = optional(number) + rate_limit_http_request_interval_sec = optional(number) + ban_duration_sec = optional(number) + ban_http_request_count = optional(number) + ban_http_request_interval_sec = optional(number) + }), + {}) + header_action = optional(list(object({ + header_name = optional(string) + header_value = optional(string) + })), []) + + preconfigured_waf_config_exclusions = optional(map(object({ + target_rule_set = string + target_rule_ids = optional(list(string), []) + request_header = optional(list(object({ + operator = string + value = optional(string) + }))) + request_cookie = optional(list(object({ + operator = string + value = optional(string) + }))) + request_uri = optional(list(object({ + operator = string + value = optional(string) + }))) + request_query_param = optional(list(object({ + operator = string + value = optional(string) + }))) + })), null) + + })) + default = {} +} diff --git a/modules/regional-backend-security-policy/versions.tf b/modules/regional-backend-security-policy/versions.tf new file mode 100644 index 0000000..6f9ea57 --- /dev/null +++ b/modules/regional-backend-security-policy/versions.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +terraform { + required_version = ">= 1.3.0" + required_providers { + google = { + source = "hashicorp/google" + version = ">= 5.29, < 6" + } + google-beta = { + source = "hashicorp/google-beta" + version = ">= 5.29, < 6" + } + } + provider_meta "google" { + module_name = "blueprints/terraform/terraform-google-cloud-armor:regional-backend-security-policy/v2.2.0" + } + provider_meta "google-beta" { + module_name = "blueprints/terraform/terraform-google-cloud-armor:regional-backend-security-policy/v2.2.0" + } +}
action = string
priority = number
description = optional(string)
preview = optional(bool, false)
redirect_type = optional(string, null)
redirect_target = optional(string, null)
src_ip_ranges = list(string)
rate_limit_options = optional(object({
enforce_on_key = optional(string)
enforce_on_key_name = optional(string)
enforce_on_key_configs = optional(list(object({
enforce_on_key_name = optional(string)
enforce_on_key_type = optional(string)
})))
exceed_action = optional(string)
rate_limit_http_request_count = optional(number)
rate_limit_http_request_interval_sec = optional(number)
ban_duration_sec = optional(number)
ban_http_request_count = optional(number)
ban_http_request_interval_sec = optional(number)
}),
{})
header_action = optional(list(object({
header_name = optional(string)
header_value = optional(string)
})), [])
}))