From 63bf9c03de1424e35f87ab0d6d10e32addd4b01d Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Tue, 2 Nov 2021 17:51:31 -0400 Subject: [PATCH 01/15] Add rate limit options for compute resource security policy rules --- .../resource_compute_security_policy.go.erb | 182 ++++++++++++++++-- ...source_compute_security_policy_test.go.erb | 43 +++++ 2 files changed, 214 insertions(+), 11 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 93889331f027..ff47b4fcf950 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -154,6 +154,98 @@ func resourceComputeSecurityPolicy() *schema.Resource { Computed: true, Description: `When set to true, the action specified above is not enforced. Stackdriver logs for requests that trigger a preview action are annotated as such.`, }, + + <% unless version == 'ga' -%> + "rate_limit_options": { + Type: schema.TypeList, + Optional: true, + Description: `Rate limit threshold for this security policy. Must be specified if the action is "rate_based_ban" or "throttle". Cannot be specified for any other actions.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "rate_limit_threshold": { + Type: schema.TypeList, + Optional: true, + Description: `Threshold at which to begin ratelimiting.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "count": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of HTTP(S) requests for calculating the threshold.`, + }, + + "interval_sec": { + Type: schema.TypeInt, + Optional: true, + Description: `Interval over which the threshold is computed.`, + }, + }, + }, + }, + + "conform_action": { + Type: schema.TypeString, + Optional: true, + Default: "allow", + ValidateFunc: validation.StringInSlice([]string{"deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), + Description: `When a request is denied, returns the HTTP response code specified. Valid options are "deny()" where valid values for status are 403, 404, 429, and 502.`, + }, + + "exceed_action": { + Type: schema.TypeString, + Optional: true, + Default: "deny-429", + ValidateFunc: validation.StringInSlice([]string{"allow"}, false), + Description: `Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only.`, + }, + + "enforce_on_key": { + Type: schema.TypeString, + Optional: true, + Default: "ALL", + ValidateFunc: validation.StringInSlice([]string{"ALL", "ALL_IPS", "HTTP_HEADER", "XFF_IP"}, false), + Description: `Determines the key to enforce the rateLimitThreshold on. Possible values are: "ALL" -- A single rate limit threshold is applied to all the requests matching this rule. This is the default value if this field 'enforceOnKey' is not configured. "ALL_IPS" -- This definition, equivalent to "ALL", has been depprecated. "IP" -- The source IP address of the request is the key. Each IP has this limit enforced separately. "HTTP_HEADER" -- The value of the HTTP Header whose name is configured under "enforceOnKeyName". The key value is truncated to the first 128 bytes of the Header value. If no such header is present in the request, the key type defaults to "ALL". "XFF_IP" -- The first IP address (i.e. the originating client IP address) specified in the list of IPs under X-Forwarded-For HTTP Header. If no such header is present or the value is not a valid IP, the key type defaults to "ALL".`, + }, + + "enforce_on_key_name": { + Type: schema.TypeString, + Optional: true, + Description: `Rate limit key name applicable only for the following key types: HTTP_HEADER -- Name of the HTTP Header whose value is taken as the key value.`, + }, + + "ban_threshold": { + Type: schema.TypeList, + Optional: true, + Description: `Can only be specified if the action for the rule is "rate_based_ban". If specified, the key will be banned for the configured 'banDurationSec' when the number of requests that exceed the 'rateLimitThreshold' also exceed this 'banThreshold'.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "count": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of HTTP(S) requests for calculating the threshold.`, + }, + + "interval_sec": { + Type: schema.TypeInt, + Optional: true, + Description: `Interval over which the threshold is computed.`, + }, + }, + }, + }, + + "ban_duration_sec": { + Type: schema.TypeInt, + Optional: true, + Description: `Can only be specified if the action for the rule is "rate_based_ban". If specified, determines the time (in seconds) the traffic will continue to be banned by the rate limit after the rate falls below the threshold.`, + }, + }, + }, + }, + <% end -%> }, }, Description: `The set of rules that belong to this policy. There must always be a default rule (rule with priority 2147483647 and match "*"). If no rules are provided when creating a security policy, a default rule with action "allow" will be added.`, @@ -497,12 +589,15 @@ func expandSecurityPolicyRules(configured []interface{}) []*compute.SecurityPoli func expandSecurityPolicyRule(raw interface{}) *compute.SecurityPolicyRule { data := raw.(map[string]interface{}) return &compute.SecurityPolicyRule{ - Description: data["description"].(string), - Priority: int64(data["priority"].(int)), - Action: data["action"].(string), - Preview: data["preview"].(bool), - Match: expandSecurityPolicyMatch(data["match"].([]interface{})), - ForceSendFields: []string{"Description", "Preview"}, + Description: data["description"].(string), + Priority: int64(data["priority"].(int)), + Action: data["action"].(string), + Preview: data["preview"].(bool), + Match: expandSecurityPolicyMatch(data["match"].([]interface{})), + <% unless version == 'ga' -%> + RateLimitOptions: expandSecurityPolicyRuleRateLimitOptions(data["rate_limit_options"].([]interface{})), + <% end -%> + ForceSendFields: []string{"Description", "Preview"}, } } @@ -549,11 +644,14 @@ func flattenSecurityPolicyRules(rules []*compute.SecurityPolicyRule) []map[strin rulesSchema := make([]map[string]interface{}, 0, len(rules)) for _, rule := range rules { data := map[string]interface{}{ - "description": rule.Description, - "priority": rule.Priority, - "action": rule.Action, - "preview": rule.Preview, - "match": flattenMatch(rule.Match), + "description": rule.Description, + "priority": rule.Priority, + "action": rule.Action, + "preview": rule.Preview, + "match": flattenMatch(rule.Match), + <% unless version == 'ga' -%> + "rateLimitOptions": flattenSecurityPolicyRuleRateLimitOptions(rule.RateLimitOptions), + <% end -%> } rulesSchema = append(rulesSchema, data) @@ -653,6 +751,68 @@ func flattenLayer7DdosDefenseConfig(conf *compute.SecurityPolicyAdaptiveProtecti } <% end -%> +<% unless version == 'ga' -%> +func expandSecurityPolicyRuleRateLimitOptions(configured []interface{}) *compute.SecurityPolicyRuleRateLimitOptions { + if len(configured) == 0 || configured[0] == nil { + return nil + } + + data := configured[0].(map[string]interface{}) + return &compute.SecurityPolicyRuleRateLimitOptions{ + BanThreshold: expandThreshold(data["ban_threshold"].([]interface{})), + RateLimitThreshold: expandThreshold(data["rate_limit_threshold"].([]interface{})), + ExceedAction: data["exceed_action"].(string), + ConformAction: data["conform_action"].(string), + EnforceOnKey: data["enforce_on_key"].(string), + EnforceOnKeyName: data["enforce_on_key_name"].(string), + BanDurationSec: data["ban_duration_sec"].(int), + } +} + +func expandThreshold(configured []interface{}) *compute.SecurityPolicyRuleRateLimitOptionsThreshold { + if len(configured) == 0 || configured[0] == nil { + return nil + } + + data := configured[0].(map[string]interface{}) + return &compute.SecurityPolicyRuleRateLimitOptionsThreshold{ + Count: data["count"].(int), + IntervalSec: data["interval_sec"].(int), + } +} + +func flattenSecurityPolicyRuleRateLimitOptions(conf *compute.SecurityPolicyRuleRateLimitOptions) []map[string]interface{} { + if conf == nil { + return nil + } + + data := map[string]interface{}{ + "ban_threshold": flattenThreshold(conf.Threshold), + "rate_limit_threshold": flattenThreshold(conf.Threshold), + "exceed_action": conf.ExceedAction, + "conform_action": conf.ConformAction, + "enforce_on_key": conf.EnforceOnKey, + "enforce_on_key_name": conf.EnforceOnKeyName, + "ban_duration_sec": conf.BanDurationSec, + } + + return []map[string]interface{}{data} +} + +func flattenThreshold(conf *compute.SecurityPolicyRuleRateLimitOptionsThreshold) []map[string]interface{} { + if conf == nil { + return nil + } + + data := map[string]interface{}{ + "count": conf.Count, + "interval_sec": conf.IntervalSec, + } + + return []map[string]interface{}{data} +} +<% end -%> + func resourceSecurityPolicyStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { config := meta.(*Config) if err := parseImportId([]string{"projects/(?P[^/]+)/global/securityPolicies/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config); err != nil { diff --git a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb index b2f10eab7b31..348e95c99d92 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb @@ -147,6 +147,30 @@ func TestAccComputeSecurityPolicy_withAdaptiveProtection(t *testing.T) { } <% end -%> +<% unless version == 'ga' -%> +func TestAccComputeSecurityPolicy_withRateLimitOptions(t *testing.T) { + t.Parallel() + + spName := fmt.Sprintf("tf-test-%s", randString(t, 10)) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeSecurityPolicy_withRateLimitOptions(spName), + }, + { + ResourceName: "google_compute_security_policy.policy", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +<% end -%> + func testAccCheckComputeSecurityPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { config := googleProviderConfig(t) @@ -356,3 +380,22 @@ resource "google_compute_security_policy" "policy" { `, spName) } <% end -%> + +<% unless version == 'ga' -%> +func testAccComputeSecurityPolicy_withRateLimitOptions(spName string) string { + return fmt.Sprintf(` +resource "google_compute_security_policy" "policy" { + name = "%s" + description = "updated description" + rate_limit_options { + exceed_action = "deny-429" + enforce_on_key = "IP" + rate_limit_threshold { + count = 100 + interval_sec = 60 + } + } +} +`, spName) +} +<% end -%> \ No newline at end of file From 3aa3dde35b227d9985bb66175934093acbfcfa72 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 3 Nov 2021 17:06:25 -0400 Subject: [PATCH 02/15] Update website docs to reflect support for rate_limit_options and corresponding field values --- .../r/compute_security_policy.html.markdown | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown index ce6a1d2623c7..71cb2d271a7b 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown @@ -83,6 +83,9 @@ The following arguments are supported: * `preview` - (Optional) When set to true, the `action` specified above is not enforced. Stackdriver logs for requests that trigger a preview action are annotated as such. +* `rate_limit_options` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) + Must be specified if the `action` is "rate_based_bad" or "throttle". Cannot be specified for other actions. Structure is [documented below](#nested_rate_limit_options). + The `match` block supports: * `config` - (Optional) The configuration options available when specifying `versioned_expr`. @@ -108,6 +111,32 @@ The following arguments are supported: * `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. The application context of the containing message determines which well-known feature set of CEL is supported. +The `rate_limit_options` block supports: + +* `ban_duration_sec` - (Optional) Can only be specified if the `action` for the rule is "rate_based_ban". + If specified, determines the time (in seconds) the traffic will continue to be banned by the ratelimit after the rate falls below the threshold. + +* `ban_threshold` - (Optional) Can only be specified if the `action` for the rule is "rate_based_ban". + If specified, the key will be banned for the configured 'ban_duration_sec' when the number of requests that exceed the 'rate_limit_threshold' also exceed this 'ban_threshold'. Structure is [documented below](#nested_threshold). + +* `conform_action` - (Optional) ConformAction: Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only. + +* `enforce_on_key` - (Optional) Determines the key to enforce the rate_limit_threshold on. + Possible values incude "ALL", "ALL_IPS", "HTTP_HEADER", "IP", "XFF_IP". If not specified, defaults to "ALL". + +* `enforce_on_key_name` - (Optional) Rate limit key name applicable only for HTTP_HEADER key types. Name of the HTTP header whose value is taken as the key value. + +* `exceed_action` - (Optional) When a request is denied, returns the HTTP response code specified. + Valid options are "deny()" where valid values for status are 403, 404, 429, and 502. + +* `rate_limit_threshold` - (Optional) Threshold at which to begin ratelimiting. Structure is [documented below](#nested_threshold). + +The `{ban/rate_limit}_threshold` block supports: + +* `count` - (Optional) Number of HTTP(S) requests for calculating the threshold. + +* `interval_sec` - (Optional) Interval over which the threshold is computed. + The `adaptive_protection_config` block supports: * `layer_7_ddos_defense_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Configuration for [Google Cloud Armor Adaptive Protection Layer 7 DDoS Defense](https://cloud.google.com/armor/docs/adaptive-protection-overview?hl=en). Structure is [documented below](#nested_layer_7_ddos_defense_config). From f3fc4b5668648361d26d8351eeff6432c9284f3d Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 3 Nov 2021 17:11:34 -0400 Subject: [PATCH 03/15] cleanup --- .../website/docs/r/compute_security_policy.html.markdown | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown index 71cb2d271a7b..445fbc19b8d6 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown @@ -114,12 +114,13 @@ The following arguments are supported: The `rate_limit_options` block supports: * `ban_duration_sec` - (Optional) Can only be specified if the `action` for the rule is "rate_based_ban". - If specified, determines the time (in seconds) the traffic will continue to be banned by the ratelimit after the rate falls below the threshold. + If specified, determines the time (in seconds) the traffic will continue to be banned by the rate limit after the rate falls below the threshold. * `ban_threshold` - (Optional) Can only be specified if the `action` for the rule is "rate_based_ban". - If specified, the key will be banned for the configured 'ban_duration_sec' when the number of requests that exceed the 'rate_limit_threshold' also exceed this 'ban_threshold'. Structure is [documented below](#nested_threshold). + If specified, the key will be banned for the configured 'ban_duration_sec' when the number of requests that exceed the 'rate_limit_threshold' also + exceed this 'ban_threshold'. Structure is [documented below](#nested_threshold). -* `conform_action` - (Optional) ConformAction: Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only. +* `conform_action` - (Optional) Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only. * `enforce_on_key` - (Optional) Determines the key to enforce the rate_limit_threshold on. Possible values incude "ALL", "ALL_IPS", "HTTP_HEADER", "IP", "XFF_IP". If not specified, defaults to "ALL". From 17bb57a164ea7dc4f00312dd31dd3a769b6fcbdf Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Tue, 16 Nov 2021 15:29:23 -0500 Subject: [PATCH 04/15] Address PR feedback and require rate_limit_threshold's count and interval_sec, as well as conform_action and exceed_action fields if opting to use rate_limit_options --- .../resources/resource_compute_security_policy.go.erb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index ff47b4fcf950..9e9bf86eb65e 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -165,7 +165,7 @@ func resourceComputeSecurityPolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "rate_limit_threshold": { Type: schema.TypeList, - Optional: true, + Required: true, Description: `Threshold at which to begin ratelimiting.`, MaxItems: 1, Elem: &schema.Resource{ @@ -187,16 +187,14 @@ func resourceComputeSecurityPolicy() *schema.Resource { "conform_action": { Type: schema.TypeString, - Optional: true, - Default: "allow", - ValidateFunc: validation.StringInSlice([]string{"deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), + Required: true, + ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), Description: `When a request is denied, returns the HTTP response code specified. Valid options are "deny()" where valid values for status are 403, 404, 429, and 502.`, }, "exceed_action": { Type: schema.TypeString, - Optional: true, - Default: "deny-429", + Required: true, ValidateFunc: validation.StringInSlice([]string{"allow"}, false), Description: `Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only.`, }, From 9210305c1861911dd3ffb947aaf174cfe652acb4 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 17 Nov 2021 14:21:18 -0500 Subject: [PATCH 05/15] Resolve compile errors --- .../resources/resource_compute_security_policy.go.erb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 9e9bf86eb65e..b5e12324d8e7 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -763,7 +763,7 @@ func expandSecurityPolicyRuleRateLimitOptions(configured []interface{}) *compute ConformAction: data["conform_action"].(string), EnforceOnKey: data["enforce_on_key"].(string), EnforceOnKeyName: data["enforce_on_key_name"].(string), - BanDurationSec: data["ban_duration_sec"].(int), + BanDurationSec: int64(data["ban_duration_sec"].(int)), } } @@ -774,8 +774,8 @@ func expandThreshold(configured []interface{}) *compute.SecurityPolicyRuleRateLi data := configured[0].(map[string]interface{}) return &compute.SecurityPolicyRuleRateLimitOptionsThreshold{ - Count: data["count"].(int), - IntervalSec: data["interval_sec"].(int), + Count: int64(data["count"].(int)), + IntervalSec: int64(data["interval_sec"].(int)), } } @@ -785,8 +785,8 @@ func flattenSecurityPolicyRuleRateLimitOptions(conf *compute.SecurityPolicyRuleR } data := map[string]interface{}{ - "ban_threshold": flattenThreshold(conf.Threshold), - "rate_limit_threshold": flattenThreshold(conf.Threshold), + "ban_threshold": flattenThreshold(conf.BanThreshold), + "rate_limit_threshold": flattenThreshold(conf.RateLimitThreshold), "exceed_action": conf.ExceedAction, "conform_action": conf.ConformAction, "enforce_on_key": conf.EnforceOnKey, From 9590f05031c6cd89cbdcfcfc39aef6933abac035 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 24 Nov 2021 10:54:28 -0500 Subject: [PATCH 06/15] Require both count and interval_sec values to be provided in rate_limit_threshold --- .../resources/resource_compute_security_policy.go.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index b5e12324d8e7..c9a01ee83687 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -172,13 +172,13 @@ func resourceComputeSecurityPolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "count": { Type: schema.TypeInt, - Optional: true, + Required: true, Description: `Number of HTTP(S) requests for calculating the threshold.`, }, "interval_sec": { Type: schema.TypeInt, - Optional: true, + Required: true, Description: `Interval over which the threshold is computed.`, }, }, From 71ac76c5337a803ff43b4d28a0470116b34e7714 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 24 Nov 2021 10:57:55 -0500 Subject: [PATCH 07/15] If ban_threshold is included, we require both count and interval_sec to be provided --- .../resources/resource_compute_security_policy.go.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index c9a01ee83687..cc51878cc0e1 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -222,13 +222,13 @@ func resourceComputeSecurityPolicy() *schema.Resource { Schema: map[string]*schema.Schema{ "count": { Type: schema.TypeInt, - Optional: true, + Required: true, Description: `Number of HTTP(S) requests for calculating the threshold.`, }, "interval_sec": { Type: schema.TypeInt, - Optional: true, + Required: true, Description: `Interval over which the threshold is computed.`, }, }, From ac12608df3502ed1645517d2f88eacb70d7b0b2f Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Tue, 7 Dec 2021 12:44:23 -0500 Subject: [PATCH 08/15] Change rateLimitOptions to rate_limit_options in flatten function Co-authored-by: Riley Karson --- .../terraform/resources/resource_compute_security_policy.go.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index cc51878cc0e1..c28c59ad0b34 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -648,7 +648,7 @@ func flattenSecurityPolicyRules(rules []*compute.SecurityPolicyRule) []map[strin "preview": rule.Preview, "match": flattenMatch(rule.Match), <% unless version == 'ga' -%> - "rateLimitOptions": flattenSecurityPolicyRuleRateLimitOptions(rule.RateLimitOptions), + "rate_limit_options": flattenSecurityPolicyRuleRateLimitOptions(rule.RateLimitOptions), <% end -%> } From f11f78ccdd04e4f8aa7c55572ff1a5dcebaed73d Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Fri, 10 Dec 2021 12:26:24 -0500 Subject: [PATCH 09/15] Update acceptable values for enforceOnKey and update unit test to provide all required fields --- .../resources/resource_compute_security_policy.go.erb | 4 ++-- .../tests/resource_compute_security_policy_test.go.erb | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index cc51878cc0e1..8ff8005cfd41 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -203,8 +203,8 @@ func resourceComputeSecurityPolicy() *schema.Resource { Type: schema.TypeString, Optional: true, Default: "ALL", - ValidateFunc: validation.StringInSlice([]string{"ALL", "ALL_IPS", "HTTP_HEADER", "XFF_IP"}, false), - Description: `Determines the key to enforce the rateLimitThreshold on. Possible values are: "ALL" -- A single rate limit threshold is applied to all the requests matching this rule. This is the default value if this field 'enforceOnKey' is not configured. "ALL_IPS" -- This definition, equivalent to "ALL", has been depprecated. "IP" -- The source IP address of the request is the key. Each IP has this limit enforced separately. "HTTP_HEADER" -- The value of the HTTP Header whose name is configured under "enforceOnKeyName". The key value is truncated to the first 128 bytes of the Header value. If no such header is present in the request, the key type defaults to "ALL". "XFF_IP" -- The first IP address (i.e. the originating client IP address) specified in the list of IPs under X-Forwarded-For HTTP Header. If no such header is present or the value is not a valid IP, the key type defaults to "ALL".`, + ValidateFunc: validation.StringInSlice([]string{"ALL", "IP", "HTTP_HEADER", "XFF_IP"}, false), + Description: `Determines the key to enforce the rateLimitThreshold on. Possible values are: "ALL" -- A single rate limit threshold is applied to all the requests matching this rule. This is the default value if this field 'enforceOnKey' is not configured. "IP" -- The source IP address of the request is the key. Each IP has this limit enforced separately. "HTTP_HEADER" -- The value of the HTTP Header whose name is configured under "enforceOnKeyName". The key value is truncated to the first 128 bytes of the Header value. If no such header is present in the request, the key type defaults to "ALL". "XFF_IP" -- The first IP address (i.e. the originating client IP address) specified in the list of IPs under X-Forwarded-For HTTP Header. If no such header is present or the value is not a valid IP, the key type defaults to "ALL".`, }, "enforce_on_key_name": { diff --git a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb index 348e95c99d92..dae4a99e213f 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb @@ -388,7 +388,8 @@ resource "google_compute_security_policy" "policy" { name = "%s" description = "updated description" rate_limit_options { - exceed_action = "deny-429" + conform_action = "allow" + exceed_action = "allow" enforce_on_key = "IP" rate_limit_threshold { count = 100 From 0f464ef08820684857239b476d7f450ae4c2b175 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Thu, 13 Jan 2022 18:06:24 -0500 Subject: [PATCH 10/15] Fix resource definition in unit test. Add rate_based_ban and threshold as possible action values for security policy rules --- .../resource_compute_security_policy.go.erb | 2 +- ...source_compute_security_policy_test.go.erb | 34 +++++++++++++------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 84f004300b40..1040433019ce 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -67,7 +67,7 @@ func resourceComputeSecurityPolicy() *schema.Resource { "action": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(502)"}, false), + ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(502)", "rate_based_ban", "threshold"}, false), Description: `Action to take when match matches the request. Valid values: "allow" : allow access to target, "deny(status)" : deny access to target, returns the HTTP response code specified (valid values are 403, 404 and 502)`, }, diff --git a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb index dae4a99e213f..18f0fb27ab66 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb @@ -385,17 +385,29 @@ resource "google_compute_security_policy" "policy" { func testAccComputeSecurityPolicy_withRateLimitOptions(spName string) string { return fmt.Sprintf(` resource "google_compute_security_policy" "policy" { - name = "%s" - description = "updated description" - rate_limit_options { - conform_action = "allow" - exceed_action = "allow" - enforce_on_key = "IP" - rate_limit_threshold { - count = 100 - interval_sec = 60 - } - } + name = "%s" + description = "updated description" + rule { + action = "throttle" + priority = 100 + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = [ + "0.0.0.0/32", + ] + } + } + rate_limit_options { + conform_action = "allow" + exceed_action = "allow" + enforce_on_key = "IP" + rate_limit_threshold { + count = 100 + interval_sec = 60 + } + } + } } `, spName) } From bfa88bc6a6370005faca83d552d6bd525dc1762a Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Thu, 13 Jan 2022 18:11:03 -0500 Subject: [PATCH 11/15] Update docs to add rate_based_ban and threshold as possible values for a rules action --- .../website/docs/r/compute_security_policy.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown index 445fbc19b8d6..6f039d16f2e5 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown @@ -71,6 +71,8 @@ The following arguments are supported: * `action` - (Required) Action to take when `match` matches the request. Valid values: * "allow" : allow access to target * "deny(status)" : deny access to target, returns the HTTP response code specified (valid values are 403, 404 and 502) + * "rate_based_ban" : limit client traffic to the configured threshold and ban the client if the traffic exceeds the threshold. Configure parameters for this action in RateLimitOptions. Requires rateLimitOptions to be set. + * "threshold" : limit client traffic to the configured threshold. Configure parameters for this action in rateLimitOptions. Requires rateLimitOptions to be set for this. * `priority` - (Required) An unique positive integer indicating the priority of evaluation for a rule. Rules are evaluated from highest priority (lowest numerically) to lowest priority (highest numerically) in order. From 97c46e2d97ff24ec59b50a8354945b5dd77cc61a Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 19 Jan 2022 10:39:22 -0500 Subject: [PATCH 12/15] Fixed typo --- .../terraform/resources/resource_compute_security_policy.go.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 1040433019ce..6aad523cea7b 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -67,7 +67,7 @@ func resourceComputeSecurityPolicy() *schema.Resource { "action": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(502)", "rate_based_ban", "threshold"}, false), + ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(502)", "rate_based_ban", "throttle"}, false), Description: `Action to take when match matches the request. Valid values: "allow" : allow access to target, "deny(status)" : deny access to target, returns the HTTP response code specified (valid values are 403, 404 and 502)`, }, From dac57c26b8646e2ddda8b3e38cd8fcebe7a81778 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Thu, 20 Jan 2022 12:12:39 -0500 Subject: [PATCH 13/15] Fix valid field values for exceed_action and conform_action. Add support for exceed_redirect_optionss --- .../resource_compute_security_policy.go.erb | 29 +++++++++++++++++-- ...source_compute_security_policy_test.go.erb | 2 +- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 6aad523cea7b..9179f6262c77 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -154,7 +154,7 @@ func resourceComputeSecurityPolicy() *schema.Resource { Computed: true, Description: `When set to true, the action specified above is not enforced. Stackdriver logs for requests that trigger a preview action are annotated as such.`, }, - + <% unless version == 'ga' -%> "rate_limit_options": { Type: schema.TypeList, @@ -188,14 +188,14 @@ func resourceComputeSecurityPolicy() *schema.Resource { "conform_action": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"allow", "deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), + ValidateFunc: validation.StringInSlice([]string{"allow"}, false), Description: `When a request is denied, returns the HTTP response code specified. Valid options are "deny()" where valid values for status are 403, 404, 429, and 502.`, }, "exceed_action": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringInSlice([]string{"allow"}, false), + ValidateFunc: validation.StringInSlice([]string{"redirect", "deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), Description: `Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only.`, }, @@ -240,6 +240,29 @@ func resourceComputeSecurityPolicy() *schema.Resource { Optional: true, Description: `Can only be specified if the action for the rule is "rate_based_ban". If specified, determines the time (in seconds) the traffic will continue to be banned by the rate limit after the rate falls below the threshold.`, }, + + "exceed_redirect_options": { + Type: schema.TypeList, + Optional: true, + Description: `Parameters defining the redirect action that is used as the exceed action. Cannot be specified if the exceed action is not redirect.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + Description: `Type of the redirect action.`, + ValidateFunc: validation.StringInSlice([]string{"EXTERNAL_302", "GOOGLE_RECAPTCHA"}, false), + }, + + "target": { + Type: schema.TypeString, + Optional: true, + Description: `Target for the redirect action. This is required if the type is EXTERNAL_302 and cannot be specified for GOOGLE_RECAPTCHA.`, + }, + }, + }, + }, }, }, }, diff --git a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb index 18f0fb27ab66..496828912ba1 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb @@ -400,7 +400,7 @@ resource "google_compute_security_policy" "policy" { } rate_limit_options { conform_action = "allow" - exceed_action = "allow" + exceed_action = "deny(403)" enforce_on_key = "IP" rate_limit_threshold { count = 100 From 9b7baada3471e7ab9c26241a7c60999869e971fb Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Thu, 20 Jan 2022 12:28:48 -0500 Subject: [PATCH 14/15] Add default security policy rule --- .../resource_compute_security_policy_test.go.erb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb index 496828912ba1..822013cbc9b7 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_security_policy_test.go.erb @@ -387,6 +387,19 @@ func testAccComputeSecurityPolicy_withRateLimitOptions(spName string) string { resource "google_compute_security_policy" "policy" { name = "%s" description = "updated description" + + rule { + action = "allow" + priority = "2147483647" + match { + versioned_expr = "SRC_IPS_V1" + config { + src_ip_ranges = ["*"] + } + } + description = "default rule" + } + rule { action = "throttle" priority = 100 From 9402321f485a8c8c7ed5b42ab9629bdb5bb535d3 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Wed, 26 Jan 2022 10:20:16 -0500 Subject: [PATCH 15/15] Fix exceed and conform action descriptions --- .../resources/resource_compute_security_policy.go.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb index 9179f6262c77..e4c04ccb73c9 100644 --- a/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/resources/resource_compute_security_policy.go.erb @@ -189,14 +189,14 @@ func resourceComputeSecurityPolicy() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{"allow"}, false), - Description: `When a request is denied, returns the HTTP response code specified. Valid options are "deny()" where valid values for status are 403, 404, 429, and 502.`, + Description: `Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only.`, }, "exceed_action": { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{"redirect", "deny(403)", "deny(404)", "deny(429)", "deny(502)"}, false), - Description: `Action to take for requests that are under the configured rate limit threshold. Valid option is "allow" only.`, + Description: `Action to take for requests that are above the configured rate limit threshold, to either deny with a specified HTTP response code, or redirect to a different endpoint. Valid options are "deny()" where valid values for status are 403, 404, 429, and 502, and "redirect" where the redirect parameters come from exceedRedirectOptions below.`, }, "enforce_on_key": {