From f80d7a2d69bcf858bdd37cac9afbeb33b8dd106d Mon Sep 17 00:00:00 2001 From: Aleksandr Kalashnikov Date: Thu, 7 Mar 2024 11:36:19 +0100 Subject: [PATCH 01/15] Add credential stuffing rules --- .../rule_credential_stuffing_mode.md | 158 ++++++++++ .../rule_credential_stuffing_point.md | 183 +++++++++++ .../rule_credential_stuffing_regex.md | 167 ++++++++++ .../wallarm_rule_credential_stuffing_mode.tf | 16 + .../wallarm_rule_credential_stuffing_point.tf | 18 ++ .../wallarm_rule_credential_stuffing_regex.tf | 21 ++ wallarm/provider.go | 76 ++--- .../resource_rule_credential_stuffing_mode.go | 258 +++++++++++++++ ...urce_rule_credential_stuffing_mode_test.go | 95 ++++++ ...resource_rule_credential_stuffing_point.go | 293 ++++++++++++++++++ ...rce_rule_credential_stuffing_point_test.go | 102 ++++++ ...resource_rule_credential_stuffing_regex.go | 283 +++++++++++++++++ ...rce_rule_credential_stuffing_regex_test.go | 91 ++++++ wallarm/utils.go | 28 ++ 14 files changed, 1753 insertions(+), 36 deletions(-) create mode 100644 docs/resources/rule_credential_stuffing_mode.md create mode 100644 docs/resources/rule_credential_stuffing_point.md create mode 100644 docs/resources/rule_credential_stuffing_regex.md create mode 100644 examples/wallarm_rule_credential_stuffing_mode.tf create mode 100644 examples/wallarm_rule_credential_stuffing_point.tf create mode 100644 examples/wallarm_rule_credential_stuffing_regex.tf create mode 100644 wallarm/resource_rule_credential_stuffing_mode.go create mode 100644 wallarm/resource_rule_credential_stuffing_mode_test.go create mode 100644 wallarm/resource_rule_credential_stuffing_point.go create mode 100644 wallarm/resource_rule_credential_stuffing_point_test.go create mode 100644 wallarm/resource_rule_credential_stuffing_regex.go create mode 100644 wallarm/resource_rule_credential_stuffing_regex_test.go diff --git a/docs/resources/rule_credential_stuffing_mode.md b/docs/resources/rule_credential_stuffing_mode.md new file mode 100644 index 0000000..a522c40 --- /dev/null +++ b/docs/resources/rule_credential_stuffing_mode.md @@ -0,0 +1,158 @@ +--- +layout: "wallarm" +page_title: "Wallarm: wallarm_rule_credential_stuffing_mode" +subcategory: "Rule" +description: |- + Provides "Credential Stuffing" rule resource. +--- + +# wallarm_rule_credential_stuffing_mode + +Provides the resource to enable and disable credentials stuffing feature for specific endpoints. + +**Important:** Rules made with Terraform can't be altered by other rules that usually change how rules work (middleware, variative_values, variative_by_regex). +This is because Terraform is designed to keep its configurations stable and not meant to be modified from outside its environment. + +## Example Usage + +```hcl +resource "wallarm_rule_credential_stuffing_point" "mode1" { + +} + +resource "wallarm_rule_credential_stuffing_point" "mode2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + mode = "custom" +} +``` + +## Argument Reference + +* `client_id` - (optional) ID of the client to apply the rules to. The value is required for [multi-tenant scenarios][2]. +* `action` - (optional) rule conditions. Possible attributes are described below. +* `mode` - (optional) credential stafing mode. Can be: `default`, `custom`, `disabled`. Default value: `default`. + +**action** + +`action` argument shares the available conditions which can be applied. The conditions are: + +* `type` - (optional) condition type. Can be: `equal`, `iequal`, `regex`, `absent`. Must be omitted for the `instance` parameter in `point`. + For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/add-rule/#condition-types) + Example: + `type = "absent"` +* `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. + Example: + `value = "example.com"` +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). + +**action.point** + + * `header` - (optional) arbitrary HEADER parameter name. + Example: + `header = "HOST"` + * `method` - (optional) request method. Can be: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH`. + Example: + `method = "POST"` + * `path` - (optional) array with URL parts separated by the `/` symbol (the last URL part is not included in the array). If there is only one part in the URL, the array will be empty. + Example: + `path = 0` + * `action_name` - (optional) the last part of the URL after the `/` symbol and before the first period (`.`). This part of the URL is always present in the request even if its value is an empty string. + Example: + `action_name = "login"` + * `action_ext` - (optional) the part of the URL after the last period (`.`). It may be missing in the request. + Example: + `action_ext = "php"` + * `query` - (optional) the query parameter name. + Example: + `query = "user"` + * `proto` - (optional) version of the HTTP Protocol. + Example: + `proto = "1.1"` + * `scheme` - (optional) `http`/`https`. + Example: + `scheme = "https"` + * `uri` - (optional) part of the request URL without domain. + Example: + `uri = "/api/login"` + * `instance` - (optional) ID of the application. + Example: + `instance = 42` + +Example: + + ```hcl + # ... omitted + + action { + type = "equal" + point = { + scheme = "https" + } + } + + action { + point = { + instance = 9 + } + } + + action { + type = "absent" + point = { + path = 0 + } + } + + action { + type = "regex" + point = { + action_name = "masking" + } + } + + action { + type = "absent" + point = { + action_ext = "" + } + } + + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } + + action { + type = "equal" + value = "admin" + point = { + query = "user" + } + } + + # ... omitted + ``` + +> **_NOTE:_** +See below what limitations apply + +When `type` is `absent`, `point` must contain key with the default value. For `action_name`, `action_ext`, `method`, `proto`, `scheme`, `uri` default value is `""` (empty string). + +## Attributes Reference + +* `rule_id` - ID of the created rule. +* `action_id` - the action ID (The conditions to apply on request). +* `rule_type` - type of the created rule. For example, `rule_type = "cred_stuff_mode"`. + +[2]: https://docs.wallarm.com/installation/multi-tenant/overview/ diff --git a/docs/resources/rule_credential_stuffing_point.md b/docs/resources/rule_credential_stuffing_point.md new file mode 100644 index 0000000..0ad2017 --- /dev/null +++ b/docs/resources/rule_credential_stuffing_point.md @@ -0,0 +1,183 @@ +--- +layout: "wallarm" +page_title: "Wallarm: wallarm_rule_credential_stuffing_point" +subcategory: "Rule" +description: |- + Provides the "Authentication endpoints by exact location of parameters in Credential Stuffing" rule resource. +--- + +# wallarm_rule_credential_stuffing_point + +Provides the resource to configure authentication endpoints for [Credential Stuffing](https://docs.wallarm.com/about-wallarm/credential-stuffing/) by using request point approach. + +**Important:** Rules made with Terraform can't be altered by other rules that usually change how rules work (middleware, variative_values, variative_by_regex). +This is because Terraform is designed to keep its configurations stable and not meant to be modified from outside its environment. + +## Example Usage + +```hcl +resource "wallarm_rule_credential_stuffing_point" "point1" { + point = [["HEADER", "HOST"]] + login_point = ["HEADER", "SESSION-ID"] +} + +resource "wallarm_rule_credential_stuffing_point" "point2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + point = [["HEADER", "HOST"]] + login_point = ["HEADER", "SESSION-ID"] +} +``` + +## Argument Reference + +* `client_id` - (optional) ID of the client to apply the rules to. The value is required for [multi-tenant scenarios][2]. +* `action` - (optional) rule conditions. Possible attributes are described below. +* `cred_stuff_type` - (optional) defines which database of compromised credentials to use. Can be: `default`, `custom`. Default value: `default`. +* `point` - (**required**) request point used for specifying password parameters. Fore more details about request points, see wallarm [documentation][1]. +* `login_point` - (**required**) request point used for specifying login parameters. Fore more details about request points, see wallarm [documentation][1]. + +**point**, **login_point** + +Should be a correct point belonging to the request, that finishes by _all + +Example: + +Correct: + +* [["post"],["form_urlencoded", "test"],["array_all"]] +* [["post"],["form_urlencoded_all"]] +* [["post"],["json_doc"],["array_all"]] +* [["header_all"]] + +Incorrect: + +* [["post"],["form_urlencoded", "test"]] +* [["post"]] +* [["path_all"]] +* [["header","HOST"]] + +**action** + +`action` argument shares the available conditions which can be applied. The conditions are: + +* `type` - (optional) condition type. Can be: `equal`, `iequal`, `regex`, `absent`. Must be omitted for the `instance` parameter in `point`. + For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/add-rule/#condition-types) + Example: + `type = "absent"` +* `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. + Example: + `value = "example.com"` +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). + +**action.point** + + * `header` - (optional) arbitrary HEADER parameter name. + Example: + `header = "HOST"` + * `method` - (optional) request method. Can be: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH`. + Example: + `method = "POST"` + * `path` - (optional) array with URL parts separated by the `/` symbol (the last URL part is not included in the array). If there is only one part in the URL, the array will be empty. + Example: + `path = 0` + * `action_name` - (optional) the last part of the URL after the `/` symbol and before the first period (`.`). This part of the URL is always present in the request even if its value is an empty string. + Example: + `action_name = "login"` + * `action_ext` - (optional) the part of the URL after the last period (`.`). It may be missing in the request. + Example: + `action_ext = "php"` + * `query` - (optional) the query parameter name. + Example: + `query = "user"` + * `proto` - (optional) version of the HTTP Protocol. + Example: + `proto = "1.1"` + * `scheme` - (optional) `http`/`https`. + Example: + `scheme = "https"` + * `uri` - (optional) part of the request URL without domain. + Example: + `uri = "/api/login"` + * `instance` - (optional) ID of the application. + Example: + `instance = 42` + +Example: + + ```hcl + # ... omitted + + action { + type = "equal" + point = { + scheme = "https" + } + } + + action { + point = { + instance = 9 + } + } + + action { + type = "absent" + point = { + path = 0 + } + } + + action { + type = "regex" + point = { + action_name = "masking" + } + } + + action { + type = "absent" + point = { + action_ext = "" + } + } + + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } + + action { + type = "equal" + value = "admin" + point = { + query = "user" + } + } + + # ... omitted + ``` + +> **_NOTE:_** +See below what limitations apply + +When `type` is `absent`, `point` must contain key with the default value. For `action_name`, `action_ext`, `method`, `proto`, `scheme`, `uri` default value is `""` (empty string). + +## Attributes Reference + +* `rule_id` - ID of the created rule. +* `action_id` - the action ID (The conditions to apply on request). +* `rule_type` - type of the created rule. For example, `rule_type = "credentials_point"`. + +[1]: https://docs.wallarm.com/user-guides/rules/rules/#points +[2]: https://docs.wallarm.com/installation/multi-tenant/overview/ diff --git a/docs/resources/rule_credential_stuffing_regex.md b/docs/resources/rule_credential_stuffing_regex.md new file mode 100644 index 0000000..bcfe7d4 --- /dev/null +++ b/docs/resources/rule_credential_stuffing_regex.md @@ -0,0 +1,167 @@ +--- +layout: "wallarm" +page_title: "Wallarm: wallarm_rule_credential_stuffing_regex" +subcategory: "Rule" +description: |- + Provides the "Authentication endpoints by regular expession in Credential Stuffing" rule resource. +--- + +# wallarm_rule_credential_stuffing_regex + +Provides the resource to configure authentication endpoints for [Credential Stuffing](https://docs.wallarm.com/about-wallarm/credential-stuffing/) by using regular expression approach. + +**Important:** Rules made with Terraform can't be altered by other rules that usually change how rules work (middleware, variative_values, variative_by_regex). +This is because Terraform is designed to keep its configurations stable and not meant to be modified from outside its environment. + +## Example Usage + +```hcl +resource "wallarm_rule_credential_stuffing_regex" "regex1" { + regex = "*abc*" + login_regex = "user*" + case_sensitive = false +} + +resource "wallarm_rule_credential_stuffing_regex" "regex2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + regex = "*abc*" + login_regex = "user*" + case_sensitive = true + cred_stuff_type = "custom" +} +``` + +## Argument Reference + +* `client_id` - (optional) ID of the client to apply the rules to. The value is required for [multi-tenant scenarios][2]. +* `action` - (optional) rule conditions. Possible attributes are described below. +* `cred_stuff_type` - (optional) defines which database of compromised credentials to use. Can be: `default`, `custom`. Default value: `default`. +* `regex` - (**required**) regular expression used for specifying password parameters. Fore more details about regexps, see wallarm [documentation][1]. +* `login_regex` - (**required**) regular expression used for specifying login parameters. Fore more details about regexps, see wallarm [documentation][1]. +* `case_sensitive` - (**required**) defines whether regex and login_regex are case sensitive. + +**action** + +`action` argument shares the available conditions which can be applied. The conditions are: + +* `type` - (optional) condition type. Can be: `equal`, `iequal`, `regex`, `absent`. Must be omitted for the `instance` parameter in `point`. + For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/add-rule/#condition-types) + Example: + `type = "absent"` +* `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. + Example: + `value = "example.com"` +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). + +**action.point** + + * `header` - (optional) arbitrary HEADER parameter name. + Example: + `header = "HOST"` + * `method` - (optional) request method. Can be: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH`. + Example: + `method = "POST"` + * `path` - (optional) array with URL parts separated by the `/` symbol (the last URL part is not included in the array). If there is only one part in the URL, the array will be empty. + Example: + `path = 0` + * `action_name` - (optional) the last part of the URL after the `/` symbol and before the first period (`.`). This part of the URL is always present in the request even if its value is an empty string. + Example: + `action_name = "login"` + * `action_ext` - (optional) the part of the URL after the last period (`.`). It may be missing in the request. + Example: + `action_ext = "php"` + * `query` - (optional) the query parameter name. + Example: + `query = "user"` + * `proto` - (optional) version of the HTTP Protocol. + Example: + `proto = "1.1"` + * `scheme` - (optional) `http`/`https`. + Example: + `scheme = "https"` + * `uri` - (optional) part of the request URL without domain. + Example: + `uri = "/api/login"` + * `instance` - (optional) ID of the application. + Example: + `instance = 42` + +Example: + + ```hcl + # ... omitted + + action { + type = "equal" + point = { + scheme = "https" + } + } + + action { + point = { + instance = 9 + } + } + + action { + type = "absent" + point = { + path = 0 + } + } + + action { + type = "regex" + point = { + action_name = "masking" + } + } + + action { + type = "absent" + point = { + action_ext = "" + } + } + + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } + + action { + type = "equal" + value = "admin" + point = { + query = "user" + } + } + + # ... omitted + ``` + +> **_NOTE:_** +See below what limitations apply + +When `type` is `absent`, `point` must contain key with the default value. For `action_name`, `action_ext`, `method`, `proto`, `scheme`, `uri` default value is `""` (empty string). + +## Attributes Reference + +* `rule_id` - ID of the created rule. +* `action_id` - the action ID (The conditions to apply on request). +* `rule_type` - type of the created rule. For example, `rule_type = "credentials_regex"`. + +[1]: https://docs.wallarm.com/user-guides/rules/rules/#condition-type-regex +[2]: https://docs.wallarm.com/installation/multi-tenant/overview/ diff --git a/examples/wallarm_rule_credential_stuffing_mode.tf b/examples/wallarm_rule_credential_stuffing_mode.tf new file mode 100644 index 0000000..1f34d9d --- /dev/null +++ b/examples/wallarm_rule_credential_stuffing_mode.tf @@ -0,0 +1,16 @@ +resource "wallarm_rule_credential_stuffing_point" "mode1" { + +} + +resource "wallarm_rule_credential_stuffing_point" "mode2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + mode = "custom" +} diff --git a/examples/wallarm_rule_credential_stuffing_point.tf b/examples/wallarm_rule_credential_stuffing_point.tf new file mode 100644 index 0000000..c604d12 --- /dev/null +++ b/examples/wallarm_rule_credential_stuffing_point.tf @@ -0,0 +1,18 @@ +resource "wallarm_rule_credential_stuffing_point" "point1" { + point = [["HEADER", "HOST"]] + login_point = ["HEADER", "SESSION-ID"] +} + +resource "wallarm_rule_credential_stuffing_point" "point2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + point = [["HEADER", "HOST"]] + login_point = ["HEADER", "SESSION-ID"] +} diff --git a/examples/wallarm_rule_credential_stuffing_regex.tf b/examples/wallarm_rule_credential_stuffing_regex.tf new file mode 100644 index 0000000..d18a618 --- /dev/null +++ b/examples/wallarm_rule_credential_stuffing_regex.tf @@ -0,0 +1,21 @@ +resource "wallarm_rule_credential_stuffing_regex" "regex1" { + regex = "*abc*" + login_regex = "user*" + case_sensitive = false +} + +resource "wallarm_rule_credential_stuffing_regex" "regex2" { + client_id = 123 + + action { + type = "iequal" + point = { + action_name = "login" + } + } + + regex = "*abc*" + login_regex = "user*" + case_sensitive = true + cred_stuff_type = "custom" +} diff --git a/wallarm/provider.go b/wallarm/provider.go index 591f4e0..c7a21bf 100644 --- a/wallarm/provider.go +++ b/wallarm/provider.go @@ -109,42 +109,45 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "wallarm_user": resourceWallarmUser(), - "wallarm_blacklist": resourceWallarmDenylist(), // deprecated & undocumented - "wallarm_denylist": resourceWallarmDenylist(), - "wallarm_allowlist": resourceWallarmAllowlist(), - "wallarm_graylist": resourceWallarmGraylist(), - "wallarm_global_mode": resourceWallarmGlobalMode(), - "wallarm_node": resourceWallarmNode(), - "wallarm_scanner": resourceWallarmScanner(), - "wallarm_application": resourceWallarmApp(), - "wallarm_integration_email": resourceWallarmEmail(), - "wallarm_integration_opsgenie": resourceWallarmOpsGenie(), - "wallarm_integration_slack": resourceWallarmSlack(), - "wallarm_integration_pagerduty": resourceWallarmPagerDuty(), - "wallarm_integration_sumologic": resourceWallarmSumologic(), - "wallarm_integration_insightconnect": resourceWallarmInsightConnect(), - "wallarm_integration_splunk": resourceWallarmSplunk(), - "wallarm_integration_webhook": resourceWallarmWebhook(), - "wallarm_trigger": resourceWallarmTrigger(), - "wallarm_rule_binary_data": resourceWallarmBinaryData(), - "wallarm_rule_disable_attack_type": resourceWallarmDisableAttackType(), - "wallarm_rule_variative_keys": resourceWallarmVariativeKeys(), - "wallarm_rule_variative_values": resourceWallarmVariativeValues(), - "wallarm_rule_vpatch": resourceWallarmVpatch(), - "wallarm_rule_mode": resourceWallarmMode(), - "wallarm_rule_masking": resourceWallarmSensitiveData(), - "wallarm_rule_parser_state": resourceWallarmParserState(), - "wallarm_rule_regex": resourceWallarmRegex(), - "wallarm_rule_ignore_regex": resourceWallarmIgnoreRegex(), - "wallarm_rule_attack_rechecker": resourceWallarmAttackRechecker(), - "wallarm_rule_attack_rechecker_rewrite": resourceWallarmAttackRecheckerRewrite(), - "wallarm_rule_set_response_header": resourceWallarmSetResponseHeader(), - "wallarm_rule_bruteforce_counter": resourceWallarmBruteForceCounter(), - "wallarm_rule_dirbust_counter": resourceWallarmDirbustCounter(), - "wallarm_rule_uploads": resourceWallarmUploads(), - "wallarm_rules_settings": resourceWallarmRulesSettings(), - "wallarm_tenant": resourceWallarmTenant(), + "wallarm_user": resourceWallarmUser(), + "wallarm_blacklist": resourceWallarmDenylist(), // deprecated & undocumented + "wallarm_denylist": resourceWallarmDenylist(), + "wallarm_allowlist": resourceWallarmAllowlist(), + "wallarm_graylist": resourceWallarmGraylist(), + "wallarm_global_mode": resourceWallarmGlobalMode(), + "wallarm_node": resourceWallarmNode(), + "wallarm_scanner": resourceWallarmScanner(), + "wallarm_application": resourceWallarmApp(), + "wallarm_integration_email": resourceWallarmEmail(), + "wallarm_integration_opsgenie": resourceWallarmOpsGenie(), + "wallarm_integration_slack": resourceWallarmSlack(), + "wallarm_integration_pagerduty": resourceWallarmPagerDuty(), + "wallarm_integration_sumologic": resourceWallarmSumologic(), + "wallarm_integration_insightconnect": resourceWallarmInsightConnect(), + "wallarm_integration_splunk": resourceWallarmSplunk(), + "wallarm_integration_webhook": resourceWallarmWebhook(), + "wallarm_trigger": resourceWallarmTrigger(), + "wallarm_rule_binary_data": resourceWallarmBinaryData(), + "wallarm_rule_disable_attack_type": resourceWallarmDisableAttackType(), + "wallarm_rule_variative_keys": resourceWallarmVariativeKeys(), + "wallarm_rule_variative_values": resourceWallarmVariativeValues(), + "wallarm_rule_vpatch": resourceWallarmVpatch(), + "wallarm_rule_mode": resourceWallarmMode(), + "wallarm_rule_masking": resourceWallarmSensitiveData(), + "wallarm_rule_parser_state": resourceWallarmParserState(), + "wallarm_rule_regex": resourceWallarmRegex(), + "wallarm_rule_ignore_regex": resourceWallarmIgnoreRegex(), + "wallarm_rule_attack_rechecker": resourceWallarmAttackRechecker(), + "wallarm_rule_attack_rechecker_rewrite": resourceWallarmAttackRecheckerRewrite(), + "wallarm_rule_set_response_header": resourceWallarmSetResponseHeader(), + "wallarm_rule_bruteforce_counter": resourceWallarmBruteForceCounter(), + "wallarm_rule_dirbust_counter": resourceWallarmDirbustCounter(), + "wallarm_rule_uploads": resourceWallarmUploads(), + "wallarm_rule_credential_stuffing_regex": resourceWallarmCredentialStuffingRegex(), + "wallarm_rule_credential_stuffing_point": resourceWallarmCredentialStuffingPoint(), + "wallarm_rule_credential_stuffing_mode": resourceWallarmCredentialStuffingMode(), + "wallarm_rules_settings": resourceWallarmRulesSettings(), + "wallarm_tenant": resourceWallarmTenant(), }, } @@ -209,6 +212,7 @@ func providerConfigure(d *schema.ResourceData, terraformVersion string) (interfa if err != nil { return nil, err } + ClientID = u.Body.Clientid } diff --git a/wallarm/resource_rule_credential_stuffing_mode.go b/wallarm/resource_rule_credential_stuffing_mode.go new file mode 100644 index 0000000..bd9550d --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_mode.go @@ -0,0 +1,258 @@ +package wallarm + +import ( + "fmt" + "log" + "strconv" + "strings" + + wallarm "github.com/wallarm/wallarm-go" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceWallarmCredentialStuffingMode() *schema.Resource { + return &schema.Resource{ + Create: resourceWallarmCredentialStuffingModeCreate, + Read: resourceWallarmCredentialStuffingModeRead, + Delete: resourceWallarmCredentialStuffingModeDelete, + Importer: &schema.ResourceImporter{ + State: resourceWallarmCredentialStuffingModeImport, + }, + Schema: map[string]*schema.Schema{ + "rule_id": { + Type: schema.TypeInt, + Computed: true, + }, + "action_id": { + Type: schema.TypeInt, + Computed: true, + }, + "rule_type": { + Type: schema.TypeString, + Computed: true, + }, + "client_id": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "The Client ID to perform changes", + ValidateFunc: validation.IntAtLeast(1), + }, + "comment": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "mode": { + Type: schema.TypeString, + Optional: true, + Default: "default", + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"custom", "default", "disabled"}, false), + }, + "action": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"equal", "iequal", "regex", "absent"}, false), + ForceNew: true, + }, + "value": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "point": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "method": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"GET", "HEAD", "POST", + "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"}, false), + }, + "path": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 60), + }, + "action_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "action_ext": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "proto": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"1.0", "1.1", "2.0", "3.0"}, false), + }, + "scheme": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"http", "https"}, true), + }, + "uri": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "instance": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(-1), + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceWallarmCredentialStuffingModeCreate(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + comment := d.Get("comment").(string) + mode := d.Get("mode").(string) + + actionsFromState := d.Get("action").(*schema.Set) + action, err := expandSetToActionDetailsList(actionsFromState) + if err != nil { + return err + } + + resp, err := client.HintCreate(&wallarm.ActionCreate{ + Type: "cred_stuff_mode", + Clientid: clientID, + Action: &action, + Validated: false, + Comment: comment, + VariativityDisabled: true, + Mode: mode, + }) + if err != nil { + return err + } + + resID := fmt.Sprintf("%d/%d/%d", resp.Body.Clientid, resp.Body.ActionID, resp.Body.ID) + d.SetId(resID) + d.Set("client_id", resp.Body.Clientid) + d.Set("rule_id", resp.Body.ID) + + return resourceWallarmCredentialStuffingModeRead(d, m) +} + +func resourceWallarmCredentialStuffingModeRead(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + rule, err := findRule(client, clientID, ruleID) + if !d.IsNewResource() { + if _, ok := err.(*ruleNotFoundError); ok { + log.Printf("[WARN] Rule %s not found, removing from state", d.Id()) + d.SetId("") + return nil + } + } + if err != nil { + return err + } + + d.Set("mode", rule.Mode) + + d.Set("rule_type", rule.Type) + d.Set("action_id", rule.ActionID) + actionsSet := schema.Set{F: hashResponseActionDetails} + for _, a := range rule.Action { + acts, err := actionDetailsToMap(a) + if err != nil { + return err + } + actionsSet.Add(acts) + } + if err := d.Set("action", &actionsSet); err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingModeDelete(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + err := client.HintDelete(&wallarm.HintDelete{ + Filter: &wallarm.HintDeleteFilter{ + Clientid: []int{clientID}, + ID: ruleID, + }, + }) + if err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingModeImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + client := m.(wallarm.API) + idParts := strings.SplitN(d.Id(), "/", 3) + if len(idParts) != 3 { + return nil, fmt.Errorf("invalid id (%q) specified, should be in format \"{clientID}/{actionID}/{ruleID}\"", d.Id()) + } + + clientID, err := strconv.Atoi(idParts[0]) + if err != nil { + return nil, err + } + ruleID, err := strconv.Atoi(idParts[2]) + if err != nil { + return nil, err + } + + _, err = findRule(client, clientID, ruleID) + if err != nil { + return nil, err + } + + d.Set("client_id", clientID) + d.Set("rule_id", ruleID) + + return []*schema.ResourceData{d}, nil +} diff --git a/wallarm/resource_rule_credential_stuffing_mode_test.go b/wallarm/resource_rule_credential_stuffing_mode_test.go new file mode 100644 index 0000000..59653fd --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_mode_test.go @@ -0,0 +1,95 @@ +package wallarm + +import ( + "fmt" + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + wallarm "github.com/wallarm/wallarm-go" +) + +func TestAccRuleCredentialStuffingMode_basic(t *testing.T) { + resourceName := generateRandomResourceName(5) + resourceAddress := "wallarm_rule_credential_stuffing_mode." + resourceName + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccRuleCredentialStuffingModeDestroy(), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccRuleCredentialStuffingMode_basic(resourceName, "default"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceAddress, "mode", "default"), + resource.TestCheckResourceAttr(resourceAddress, "action.#", "1"), + ), + }, + }, + }) +} + +func testAccRuleCredentialStuffingMode_basic(resourceName string, mode string) string { + return fmt.Sprintf(` +resource "wallarm_rule_credential_stuffing_mode" %[1]q { + mode = %[2]q + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } +} +`, resourceName, mode) +} + +func testAccRuleCredentialStuffingModeDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(wallarm.API) + + for _, resource := range s.RootModule().Resources { + if resource.Type != "wallarm_rule_credential_stuffing_mode" { + continue + } + + clientID, err := strconv.Atoi(resource.Primary.Attributes["client_id"]) + if err != nil { + return err + } + ruleID, err := strconv.Atoi(resource.Primary.Attributes["rule_id"]) + if err != nil { + return err + } + + resp, err := client.HintRead(&wallarm.HintRead{ + Limit: 1, + OrderBy: "updated_at", + Filter: &wallarm.HintFilter{ + Clientid: []int{clientID}, + ID: []int{ruleID}, + }, + }) + if err != nil { + return err + } + + if resp != nil && resp.Body != nil && len(*resp.Body) != 0 { + return fmt.Errorf("Resource still exists: %s", resource.Primary.ID) + } + } + + return nil + } +} + +func testAccRuleCredentialStuffingModeIdFunc(resourceAddress string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceAddress] + if !ok { + return "", fmt.Errorf("Not Found: %s", resourceAddress) + } + + return fmt.Sprintf("%s/%s/%s", rs.Primary.Attributes["client_id"], rs.Primary.Attributes["action_id"], rs.Primary.Attributes["rule_id"]), nil + } +} diff --git a/wallarm/resource_rule_credential_stuffing_point.go b/wallarm/resource_rule_credential_stuffing_point.go new file mode 100644 index 0000000..802776c --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_point.go @@ -0,0 +1,293 @@ +package wallarm + +import ( + "fmt" + "log" + "strconv" + "strings" + + wallarm "github.com/wallarm/wallarm-go" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceWallarmCredentialStuffingPoint() *schema.Resource { + return &schema.Resource{ + Create: resourceWallarmCredentialStuffingPointCreate, + Read: resourceWallarmCredentialStuffingPointRead, + Delete: resourceWallarmCredentialStuffingPointDelete, + Importer: &schema.ResourceImporter{ + State: resourceWallarmCredentialStuffingPointImport, + }, + Schema: map[string]*schema.Schema{ + "rule_id": { + Type: schema.TypeInt, + Computed: true, + }, + "action_id": { + Type: schema.TypeInt, + Computed: true, + }, + "rule_type": { + Type: schema.TypeString, + Computed: true, + }, + "client_id": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "The Client ID to perform changes", + ValidateFunc: validation.IntAtLeast(1), + }, + "comment": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "point": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + "login_point": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + "cred_stuff_type": { + Type: schema.TypeString, + Optional: true, + Default: "default", + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"custom", "default"}, false), + }, + "action": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"equal", "iequal", "regex", "absent"}, false), + ForceNew: true, + }, + "value": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "point": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "method": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"GET", "HEAD", "POST", + "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"}, false), + }, + "path": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 60), + }, + "action_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "action_ext": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "proto": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"1.0", "1.1", "2.0", "3.0"}, false), + }, + "scheme": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"http", "https"}, true), + }, + "uri": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "instance": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(-1), + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + comment := d.Get("comment").(string) + credStuffType := d.Get("cred_stuff_type").(string) + + iPoint := d.Get("point").([]interface{}) + point, err := expandPointsToTwoDimensionalArray(iPoint) + if err != nil { + return err + } + + iLoginPoint := d.Get("login_point").([]interface{}) + loginPoint, err := expandPointsToTwoDimensionalArray(iLoginPoint) + if err != nil { + return err + } + + actionsFromState := d.Get("action").(*schema.Set) + action, err := expandSetToActionDetailsList(actionsFromState) + if err != nil { + return err + } + + resp, err := client.HintCreate(&wallarm.ActionCreate{ + Type: "credentials_point", + Clientid: clientID, + Action: &action, + Validated: false, + Comment: comment, + VariativityDisabled: true, + Point: point, + LoginPoint: loginPoint, + CredStuffType: credStuffType, + }) + if err != nil { + return err + } + + resID := fmt.Sprintf("%d/%d/%d", resp.Body.Clientid, resp.Body.ActionID, resp.Body.ID) + d.SetId(resID) + d.Set("client_id", resp.Body.Clientid) + d.Set("rule_id", resp.Body.ID) + + return resourceWallarmCredentialStuffingPointRead(d, m) +} + +func resourceWallarmCredentialStuffingPointRead(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + rule, err := findRule(client, clientID, ruleID) + if !d.IsNewResource() { + if _, ok := err.(*ruleNotFoundError); ok { + log.Printf("[WARN] Rule %s not found, removing from state", d.Id()) + d.SetId("") + return nil + } + } + if err != nil { + return err + } + + d.Set("cred_stuff_type", rule.CredStuffType) + + d.Set("point", rule.Point) + d.Set("login_point", rule.LoginPoint) + + d.Set("rule_type", rule.Type) + d.Set("action_id", rule.ActionID) + actionsSet := schema.Set{F: hashResponseActionDetails} + for _, a := range rule.Action { + acts, err := actionDetailsToMap(a) + if err != nil { + return err + } + actionsSet.Add(acts) + } + if err := d.Set("action", &actionsSet); err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingPointDelete(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + err := client.HintDelete(&wallarm.HintDelete{ + Filter: &wallarm.HintDeleteFilter{ + Clientid: []int{clientID}, + ID: ruleID, + }, + }) + if err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingPointImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + client := m.(wallarm.API) + idParts := strings.SplitN(d.Id(), "/", 3) + if len(idParts) != 3 { + return nil, fmt.Errorf("invalid id (%q) specified, should be in format \"{clientID}/{actionID}/{ruleID}\"", d.Id()) + } + + clientID, err := strconv.Atoi(idParts[0]) + if err != nil { + return nil, err + } + ruleID, err := strconv.Atoi(idParts[2]) + if err != nil { + return nil, err + } + + _, err = findRule(client, clientID, ruleID) + if err != nil { + return nil, err + } + + d.Set("client_id", clientID) + d.Set("rule_id", ruleID) + + return []*schema.ResourceData{d}, nil +} diff --git a/wallarm/resource_rule_credential_stuffing_point_test.go b/wallarm/resource_rule_credential_stuffing_point_test.go new file mode 100644 index 0000000..bd47c41 --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_point_test.go @@ -0,0 +1,102 @@ +package wallarm + +import ( + "fmt" + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + wallarm "github.com/wallarm/wallarm-go" +) + +func TestAccRuleCredentialStuffingPoint_basic(t *testing.T) { + resourceName := generateRandomResourceName(5) + resourceAddress := "wallarm_rule_credential_stuffing_point." + resourceName + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccRuleCredentialStuffingPointDestroy(), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccRuleCredentialStuffingPoint_basic(resourceName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceAddress, "point.0.0", "header"), + resource.TestCheckResourceAttr(resourceAddress, "point.0.1", "HOST"), + resource.TestCheckResourceAttr(resourceAddress, "login_point.0.0", "header"), + resource.TestCheckResourceAttr(resourceAddress, "login_point.0.1", "SESSION-ID"), + resource.TestCheckResourceAttr(resourceAddress, "cred_stuff_type", "custom"), + resource.TestCheckResourceAttr(resourceAddress, "action.#", "1"), + ), + }, + }, + }) +} + +func testAccRuleCredentialStuffingPoint_basic(resourceName string) string { + return fmt.Sprintf(` +resource "wallarm_rule_credential_stuffing_point" %[1]q { + point = [["header", "HOST"]] + login_point = [["header", "SESSION-ID"]] + cred_stuff_type = "custom" + + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } +} +`, resourceName) +} + +func testAccRuleCredentialStuffingPointDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(wallarm.API) + + for _, resource := range s.RootModule().Resources { + if resource.Type != "wallarm_rule_credential_stuffing_point" { + continue + } + + clientID, err := strconv.Atoi(resource.Primary.Attributes["client_id"]) + if err != nil { + return err + } + ruleID, err := strconv.Atoi(resource.Primary.Attributes["rule_id"]) + if err != nil { + return err + } + + resp, err := client.HintRead(&wallarm.HintRead{ + Limit: 1, + OrderBy: "updated_at", + Filter: &wallarm.HintFilter{ + Clientid: []int{clientID}, + ID: []int{ruleID}, + }, + }) + if err != nil { + return err + } + + if resp != nil && resp.Body != nil && len(*resp.Body) != 0 { + return fmt.Errorf("Resource still exists: %s", resource.Primary.ID) + } + } + + return nil + } +} + +func testAccRuleCredentialStuffingPointIdFunc(resourceAddress string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[resourceAddress] + if !ok { + return "", fmt.Errorf("Not Found: %s", resourceAddress) + } + + return fmt.Sprintf("%s/%s/%s", rs.Primary.Attributes["client_id"], rs.Primary.Attributes["action_id"], rs.Primary.Attributes["rule_id"]), nil + } +} diff --git a/wallarm/resource_rule_credential_stuffing_regex.go b/wallarm/resource_rule_credential_stuffing_regex.go new file mode 100644 index 0000000..bd76546 --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_regex.go @@ -0,0 +1,283 @@ +package wallarm + +import ( + "fmt" + "log" + "strconv" + "strings" + + wallarm "github.com/wallarm/wallarm-go" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceWallarmCredentialStuffingRegex() *schema.Resource { + return &schema.Resource{ + Create: resourceWallarmCredentialStuffingRegexCreate, + Read: resourceWallarmCredentialStuffingRegexRead, + Delete: resourceWallarmCredentialStuffingRegexDelete, + Importer: &schema.ResourceImporter{ + State: resourceWallarmCredentialStuffingRegexImport, + }, + Schema: map[string]*schema.Schema{ + "rule_id": { + Type: schema.TypeInt, + Computed: true, + }, + "action_id": { + Type: schema.TypeInt, + Computed: true, + }, + "rule_type": { + Type: schema.TypeString, + Computed: true, + }, + "client_id": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "The Client ID to perform changes", + ValidateFunc: validation.IntAtLeast(1), + }, + "comment": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "regex": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "cred_stuff_type": { + Type: schema.TypeString, + Optional: true, + Default: "default", + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"custom", "default"}, false), + }, + "case_sensitive": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + }, + "login_regex": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 4096), + }, + "action": { + Type: schema.TypeSet, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"equal", "iequal", "regex", "absent"}, false), + ForceNew: true, + }, + "value": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "point": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "method": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"GET", "HEAD", "POST", + "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE", "PATCH"}, false), + }, + "path": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntBetween(0, 60), + }, + "action_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "action_ext": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "query": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "proto": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"1.0", "1.1", "2.0", "3.0"}, false), + }, + "scheme": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"http", "https"}, true), + }, + "uri": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "instance": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(-1), + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func resourceWallarmCredentialStuffingRegexCreate(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + comment := d.Get("comment").(string) + regex := d.Get("regex").(string) + credStuffType := d.Get("cred_stuff_type").(string) + caseSensitive := d.Get("case_sensitive").(bool) + loginRegex := d.Get("login_regex").(string) + + actionsFromState := d.Get("action").(*schema.Set) + action, err := expandSetToActionDetailsList(actionsFromState) + if err != nil { + return err + } + + resp, err := client.HintCreate(&wallarm.ActionCreate{ + Type: "credentials_regex", + Clientid: clientID, + Action: &action, + Validated: false, + Comment: comment, + VariativityDisabled: true, + Regex: regex, + LoginRegex: loginRegex, + CredStuffType: credStuffType, + CaseSensitive: &caseSensitive, + }) + if err != nil { + return err + } + + resID := fmt.Sprintf("%d/%d/%d", resp.Body.Clientid, resp.Body.ActionID, resp.Body.ID) + d.SetId(resID) + d.Set("client_id", resp.Body.Clientid) + d.Set("rule_id", resp.Body.ID) + + return resourceWallarmCredentialStuffingRegexRead(d, m) +} + +func resourceWallarmCredentialStuffingRegexRead(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + rule, err := findRule(client, clientID, ruleID) + if !d.IsNewResource() { + if _, ok := err.(*ruleNotFoundError); ok { + log.Printf("[WARN] Rule %s not found, removing from state", d.Id()) + d.SetId("") + return nil + } + } + if err != nil { + return err + } + + d.Set("regex", rule.Regex) + d.Set("cred_stuff_type", rule.CredStuffType) + d.Set("case_sensitive", rule.CaseSensitive) + d.Set("login_regex", rule.LoginRegex) + + d.Set("rule_type", rule.Type) + d.Set("action_id", rule.ActionID) + actionsSet := schema.Set{F: hashResponseActionDetails} + for _, a := range rule.Action { + acts, err := actionDetailsToMap(a) + if err != nil { + return err + } + actionsSet.Add(acts) + } + if err := d.Set("action", &actionsSet); err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingRegexDelete(d *schema.ResourceData, m interface{}) error { + client := m.(wallarm.API) + clientID := retrieveClientID(d, client) + ruleID := d.Get("rule_id").(int) + + err := client.HintDelete(&wallarm.HintDelete{ + Filter: &wallarm.HintDeleteFilter{ + Clientid: []int{clientID}, + ID: ruleID, + }, + }) + if err != nil { + return err + } + + return nil +} + +func resourceWallarmCredentialStuffingRegexImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + client := m.(wallarm.API) + idParts := strings.SplitN(d.Id(), "/", 3) + if len(idParts) != 3 { + return nil, fmt.Errorf("invalid id (%q) specified, should be in format \"{clientID}/{actionID}/{ruleID}\"", d.Id()) + } + + clientID, err := strconv.Atoi(idParts[0]) + if err != nil { + return nil, err + } + ruleID, err := strconv.Atoi(idParts[2]) + if err != nil { + return nil, err + } + + _, err = findRule(client, clientID, ruleID) + if err != nil { + return nil, err + } + + d.Set("client_id", clientID) + d.Set("rule_id", ruleID) + + return []*schema.ResourceData{d}, nil +} diff --git a/wallarm/resource_rule_credential_stuffing_regex_test.go b/wallarm/resource_rule_credential_stuffing_regex_test.go new file mode 100644 index 0000000..b3ecba6 --- /dev/null +++ b/wallarm/resource_rule_credential_stuffing_regex_test.go @@ -0,0 +1,91 @@ +package wallarm + +import ( + "fmt" + "strconv" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + wallarm "github.com/wallarm/wallarm-go" +) + +func TestAccRuleCredentialStuffingRegex_basic(t *testing.T) { + resourceName := generateRandomResourceName(5) + resourceAddress := "wallarm_rule_credential_stuffing_regex." + resourceName + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testAccRuleCredentialStuffingRegexDestroy(), + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccRuleCredentialStuffingRegex_basic(resourceName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceAddress, "regex", "abc"), + resource.TestCheckResourceAttr(resourceAddress, "login_regex", "def"), + resource.TestCheckResourceAttr(resourceAddress, "case_sensitive", "true"), + resource.TestCheckResourceAttr(resourceAddress, "cred_stuff_type", "custom"), + resource.TestCheckResourceAttr(resourceAddress, "action.#", "1"), + ), + }, + }, + }) +} + +func testAccRuleCredentialStuffingRegex_basic(resourceName string) string { + return fmt.Sprintf(` +resource "wallarm_rule_credential_stuffing_regex" %[1]q { + regex = "abc" + login_regex = "def" + case_sensitive = true + cred_stuff_type = "custom" + + action { + type = "iequal" + value = "example.com" + point = { + header = "HOST" + } + } +} +`, resourceName) +} + +func testAccRuleCredentialStuffingRegexDestroy() resource.TestCheckFunc { + return func(s *terraform.State) error { + client := testAccProvider.Meta().(wallarm.API) + + for _, resource := range s.RootModule().Resources { + if resource.Type != "wallarm_rule_credential_stuffing_regex" { + continue + } + + clientID, err := strconv.Atoi(resource.Primary.Attributes["client_id"]) + if err != nil { + return err + } + ruleID, err := strconv.Atoi(resource.Primary.Attributes["rule_id"]) + if err != nil { + return err + } + + resp, err := client.HintRead(&wallarm.HintRead{ + Limit: 1, + OrderBy: "updated_at", + Filter: &wallarm.HintFilter{ + Clientid: []int{clientID}, + ID: []int{ruleID}, + }, + }) + if err != nil { + return err + } + + if resp != nil && resp.Body != nil && len(*resp.Body) != 0 { + return fmt.Errorf("Resource still exists: %s", resource.Primary.ID) + } + } + + return nil + } +} diff --git a/wallarm/utils.go b/wallarm/utils.go index 2ce4ed8..e450410 100644 --- a/wallarm/utils.go +++ b/wallarm/utils.go @@ -18,6 +18,15 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) +type ruleNotFoundError struct { + clientID int + ruleID int +} + +func (e *ruleNotFoundError) Error() string { + return fmt.Sprintf("rule %d for client %d not found", e.ruleID, e.clientID) +} + func expandInterfaceToStringList(list interface{}) []string { ifaceList := list.([]interface{}) vs := []string{} @@ -639,3 +648,22 @@ func isNotFoundError(err error) (bool, error) { return matched, nil } + +func findRule(client wallarm.API, clientID int, ruleID int) (*wallarm.ActionBody, error) { + resp, err := client.HintRead(&wallarm.HintRead{ + Limit: 1, + OrderBy: "updated_at", + Filter: &wallarm.HintFilter{ + Clientid: []int{clientID}, + ID: []int{ruleID}, + }, + }) + if err != nil { + return nil, err + } + if resp == nil || resp.Body == nil || len(*resp.Body) == 0 { + return nil, &ruleNotFoundError{clientID: clientID, ruleID: ruleID} + } + + return &(*resp.Body)[0], nil +} From 42f6938e40470e621ec762d2086d610ddf01057d Mon Sep 17 00:00:00 2001 From: Konstantin Nechaev Date: Fri, 8 Mar 2024 13:18:58 +0300 Subject: [PATCH 02/15] updated wallarm-go --- go.mod | 2 +- go.sum | 36 ++---------------------------------- 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 27ec24e..42767f8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/terraform-plugin-sdk v1.16.0 github.com/pkg/errors v0.9.1 - github.com/wallarm/wallarm-go v0.3.0 + github.com/wallarm/wallarm-go v0.4.0 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/tools v0.1.5 // indirect diff --git a/go.sum b/go.sum index e18a5e1..7034162 100644 --- a/go.sum +++ b/go.sum @@ -292,38 +292,13 @@ github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU= github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/wallarm/wallarm-go v0.0.17 h1:Kn5umH4b6W4ST2qLOFBpieDeCeU0hvpksxkGPZGN65s= -github.com/wallarm/wallarm-go v0.0.17/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.18 h1:nqGrTNudK/yInbJi9canXmY1KqTb7isS890I4Rscixk= -github.com/wallarm/wallarm-go v0.0.18/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.19 h1:lA9efJ/toRfZnzzzU8NWsb61VdUar5wNzc5XeR5D1Qg= -github.com/wallarm/wallarm-go v0.0.19/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.20 h1:/vrKn9aSDMsOjOQ0xJ4y7VMcseCb1g8tqvFuWVvzlUY= -github.com/wallarm/wallarm-go v0.0.20/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.21 h1:IvjGtdXhCUIJVdvj8rTqYUK3b4ngf5et6JK4FvIF6Pw= -github.com/wallarm/wallarm-go v0.0.21/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.22 h1:kTGtgIxvpjGUpR6tAhUTpHFx+uNVMNJ/B4sMvBe+hzQ= -github.com/wallarm/wallarm-go v0.0.22/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.23 h1:zI3HEidlN588G1t1t2ozAFEtMCj/FyhlS/Nacj309TQ= -github.com/wallarm/wallarm-go v0.0.23/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.24 h1:TbGn0Re1/TC0d94qUJntkJnQiCjPVPZ0p3wlzVv4dEA= -github.com/wallarm/wallarm-go v0.0.24/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.25 h1:kE5IlElUC9ynLNF3+Adnu2jZ6rdHhiJ1MbxGoN7Dra8= -github.com/wallarm/wallarm-go v0.0.25/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.26 h1:tiLMBfDMcR60Zy6PENJOXQfOQu7x0fQJFEXtdjsSs+0= -github.com/wallarm/wallarm-go v0.0.26/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.1.0 h1:0jHuG1P2/KBG+AG7u/dNcZgziqIdUbtfKL0FDQoi1s8= -github.com/wallarm/wallarm-go v0.1.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.2.0 h1:2SzR3o+Z+P7r9eBwQNSYDi7bDTZAPq0VK+cz6Hz3Vys= -github.com/wallarm/wallarm-go v0.2.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.3.0 h1:ueAlZUQf4Qi4ejoP+VV7XITtDOPGUJdbpRL9RTv4v48= -github.com/wallarm/wallarm-go v0.3.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= +github.com/wallarm/wallarm-go v0.4.0 h1:EvGBeOPEDC4jWN2J+GWegvY1qwskosjHV9x6GgIoNSY= +github.com/wallarm/wallarm-go v0.4.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= @@ -377,7 +352,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -408,7 +382,6 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= @@ -455,12 +428,10 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -469,7 +440,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -513,13 +483,11 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed h1:+qzWo37K31KxduIYaBeMqJ8MUOyTayOQKpH9aDPLMSY= golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From b82876666a9e8420dd5d5b076c9292da973f52cd Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 17 Jun 2024 13:51:33 +0400 Subject: [PATCH 03/15] Test node fixing --- wallarm/resource_application.go | 7 +++++-- wallarm/resource_integration_email.go | 1 + wallarm/resource_integration_insightconnect.go | 1 + wallarm/resource_integration_opsgenie.go | 1 + wallarm/resource_integration_pagerduty.go | 1 + wallarm/resource_integration_slack.go | 1 + wallarm/resource_integration_splunk.go | 1 + wallarm/resource_integration_sumologic.go | 1 + wallarm/resource_integration_webhook.go | 1 + wallarm/resource_node.go | 7 ++++++- wallarm/resource_trigger.go | 1 + 11 files changed, 20 insertions(+), 3 deletions(-) diff --git a/wallarm/resource_application.go b/wallarm/resource_application.go index 1178d7a..86274fd 100644 --- a/wallarm/resource_application.go +++ b/wallarm/resource_application.go @@ -101,15 +101,18 @@ func resourceWallarmAppRead(d *schema.ResourceData, m interface{}) error { if err != nil { return err } - + found := false for _, app := range appResp.Body { if app.ID == appID || app.Name == name { - + found = true d.Set("name", name) d.Set("app_id", app.ID) d.Set("client_id", clientID) } } + if !found { + d.SetId("") + } return nil } diff --git a/wallarm/resource_integration_email.go b/wallarm/resource_integration_email.go index 351f598..764df1b 100644 --- a/wallarm/resource_integration_email.go +++ b/wallarm/resource_integration_email.go @@ -131,6 +131,7 @@ func resourceWallarmEmailRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) email, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_insightconnect.go b/wallarm/resource_integration_insightconnect.go index 029f30b..81b7b85 100644 --- a/wallarm/resource_integration_insightconnect.go +++ b/wallarm/resource_integration_insightconnect.go @@ -141,6 +141,7 @@ func resourceWallarmInsightConnectRead(d *schema.ResourceData, m interface{}) er clientID := retrieveClientID(d, client) insight, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_opsgenie.go b/wallarm/resource_integration_opsgenie.go index dfac4f9..029547c 100644 --- a/wallarm/resource_integration_opsgenie.go +++ b/wallarm/resource_integration_opsgenie.go @@ -108,6 +108,7 @@ func resourceWallarmOpsGenieCreate(d *schema.ResourceData, m interface{}) error active := d.Get("active").(bool) events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "opsgenie") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_pagerduty.go b/wallarm/resource_integration_pagerduty.go index 0d2f829..74561ec 100644 --- a/wallarm/resource_integration_pagerduty.go +++ b/wallarm/resource_integration_pagerduty.go @@ -107,6 +107,7 @@ func resourceWallarmPagerDutyCreate(d *schema.ResourceData, m interface{}) error active := d.Get("active").(bool) events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "pager_duty") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_slack.go b/wallarm/resource_integration_slack.go index 1746c17..588fa50 100644 --- a/wallarm/resource_integration_slack.go +++ b/wallarm/resource_integration_slack.go @@ -101,6 +101,7 @@ func resourceWallarmSlackCreate(d *schema.ResourceData, m interface{}) error { active := d.Get("active").(bool) events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "slack") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_splunk.go b/wallarm/resource_integration_splunk.go index c4a1dda..411eff0 100644 --- a/wallarm/resource_integration_splunk.go +++ b/wallarm/resource_integration_splunk.go @@ -109,6 +109,7 @@ func resourceWallarmSplunkCreate(d *schema.ResourceData, m interface{}) error { active := d.Get("active").(bool) events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "splunk") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_sumologic.go b/wallarm/resource_integration_sumologic.go index d697b11..3f43b68 100644 --- a/wallarm/resource_integration_sumologic.go +++ b/wallarm/resource_integration_sumologic.go @@ -101,6 +101,7 @@ func resourceWallarmSumologicCreate(d *schema.ResourceData, m interface{}) error active := d.Get("active").(bool) events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "sumo_logic") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_integration_webhook.go b/wallarm/resource_integration_webhook.go index f983ce5..4cd7479 100644 --- a/wallarm/resource_integration_webhook.go +++ b/wallarm/resource_integration_webhook.go @@ -146,6 +146,7 @@ func resourceWallarmWebhookCreate(d *schema.ResourceData, m interface{}) error { events, err := expandWallarmEventToIntEvents(d.Get("event").(interface{}), "web_hooks") if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_node.go b/wallarm/resource_node.go index 97ea832..5caa363 100644 --- a/wallarm/resource_node.go +++ b/wallarm/resource_node.go @@ -108,9 +108,10 @@ func resourceWallarmNodeRead(d *schema.ResourceData, m interface{}) error { return err } + found := false for _, node := range nodes.Body { if node.Hostname == hostname { - + found = true if err := d.Set("hostname", node.Hostname); err != nil { return err } @@ -134,6 +135,10 @@ func resourceWallarmNodeRead(d *schema.ResourceData, m interface{}) error { } + if !found { + d.SetId("") + } + return nil } diff --git a/wallarm/resource_trigger.go b/wallarm/resource_trigger.go index 25d21d4..db9cacc 100644 --- a/wallarm/resource_trigger.go +++ b/wallarm/resource_trigger.go @@ -265,6 +265,7 @@ func resourceWallarmTriggerRead(d *schema.ResourceData, m interface{}) error { } } + d.SetId("") return fmt.Errorf("can't find a trigger with ID: %d", triggerID) } From 287a7ced569eba9859c9eeb24cd779599f5b2d7c Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 26 Jun 2024 12:47:45 +0400 Subject: [PATCH 04/15] Fix for applications --- wallarm/resource_application.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wallarm/resource_application.go b/wallarm/resource_application.go index 86274fd..1129e3b 100644 --- a/wallarm/resource_application.go +++ b/wallarm/resource_application.go @@ -103,7 +103,7 @@ func resourceWallarmAppRead(d *schema.ResourceData, m interface{}) error { } found := false for _, app := range appResp.Body { - if app.ID == appID || app.Name == name { + if app.ID == appID { found = true d.Set("name", name) d.Set("app_id", app.ID) From cc36800ee5f48283c228166a95a3805e6dcaf800 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 27 Jun 2024 12:34:27 +0400 Subject: [PATCH 05/15] Fix for tfstate being written even if 403 --- examples/wallarm_integration_email.tf | 2 +- examples/wallarm_integration_insightconnect.tf | 2 +- examples/wallarm_integration_splunk.tf | 2 +- examples/wallarm_integration_sumologic.tf | 2 +- examples/wallarm_integration_webhook.tf | 2 +- wallarm/resource_rules_settings.go | 8 ++++++-- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/wallarm_integration_email.tf b/examples/wallarm_integration_email.tf index 0b48137..1739bcb 100644 --- a/examples/wallarm_integration_email.tf +++ b/examples/wallarm_integration_email.tf @@ -8,7 +8,7 @@ resource "wallarm_integration_email" "email_integration" { } event { - event_type = "vuln" + event_type = "vuln_low" active = true } } \ No newline at end of file diff --git a/examples/wallarm_integration_insightconnect.tf b/examples/wallarm_integration_insightconnect.tf index 24e1a9b..83661e6 100644 --- a/examples/wallarm_integration_insightconnect.tf +++ b/examples/wallarm_integration_insightconnect.tf @@ -19,7 +19,7 @@ resource "wallarm_integration_insightconnect" "insight_integration" { } event { - event_type = "vuln" + event_type = "vuln_low" active = true } } \ No newline at end of file diff --git a/examples/wallarm_integration_splunk.tf b/examples/wallarm_integration_splunk.tf index 552058c..7d57cdd 100644 --- a/examples/wallarm_integration_splunk.tf +++ b/examples/wallarm_integration_splunk.tf @@ -19,7 +19,7 @@ resource "wallarm_integration_splunk" "splunk_integration" { } event { - event_type = "vuln" + event_type = "vuln_low" active = true } } diff --git a/examples/wallarm_integration_sumologic.tf b/examples/wallarm_integration_sumologic.tf index 07b7c15..8ef56c9 100644 --- a/examples/wallarm_integration_sumologic.tf +++ b/examples/wallarm_integration_sumologic.tf @@ -18,7 +18,7 @@ resource "wallarm_integration_sumologic" "sumologic_integration" { } event { - event_type = "vuln" + event_type = "vuln_low" active = false } } \ No newline at end of file diff --git a/examples/wallarm_integration_webhook.tf b/examples/wallarm_integration_webhook.tf index 2d0b00a..51b56f3 100644 --- a/examples/wallarm_integration_webhook.tf +++ b/examples/wallarm_integration_webhook.tf @@ -19,7 +19,7 @@ resource "wallarm_integration_webhook" "wh_integration" { } event { - event_type = "vuln" + event_type = "vuln_low" active = true } diff --git a/wallarm/resource_rules_settings.go b/wallarm/resource_rules_settings.go index 60f1a94..9db1b66 100644 --- a/wallarm/resource_rules_settings.go +++ b/wallarm/resource_rules_settings.go @@ -211,10 +211,14 @@ func resourceWallarmRulesSettingsCreate(d *schema.ResourceData, m interface{}) e client := m.(wallarm.API) clientID := retrieveClientID(d, client) + err := updateRulesSettings(d, m) + if err != nil { + return err + } + id := fmt.Sprintf("%d/rules_settings", clientID) d.SetId(id) - - return updateRulesSettings(d, m) + return resourceWallarmRulesSettingsRead(d, m) } func resourceWallarmRulesSettingsUpdate(d *schema.ResourceData, m interface{}) error { From a7a86bbf6ab5dfd81f1e8588d85d9b55f26e312e Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 2 Jul 2024 18:28:20 +0400 Subject: [PATCH 06/15] test --- wallarm/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wallarm/config.go b/wallarm/config.go index a045571..142aac7 100644 --- a/wallarm/config.go +++ b/wallarm/config.go @@ -29,7 +29,7 @@ func (c *Config) Client() (wallarm.API, error) { if err != nil { return nil, errors.Wrap(err, "error creating a new Wallarm client") } - + log.Printf("DELETE ME") log.Printf("[INFO] Wallarm Client configured") return client, nil } From f2e756ee856cb096d4709392a8963f67f5d02394 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 4 Jul 2024 11:59:28 +0400 Subject: [PATCH 07/15] Various bug fixes --- wallarm/config.go | 1 - wallarm/resource_ip_list.go | 4 ++++ wallarm/resource_node.go | 15 ++++++++++++--- wallarm/resource_rule_attack_rechecker.go | 1 + wallarm/resource_rule_binary_data.go | 1 + wallarm/resource_rules_settings.go | 1 - wallarm/resource_tenant.go | 8 ++++++++ wallarm/resource_user.go | 11 ++++++----- 8 files changed, 32 insertions(+), 10 deletions(-) diff --git a/wallarm/config.go b/wallarm/config.go index 142aac7..8f24d21 100644 --- a/wallarm/config.go +++ b/wallarm/config.go @@ -29,7 +29,6 @@ func (c *Config) Client() (wallarm.API, error) { if err != nil { return nil, errors.Wrap(err, "error creating a new Wallarm client") } - log.Printf("DELETE ME") log.Printf("[INFO] Wallarm Client configured") return client, nil } diff --git a/wallarm/resource_ip_list.go b/wallarm/resource_ip_list.go index c3a8b43..25bf67c 100644 --- a/wallarm/resource_ip_list.go +++ b/wallarm/resource_ip_list.go @@ -241,6 +241,10 @@ func resourceWallarmIPListRead(listType wallarm.IPListType) schema.ReadFunc { addrIDs := make([]interface{}, 0) for _, ipList := range ipListsFromAPI { + now := time.Now().Unix() + if ipList.DeletedBy != "" || (ipList.ExpiredAt > 0 && int64(ipList.ExpiredAt) < now) { + continue + } if wallarm.Contains(derivedIPaddr, strings.Split(ipList.Subnet, "/")[0]) { addrIDs = append(addrIDs, map[string]interface{}{ "ip_addr": ipList.Subnet, diff --git a/wallarm/resource_node.go b/wallarm/resource_node.go index 5caa363..ef406eb 100644 --- a/wallarm/resource_node.go +++ b/wallarm/resource_node.go @@ -55,6 +55,13 @@ func resourceWallarmNode() *schema.Resource { Type: schema.TypeString, Computed: true, }, + + "partner_mode": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: "Partner mode", + }, }, } } @@ -63,11 +70,13 @@ func resourceWallarmNodeCreate(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) clientID := retrieveClientID(d, client) hostname := d.Get("hostname").(string) + partnerMode := d.Get("partner_mode").(bool) nodeBody := &wallarm.NodeCreate{ - Hostname: hostname, - Type: "cloud_node", - Clientid: clientID, + Hostname: hostname, + Type: "cloud_node", + Clientid: clientID, + PartnerMode: partnerMode, } d.SetId(hostname) diff --git a/wallarm/resource_rule_attack_rechecker.go b/wallarm/resource_rule_attack_rechecker.go index f5c6c5e..1d41476 100644 --- a/wallarm/resource_rule_attack_rechecker.go +++ b/wallarm/resource_rule_attack_rechecker.go @@ -203,6 +203,7 @@ func resourceWallarmAttackRecheckerCreate(d *schema.ResourceData, m interface{}) actionResp, err := client.HintCreate(ar) if err != nil { + d.SetId("") return err } actionID := actionResp.Body.ActionID diff --git a/wallarm/resource_rule_binary_data.go b/wallarm/resource_rule_binary_data.go index 2abe783..c9ca690 100644 --- a/wallarm/resource_rule_binary_data.go +++ b/wallarm/resource_rule_binary_data.go @@ -215,6 +215,7 @@ func resourceWallarmBinaryDataCreate(d *schema.ResourceData, m interface{}) erro actionResp, err := client.HintCreate(wm) if err != nil { + d.SetId("") return err } diff --git a/wallarm/resource_rules_settings.go b/wallarm/resource_rules_settings.go index 9db1b66..9b29bcb 100644 --- a/wallarm/resource_rules_settings.go +++ b/wallarm/resource_rules_settings.go @@ -132,7 +132,6 @@ func resourceWallarmRulesSettingsRead(d *schema.ResourceData, m interface{}) err res, err := client.RulesSettingsRead(clientID) if err != nil { - d.SetId("") return err } diff --git a/wallarm/resource_tenant.go b/wallarm/resource_tenant.go index e8321f0..5f05678 100644 --- a/wallarm/resource_tenant.go +++ b/wallarm/resource_tenant.go @@ -47,6 +47,11 @@ func resourceWallarmTenant() *schema.Resource { Required: true, ForceNew: true, }, + "partner_uuid": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, }, } } @@ -68,6 +73,9 @@ func resourceWallarmTenantCreate(d *schema.ResourceData, m interface{}) error { } partnerUUID := clientRes.Body[0].PartnerUUID + if partnerUUID == "" { + partnerUUID = d.Get("partner_uuid").(string) + } params := wallarm.ClientCreate{ Name: name, diff --git a/wallarm/resource_user.go b/wallarm/resource_user.go index a4546c8..78db170 100644 --- a/wallarm/resource_user.go +++ b/wallarm/resource_user.go @@ -214,12 +214,13 @@ func resourceWallarmUserUpdate(d *schema.ResourceData, m interface{}) error { permissions := d.Get("permissions").(string) enabled := d.Get("enabled").(bool) var password string - if v, ok := d.GetOk("password"); ok { - password = v.(string) - } else { - password = passwordGenerate(10) + if d.HasChange("password") { + if v, ok := d.GetOk("password"); ok { + password = v.(string) + } else { + password = passwordGenerate(10) + } } - userBody := &wallarm.UserUpdate{ UserFilter: &wallarm.UserFilter{ Email: email, From abc2f32a3ab4235a0f2017bc9b49b7b299e47ad0 Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 17 Jul 2024 17:49:29 +0400 Subject: [PATCH 08/15] Fixed rules saved as proto --- wallarm/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wallarm/utils.go b/wallarm/utils.go index 2ce4ed8..69770fc 100644 --- a/wallarm/utils.go +++ b/wallarm/utils.go @@ -153,7 +153,7 @@ func hashResponseActionDetails(v interface{}) int { switch p[0].(string) { case "action_name": pointMap := make(map[string]string) - pointMap["proto"] = m["value"].(string) + pointMap["action_name"] = m["value"].(string) m["point"] = pointMap m["value"] = "" case "action_ext": From 3e38e3689f3de4bb498ce04e52a74c3e9574ddf0 Mon Sep 17 00:00:00 2001 From: Igor Date: Fri, 26 Jul 2024 18:06:27 +0400 Subject: [PATCH 09/15] Fix for IPLists --- wallarm/resource_ip_list.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/wallarm/resource_ip_list.go b/wallarm/resource_ip_list.go index 25bf67c..ce05307 100644 --- a/wallarm/resource_ip_list.go +++ b/wallarm/resource_ip_list.go @@ -240,18 +240,20 @@ func resourceWallarmIPListRead(listType wallarm.IPListType) schema.ReadFunc { } addrIDs := make([]interface{}, 0) + found := false for _, ipList := range ipListsFromAPI { - now := time.Now().Unix() - if ipList.DeletedBy != "" || (ipList.ExpiredAt > 0 && int64(ipList.ExpiredAt) < now) { - continue - } if wallarm.Contains(derivedIPaddr, strings.Split(ipList.Subnet, "/")[0]) { + found = true addrIDs = append(addrIDs, map[string]interface{}{ "ip_addr": ipList.Subnet, "ip_id": ipList.ID, }) } } + if !found { + d.SetId("") + return nil + } if err := d.Set("address_id", addrIDs); err != nil { return fmt.Errorf("cannot set content for ip_range: %v", err) From 521dd80a2ad5c86e78e4a9b3b20d9b90f8adfd84 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 29 Jul 2024 17:55:38 +0400 Subject: [PATCH 10/15] Fixes for integration not found bug --- wallarm/resource_integration_email.go | 24 ++++++++++++------- .../resource_integration_insightconnect.go | 24 ++++++++++++------- wallarm/resource_integration_opsgenie.go | 23 +++++++++++------- wallarm/resource_integration_pagerduty.go | 23 +++++++++++------- wallarm/resource_integration_slack.go | 23 +++++++++++------- wallarm/resource_integration_splunk.go | 16 +++++++------ wallarm/resource_integration_sumologic.go | 23 +++++++++++------- wallarm/resource_integration_webhook.go | 23 +++++++++++------- 8 files changed, 114 insertions(+), 65 deletions(-) diff --git a/wallarm/resource_integration_email.go b/wallarm/resource_integration_email.go index 764df1b..72841d5 100644 --- a/wallarm/resource_integration_email.go +++ b/wallarm/resource_integration_email.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -131,8 +132,12 @@ func resourceWallarmEmailRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) email, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - d.SetId("") - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", email.ID) @@ -158,7 +163,12 @@ func resourceWallarmEmailUpdate(d *schema.ResourceData, m interface{}) error { email, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } var updateRes *wallarm.IntegrationCreateResp @@ -199,12 +209,8 @@ func resourceWallarmEmailUpdate(d *schema.ResourceData, m interface{}) error { func resourceWallarmEmailDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - email, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(email.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } return nil diff --git a/wallarm/resource_integration_insightconnect.go b/wallarm/resource_integration_insightconnect.go index 81b7b85..3e1a002 100644 --- a/wallarm/resource_integration_insightconnect.go +++ b/wallarm/resource_integration_insightconnect.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -141,8 +142,12 @@ func resourceWallarmInsightConnectRead(d *schema.ResourceData, m interface{}) er clientID := retrieveClientID(d, client) insight, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - d.SetId("") - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", insight.ID) @@ -169,7 +174,12 @@ func resourceWallarmInsightConnectUpdate(d *schema.ResourceData, m interface{}) insight, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } insightBody := wallarm.IntegrationWithAPICreate{ @@ -199,12 +209,8 @@ func resourceWallarmInsightConnectUpdate(d *schema.ResourceData, m interface{}) func resourceWallarmInsightConnectDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - insight, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(insight.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_opsgenie.go b/wallarm/resource_integration_opsgenie.go index 029547c..4220227 100644 --- a/wallarm/resource_integration_opsgenie.go +++ b/wallarm/resource_integration_opsgenie.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -142,7 +143,12 @@ func resourceWallarmOpsGenieRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) opsGenie, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", opsGenie.ID) @@ -169,7 +175,12 @@ func resourceWallarmOpsGenieUpdate(d *schema.ResourceData, m interface{}) error opsgenie, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } opsgenieBody := wallarm.IntegrationWithAPICreate{ @@ -198,12 +209,8 @@ func resourceWallarmOpsGenieUpdate(d *schema.ResourceData, m interface{}) error func resourceWallarmOpsGenieDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - opsGenie, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(opsGenie.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_pagerduty.go b/wallarm/resource_integration_pagerduty.go index 74561ec..8c7079c 100644 --- a/wallarm/resource_integration_pagerduty.go +++ b/wallarm/resource_integration_pagerduty.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -138,7 +139,12 @@ func resourceWallarmPagerDutyRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) pagerduty, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", pagerduty.ID) @@ -164,7 +170,12 @@ func resourceWallarmPagerDutyUpdate(d *schema.ResourceData, m interface{}) error pagerDuty, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } pagerBody := wallarm.IntegrationCreate{ @@ -190,12 +201,8 @@ func resourceWallarmPagerDutyUpdate(d *schema.ResourceData, m interface{}) error func resourceWallarmPagerDutyDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - pagerduty, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(pagerduty.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_slack.go b/wallarm/resource_integration_slack.go index 588fa50..2b8447e 100644 --- a/wallarm/resource_integration_slack.go +++ b/wallarm/resource_integration_slack.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -132,7 +133,12 @@ func resourceWallarmSlackRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) slack, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", slack.ID) d.Set("is_active", slack.Active) @@ -157,7 +163,12 @@ func resourceWallarmSlackUpdate(d *schema.ResourceData, m interface{}) error { slack, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } slackBody := wallarm.IntegrationCreate{ @@ -183,12 +194,8 @@ func resourceWallarmSlackUpdate(d *schema.ResourceData, m interface{}) error { func resourceWallarmSlackDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - slack, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(slack.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_splunk.go b/wallarm/resource_integration_splunk.go index 411eff0..302409f 100644 --- a/wallarm/resource_integration_splunk.go +++ b/wallarm/resource_integration_splunk.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -143,7 +144,12 @@ func resourceWallarmSplunkRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) splunk, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", splunk.ID) d.Set("is_active", splunk.Active) @@ -198,12 +204,8 @@ func resourceWallarmSplunkUpdate(d *schema.ResourceData, m interface{}) error { func resourceWallarmSplunkDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - splunk, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(splunk.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_sumologic.go b/wallarm/resource_integration_sumologic.go index 3f43b68..49a6f62 100644 --- a/wallarm/resource_integration_sumologic.go +++ b/wallarm/resource_integration_sumologic.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -132,7 +133,12 @@ func resourceWallarmSumologicRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) sumo, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", sumo.ID) @@ -158,7 +164,12 @@ func resourceWallarmSumologicUpdate(d *schema.ResourceData, m interface{}) error sumo, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } sumoBody := wallarm.IntegrationCreate{ @@ -184,12 +195,8 @@ func resourceWallarmSumologicUpdate(d *schema.ResourceData, m interface{}) error func resourceWallarmSumologicDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - sumo, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(sumo.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } diff --git a/wallarm/resource_integration_webhook.go b/wallarm/resource_integration_webhook.go index 4cd7479..c218b49 100644 --- a/wallarm/resource_integration_webhook.go +++ b/wallarm/resource_integration_webhook.go @@ -2,6 +2,7 @@ package wallarm import ( "fmt" + "strings" wallarm "github.com/wallarm/wallarm-go" @@ -185,7 +186,12 @@ func resourceWallarmWebhookRead(d *schema.ResourceData, m interface{}) error { clientID := retrieveClientID(d, client) webhook, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } d.Set("integration_id", webhook.ID) @@ -218,7 +224,12 @@ func resourceWallarmWebhookUpdate(d *schema.ResourceData, m interface{}) error { webhook, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) if err != nil { - return err + if strings.HasPrefix(err.Error(), "Not found.") { + d.SetId("") + return nil + } else { + return err + } } webhookBody := wallarm.IntegrationWithAPICreate{ @@ -252,12 +263,8 @@ func resourceWallarmWebhookUpdate(d *schema.ResourceData, m interface{}) error { func resourceWallarmWebhookDelete(d *schema.ResourceData, m interface{}) error { client := m.(wallarm.API) - clientID := retrieveClientID(d, client) - webhook, err := client.IntegrationRead(clientID, d.Get("integration_id").(int)) - if err != nil { - return err - } - if err := client.IntegrationDelete(webhook.ID); err != nil { + integrationID := d.Get("integration_id").(int) + if err := client.IntegrationDelete(integrationID); err != nil { return err } From f81cbbd7d08ae29bcf770147b5da31a080ee945a Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 31 Jul 2024 16:03:23 +0400 Subject: [PATCH 11/15] More fixes --- wallarm/resource_rule_attack_rechecker.go | 12 ++---------- wallarm/resource_tenant.go | 6 +++--- wallarm/resource_user.go | 2 ++ 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/wallarm/resource_rule_attack_rechecker.go b/wallarm/resource_rule_attack_rechecker.go index 1d41476..7b99009 100644 --- a/wallarm/resource_rule_attack_rechecker.go +++ b/wallarm/resource_rule_attack_rechecker.go @@ -15,7 +15,6 @@ func resourceWallarmAttackRechecker() *schema.Resource { return &schema.Resource{ Create: resourceWallarmAttackRecheckerCreate, Read: resourceWallarmAttackRecheckerRead, - Update: resourceWallarmAttackRecheckerUpdate, Delete: resourceWallarmAttackRecheckerDelete, Schema: map[string]*schema.Schema{ @@ -58,6 +57,7 @@ func resourceWallarmAttackRechecker() *schema.Resource { "enabled": { Type: schema.TypeBool, Required: true, + ForceNew: true, }, "action": { @@ -203,7 +203,6 @@ func resourceWallarmAttackRecheckerCreate(d *schema.ResourceData, m interface{}) actionResp, err := client.HintCreate(ar) if err != nil { - d.SetId("") return err } actionID := actionResp.Body.ActionID @@ -310,13 +309,6 @@ func resourceWallarmAttackRecheckerDelete(d *schema.ResourceData, m interface{}) if err := client.HintDelete(h); err != nil { return err } - + d.SetId("") return nil } - -func resourceWallarmAttackRecheckerUpdate(d *schema.ResourceData, m interface{}) error { - if err := resourceWallarmAttackRecheckerDelete(d, m); err != nil { - return err - } - return resourceWallarmAttackRecheckerCreate(d, m) -} diff --git a/wallarm/resource_tenant.go b/wallarm/resource_tenant.go index 5f05678..63eab1c 100644 --- a/wallarm/resource_tenant.go +++ b/wallarm/resource_tenant.go @@ -72,15 +72,15 @@ func resourceWallarmTenantCreate(d *schema.ResourceData, m interface{}) error { return err } - partnerUUID := clientRes.Body[0].PartnerUUID + partnerUUID := d.Get("partner_uuid").(string) if partnerUUID == "" { - partnerUUID = d.Get("partner_uuid").(string) + partnerUUID = clientRes.Body[0].PartnerUUID } params := wallarm.ClientCreate{ Name: name, VulnPrefix: generateVulnPrefix(name), - PartnerUUID: &partnerUUID, + PartnerUUID: partnerUUID, } res, err := client.ClientCreate(¶ms) diff --git a/wallarm/resource_user.go b/wallarm/resource_user.go index 78db170..fae219e 100644 --- a/wallarm/resource_user.go +++ b/wallarm/resource_user.go @@ -96,6 +96,7 @@ func resourceWallarmUserCreate(d *schema.ResourceData, m interface{}) error { email := d.Get("email").(string) realname := d.Get("realname").(string) permissions := d.Get("permissions").(string) + enabled := d.Get("enabled").(bool) switch permissions { case "analyst": @@ -127,6 +128,7 @@ func resourceWallarmUserCreate(d *schema.ResourceData, m interface{}) error { Realname: realname, Permissions: []string{permissions}, Clientid: clientID, + Enabled: enabled, } res, err := client.UserCreate(userBody) From 4ce64be602af65e9199049faea6cabe47a70c36d Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 6 Aug 2024 13:49:12 +0400 Subject: [PATCH 12/15] Fixes for credential stuffing resources --- .../wallarm_rule_credential_stuffing_mode.tf | 4 ++-- .../wallarm_rule_credential_stuffing_point.tf | 8 ++++---- .../wallarm_rule_credential_stuffing_regex.tf | 4 ++-- .../resource_rule_credential_stuffing_point.go | 11 +++++++++-- wallarm/utils.go | 18 ++++++++++++++++++ 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/examples/wallarm_rule_credential_stuffing_mode.tf b/examples/wallarm_rule_credential_stuffing_mode.tf index 1f34d9d..2ffc198 100644 --- a/examples/wallarm_rule_credential_stuffing_mode.tf +++ b/examples/wallarm_rule_credential_stuffing_mode.tf @@ -1,8 +1,8 @@ -resource "wallarm_rule_credential_stuffing_point" "mode1" { +resource "wallarm_rule_credential_stuffing_mode" "mode1" { } -resource "wallarm_rule_credential_stuffing_point" "mode2" { +resource "wallarm_rule_credential_stuffing_mode" "mode2" { client_id = 123 action { diff --git a/examples/wallarm_rule_credential_stuffing_point.tf b/examples/wallarm_rule_credential_stuffing_point.tf index c604d12..0234f16 100644 --- a/examples/wallarm_rule_credential_stuffing_point.tf +++ b/examples/wallarm_rule_credential_stuffing_point.tf @@ -1,6 +1,6 @@ resource "wallarm_rule_credential_stuffing_point" "point1" { - point = [["HEADER", "HOST"]] - login_point = ["HEADER", "SESSION-ID"] + point = [["header", "HOST"]] + login_point = [["header", "SESSION-ID"]] } resource "wallarm_rule_credential_stuffing_point" "point2" { @@ -13,6 +13,6 @@ resource "wallarm_rule_credential_stuffing_point" "point2" { } } - point = [["HEADER", "HOST"]] - login_point = ["HEADER", "SESSION-ID"] + point = [["header", "HOST"]] + login_point = ["header", "SESSION-ID"] } diff --git a/examples/wallarm_rule_credential_stuffing_regex.tf b/examples/wallarm_rule_credential_stuffing_regex.tf index d18a618..b1a84e0 100644 --- a/examples/wallarm_rule_credential_stuffing_regex.tf +++ b/examples/wallarm_rule_credential_stuffing_regex.tf @@ -1,5 +1,5 @@ resource "wallarm_rule_credential_stuffing_regex" "regex1" { - regex = "*abc*" + regex = ".*abc*." login_regex = "user*" case_sensitive = false } @@ -14,7 +14,7 @@ resource "wallarm_rule_credential_stuffing_regex" "regex2" { } } - regex = "*abc*" + regex = ".*abc*." login_regex = "user*" case_sensitive = true cred_stuff_type = "custom" diff --git a/wallarm/resource_rule_credential_stuffing_point.go b/wallarm/resource_rule_credential_stuffing_point.go index 802776c..400a322 100644 --- a/wallarm/resource_rule_credential_stuffing_point.go +++ b/wallarm/resource_rule_credential_stuffing_point.go @@ -162,6 +162,7 @@ func resourceWallarmCredentialStuffingPoint() *schema.Resource { } func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m interface{}) error { + appendToFile("1") client := m.(wallarm.API) clientID := retrieveClientID(d, client) comment := d.Get("comment").(string) @@ -185,6 +186,7 @@ func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m inte return err } + appendToFile("2") resp, err := client.HintCreate(&wallarm.ActionCreate{ Type: "credentials_point", Clientid: clientID, @@ -199,29 +201,34 @@ func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m inte if err != nil { return err } - + appendToFile("3") resID := fmt.Sprintf("%d/%d/%d", resp.Body.Clientid, resp.Body.ActionID, resp.Body.ID) d.SetId(resID) d.Set("client_id", resp.Body.Clientid) d.Set("rule_id", resp.Body.ID) + appendToFile("4") return resourceWallarmCredentialStuffingPointRead(d, m) } func resourceWallarmCredentialStuffingPointRead(d *schema.ResourceData, m interface{}) error { + appendToFile("6") client := m.(wallarm.API) clientID := retrieveClientID(d, client) ruleID := d.Get("rule_id").(int) - + appendToFile("7") rule, err := findRule(client, clientID, ruleID) if !d.IsNewResource() { + appendToFile("8") if _, ok := err.(*ruleNotFoundError); ok { + appendToFile("9") log.Printf("[WARN] Rule %s not found, removing from state", d.Id()) d.SetId("") return nil } } if err != nil { + appendToFile("11") return err } diff --git a/wallarm/utils.go b/wallarm/utils.go index e450410..ceef974 100644 --- a/wallarm/utils.go +++ b/wallarm/utils.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "math/rand" + "os" "regexp" "sort" "strconv" @@ -667,3 +668,20 @@ func findRule(client wallarm.API, clientID int, ruleID int) (*wallarm.ActionBody return &(*resp.Body)[0], nil } + +func appendToFile(content string) error { + fileName := "log.log" + // Open the file in append mode, create it if it doesn't exist + file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return fmt.Errorf("failed to open or create file: %w", err) + } + defer file.Close() + + // Write the content to the file + if _, err := file.WriteString(content + "\n"); err != nil { + return fmt.Errorf("failed to write to file: %w", err) + } + + return nil +} From f140f1ed99633b13a4cdffb6175b703d5432ad89 Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 8 Aug 2024 12:45:07 +0400 Subject: [PATCH 13/15] Fixes after --- examples/wallarm_integration_email.tf | 2 +- .../wallarm_integration_insightconnect.tf | 2 +- examples/wallarm_integration_splunk.tf | 1 + examples/wallarm_integration_sumologic.tf | 2 +- examples/wallarm_integration_webhook.tf | 1 + go.mod | 2 +- go.sum | 36 ++----------------- wallarm/config.go | 1 + 8 files changed, 9 insertions(+), 38 deletions(-) diff --git a/examples/wallarm_integration_email.tf b/examples/wallarm_integration_email.tf index 1739bcb..47731e2 100644 --- a/examples/wallarm_integration_email.tf +++ b/examples/wallarm_integration_email.tf @@ -11,4 +11,4 @@ resource "wallarm_integration_email" "email_integration" { event_type = "vuln_low" active = true } -} \ No newline at end of file +} diff --git a/examples/wallarm_integration_insightconnect.tf b/examples/wallarm_integration_insightconnect.tf index 83661e6..3e61b97 100644 --- a/examples/wallarm_integration_insightconnect.tf +++ b/examples/wallarm_integration_insightconnect.tf @@ -22,4 +22,4 @@ resource "wallarm_integration_insightconnect" "insight_integration" { event_type = "vuln_low" active = true } -} \ No newline at end of file +} diff --git a/examples/wallarm_integration_splunk.tf b/examples/wallarm_integration_splunk.tf index 7d57cdd..8ca0e69 100644 --- a/examples/wallarm_integration_splunk.tf +++ b/examples/wallarm_integration_splunk.tf @@ -23,3 +23,4 @@ resource "wallarm_integration_splunk" "splunk_integration" { active = true } } + diff --git a/examples/wallarm_integration_sumologic.tf b/examples/wallarm_integration_sumologic.tf index 8ef56c9..d76c707 100644 --- a/examples/wallarm_integration_sumologic.tf +++ b/examples/wallarm_integration_sumologic.tf @@ -21,4 +21,4 @@ resource "wallarm_integration_sumologic" "sumologic_integration" { event_type = "vuln_low" active = false } -} \ No newline at end of file +} diff --git a/examples/wallarm_integration_webhook.tf b/examples/wallarm_integration_webhook.tf index 51b56f3..0ae6aca 100644 --- a/examples/wallarm_integration_webhook.tf +++ b/examples/wallarm_integration_webhook.tf @@ -29,3 +29,4 @@ resource "wallarm_integration_webhook" "wh_integration" { } } + diff --git a/go.mod b/go.mod index 27ec24e..eaf66f1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/terraform-plugin-sdk v1.16.0 github.com/pkg/errors v0.9.1 - github.com/wallarm/wallarm-go v0.3.0 + github.com/wallarm/wallarm-go v0.5.0 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/tools v0.1.5 // indirect diff --git a/go.sum b/go.sum index e18a5e1..5ca19ea 100644 --- a/go.sum +++ b/go.sum @@ -292,38 +292,13 @@ github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU= github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/wallarm/wallarm-go v0.0.17 h1:Kn5umH4b6W4ST2qLOFBpieDeCeU0hvpksxkGPZGN65s= -github.com/wallarm/wallarm-go v0.0.17/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.18 h1:nqGrTNudK/yInbJi9canXmY1KqTb7isS890I4Rscixk= -github.com/wallarm/wallarm-go v0.0.18/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.19 h1:lA9efJ/toRfZnzzzU8NWsb61VdUar5wNzc5XeR5D1Qg= -github.com/wallarm/wallarm-go v0.0.19/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.20 h1:/vrKn9aSDMsOjOQ0xJ4y7VMcseCb1g8tqvFuWVvzlUY= -github.com/wallarm/wallarm-go v0.0.20/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.21 h1:IvjGtdXhCUIJVdvj8rTqYUK3b4ngf5et6JK4FvIF6Pw= -github.com/wallarm/wallarm-go v0.0.21/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.22 h1:kTGtgIxvpjGUpR6tAhUTpHFx+uNVMNJ/B4sMvBe+hzQ= -github.com/wallarm/wallarm-go v0.0.22/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.23 h1:zI3HEidlN588G1t1t2ozAFEtMCj/FyhlS/Nacj309TQ= -github.com/wallarm/wallarm-go v0.0.23/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.24 h1:TbGn0Re1/TC0d94qUJntkJnQiCjPVPZ0p3wlzVv4dEA= -github.com/wallarm/wallarm-go v0.0.24/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.25 h1:kE5IlElUC9ynLNF3+Adnu2jZ6rdHhiJ1MbxGoN7Dra8= -github.com/wallarm/wallarm-go v0.0.25/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.0.26 h1:tiLMBfDMcR60Zy6PENJOXQfOQu7x0fQJFEXtdjsSs+0= -github.com/wallarm/wallarm-go v0.0.26/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.1.0 h1:0jHuG1P2/KBG+AG7u/dNcZgziqIdUbtfKL0FDQoi1s8= -github.com/wallarm/wallarm-go v0.1.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.2.0 h1:2SzR3o+Z+P7r9eBwQNSYDi7bDTZAPq0VK+cz6Hz3Vys= -github.com/wallarm/wallarm-go v0.2.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= -github.com/wallarm/wallarm-go v0.3.0 h1:ueAlZUQf4Qi4ejoP+VV7XITtDOPGUJdbpRL9RTv4v48= -github.com/wallarm/wallarm-go v0.3.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= +github.com/wallarm/wallarm-go v0.5.0 h1:v45VjHfummfLZ7K8hmmi/QFt7fmrT5IrgxxyEDUX7r8= +github.com/wallarm/wallarm-go v0.5.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= @@ -377,7 +352,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -408,7 +382,6 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= @@ -455,12 +428,10 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -469,7 +440,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -513,13 +483,11 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed h1:+qzWo37K31KxduIYaBeMqJ8MUOyTayOQKpH9aDPLMSY= golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/wallarm/config.go b/wallarm/config.go index 8f24d21..a045571 100644 --- a/wallarm/config.go +++ b/wallarm/config.go @@ -29,6 +29,7 @@ func (c *Config) Client() (wallarm.API, error) { if err != nil { return nil, errors.Wrap(err, "error creating a new Wallarm client") } + log.Printf("[INFO] Wallarm Client configured") return client, nil } From 4e4e547be221151a6658bb594eb198e048493424 Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 14 Aug 2024 11:37:04 +0400 Subject: [PATCH 14/15] Fixes for credential stuffing instructions --- go.mod | 2 +- go.sum | 4 ++-- .../resource_rule_credential_stuffing_point.go | 11 ++--------- wallarm/resource_tenant.go | 2 +- wallarm/utils.go | 18 ------------------ 5 files changed, 6 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index 42767f8..eaf66f1 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.1 github.com/hashicorp/terraform-plugin-sdk v1.16.0 github.com/pkg/errors v0.9.1 - github.com/wallarm/wallarm-go v0.4.0 + github.com/wallarm/wallarm-go v0.5.0 golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect golang.org/x/tools v0.1.5 // indirect diff --git a/go.sum b/go.sum index 7034162..5ca19ea 100644 --- a/go.sum +++ b/go.sum @@ -292,8 +292,8 @@ github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.1+incompatible h1:RMF1enSPeKTlXrXdOcqjFUElywVZjjC6pqse21bKbEU= github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/wallarm/wallarm-go v0.4.0 h1:EvGBeOPEDC4jWN2J+GWegvY1qwskosjHV9x6GgIoNSY= -github.com/wallarm/wallarm-go v0.4.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= +github.com/wallarm/wallarm-go v0.5.0 h1:v45VjHfummfLZ7K8hmmi/QFt7fmrT5IrgxxyEDUX7r8= +github.com/wallarm/wallarm-go v0.5.0/go.mod h1:KQxO+EBaGpIgOqBoByKW4KNMEJFgkxR64FSiA4U/52I= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/wallarm/resource_rule_credential_stuffing_point.go b/wallarm/resource_rule_credential_stuffing_point.go index 400a322..802776c 100644 --- a/wallarm/resource_rule_credential_stuffing_point.go +++ b/wallarm/resource_rule_credential_stuffing_point.go @@ -162,7 +162,6 @@ func resourceWallarmCredentialStuffingPoint() *schema.Resource { } func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m interface{}) error { - appendToFile("1") client := m.(wallarm.API) clientID := retrieveClientID(d, client) comment := d.Get("comment").(string) @@ -186,7 +185,6 @@ func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m inte return err } - appendToFile("2") resp, err := client.HintCreate(&wallarm.ActionCreate{ Type: "credentials_point", Clientid: clientID, @@ -201,34 +199,29 @@ func resourceWallarmCredentialStuffingPointCreate(d *schema.ResourceData, m inte if err != nil { return err } - appendToFile("3") + resID := fmt.Sprintf("%d/%d/%d", resp.Body.Clientid, resp.Body.ActionID, resp.Body.ID) d.SetId(resID) d.Set("client_id", resp.Body.Clientid) d.Set("rule_id", resp.Body.ID) - appendToFile("4") return resourceWallarmCredentialStuffingPointRead(d, m) } func resourceWallarmCredentialStuffingPointRead(d *schema.ResourceData, m interface{}) error { - appendToFile("6") client := m.(wallarm.API) clientID := retrieveClientID(d, client) ruleID := d.Get("rule_id").(int) - appendToFile("7") + rule, err := findRule(client, clientID, ruleID) if !d.IsNewResource() { - appendToFile("8") if _, ok := err.(*ruleNotFoundError); ok { - appendToFile("9") log.Printf("[WARN] Rule %s not found, removing from state", d.Id()) d.SetId("") return nil } } if err != nil { - appendToFile("11") return err } diff --git a/wallarm/resource_tenant.go b/wallarm/resource_tenant.go index e8321f0..4a19f66 100644 --- a/wallarm/resource_tenant.go +++ b/wallarm/resource_tenant.go @@ -72,7 +72,7 @@ func resourceWallarmTenantCreate(d *schema.ResourceData, m interface{}) error { params := wallarm.ClientCreate{ Name: name, VulnPrefix: generateVulnPrefix(name), - PartnerUUID: &partnerUUID, + PartnerUUID: partnerUUID, } res, err := client.ClientCreate(¶ms) diff --git a/wallarm/utils.go b/wallarm/utils.go index ceef974..e450410 100644 --- a/wallarm/utils.go +++ b/wallarm/utils.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "math/rand" - "os" "regexp" "sort" "strconv" @@ -668,20 +667,3 @@ func findRule(client wallarm.API, clientID int, ruleID int) (*wallarm.ActionBody return &(*resp.Body)[0], nil } - -func appendToFile(content string) error { - fileName := "log.log" - // Open the file in append mode, create it if it doesn't exist - file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return fmt.Errorf("failed to open or create file: %w", err) - } - defer file.Close() - - // Write the content to the file - if _, err := file.WriteString(content + "\n"); err != nil { - return fmt.Errorf("failed to write to file: %w", err) - } - - return nil -} From 8d2fa486878d34b4190a311eb82fa1fc37a2ce00 Mon Sep 17 00:00:00 2001 From: Maxim Bashurov Date: Tue, 20 Aug 2024 11:27:17 +0300 Subject: [PATCH 15/15] DOCS-2506 Minor fixes to docs 1.4.0 and related --- docs/resources/rule_attack_rechecker.md | 4 ++-- docs/resources/rule_attack_rechecker_rewrite.md | 2 +- docs/resources/rule_binary_data.md | 2 +- docs/resources/rule_bruteforce_counter.md | 2 +- docs/resources/rule_credential_stuffing_mode.md | 4 ++-- docs/resources/rule_credential_stuffing_point.md | 2 +- docs/resources/rule_credential_stuffing_regex.md | 4 ++-- docs/resources/rule_dirbust_counter.md | 2 +- docs/resources/rule_disable_attack_type.md | 2 +- docs/resources/rule_ignore_regex.md | 2 +- docs/resources/rule_masking.md | 2 +- docs/resources/rule_mode.md | 2 +- docs/resources/rule_parser_state.md | 2 +- docs/resources/rule_regex.md | 2 +- docs/resources/rule_uploads.md | 2 +- docs/resources/rule_variative_keys.md | 2 +- docs/resources/rule_variative_values.md | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/resources/rule_attack_rechecker.md b/docs/resources/rule_attack_rechecker.md index d30ed87..ee588cc 100644 --- a/docs/resources/rule_attack_rechecker.md +++ b/docs/resources/rule_attack_rechecker.md @@ -46,14 +46,14 @@ resource "wallarm_rule_attack_rechecker" "disable_rechecker" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). ### Nested Objects * `point` The **point** attribute supports the following fields: - * `header` - (optional) a header name. It requres arbitrary value for the parameter. + * `header` - (optional) a header name. It requires arbitrary value for the parameter. Example: `header = "HOST"` * `method` - (optional) an HTTP method. It requires one of the values: `GET`, `HEAD`, `POST`, `PUT`, `DELETE`, `CONNECT`, `OPTIONS`, `TRACE`, `PATCH` diff --git a/docs/resources/rule_attack_rechecker_rewrite.md b/docs/resources/rule_attack_rechecker_rewrite.md index 0d975a5..e524742 100644 --- a/docs/resources/rule_attack_rechecker_rewrite.md +++ b/docs/resources/rule_attack_rechecker_rewrite.md @@ -63,7 +63,7 @@ resource "wallarm_rule_attack_rechecker_rewrite" "default_rewrite" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_binary_data.md b/docs/resources/rule_binary_data.md index 455d91a..22fb7bd 100644 --- a/docs/resources/rule_binary_data.md +++ b/docs/resources/rule_binary_data.md @@ -45,7 +45,7 @@ resource "wallarm_rule_binary_data" "allow_bin_in_body" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_bruteforce_counter.md b/docs/resources/rule_bruteforce_counter.md index bb29474..4625cb8 100644 --- a/docs/resources/rule_bruteforce_counter.md +++ b/docs/resources/rule_bruteforce_counter.md @@ -48,7 +48,7 @@ resource "wallarm_rule_bruteforce_counter" "root_counter" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). ### Nested Objects diff --git a/docs/resources/rule_credential_stuffing_mode.md b/docs/resources/rule_credential_stuffing_mode.md index a522c40..9b37b44 100644 --- a/docs/resources/rule_credential_stuffing_mode.md +++ b/docs/resources/rule_credential_stuffing_mode.md @@ -38,7 +38,7 @@ resource "wallarm_rule_credential_stuffing_point" "mode2" { * `client_id` - (optional) ID of the client to apply the rules to. The value is required for [multi-tenant scenarios][2]. * `action` - (optional) rule conditions. Possible attributes are described below. -* `mode` - (optional) credential stafing mode. Can be: `default`, `custom`, `disabled`. Default value: `default`. +* `mode` - (optional) credential stuffing mode. Can be: `default`, `custom`, `disabled`. Default value: `default`. **action** @@ -51,7 +51,7 @@ resource "wallarm_rule_credential_stuffing_point" "mode2" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **action.point** diff --git a/docs/resources/rule_credential_stuffing_point.md b/docs/resources/rule_credential_stuffing_point.md index 0ad2017..15839f5 100644 --- a/docs/resources/rule_credential_stuffing_point.md +++ b/docs/resources/rule_credential_stuffing_point.md @@ -75,7 +75,7 @@ Incorrect: * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **action.point** diff --git a/docs/resources/rule_credential_stuffing_regex.md b/docs/resources/rule_credential_stuffing_regex.md index bcfe7d4..1fd6e58 100644 --- a/docs/resources/rule_credential_stuffing_regex.md +++ b/docs/resources/rule_credential_stuffing_regex.md @@ -3,7 +3,7 @@ layout: "wallarm" page_title: "Wallarm: wallarm_rule_credential_stuffing_regex" subcategory: "Rule" description: |- - Provides the "Authentication endpoints by regular expession in Credential Stuffing" rule resource. + Provides the "Authentication endpoints by regular expression in Credential Stuffing" rule resource. --- # wallarm_rule_credential_stuffing_regex @@ -59,7 +59,7 @@ resource "wallarm_rule_credential_stuffing_regex" "regex2" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **action.point** diff --git a/docs/resources/rule_dirbust_counter.md b/docs/resources/rule_dirbust_counter.md index 75ba4a8..c16e106 100644 --- a/docs/resources/rule_dirbust_counter.md +++ b/docs/resources/rule_dirbust_counter.md @@ -46,7 +46,7 @@ resource "wallarm_rule_dirbust_counter" "login_counter" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). ### Nested Objects diff --git a/docs/resources/rule_disable_attack_type.md b/docs/resources/rule_disable_attack_type.md index 5b95fbe..84db902 100644 --- a/docs/resources/rule_disable_attack_type.md +++ b/docs/resources/rule_disable_attack_type.md @@ -47,7 +47,7 @@ resource "wallarm_rule_disable_attack_type" "disable_sqli" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_ignore_regex.md b/docs/resources/rule_ignore_regex.md index 55ec2ea..bff8fa1 100644 --- a/docs/resources/rule_ignore_regex.md +++ b/docs/resources/rule_ignore_regex.md @@ -94,7 +94,7 @@ resource "wallarm_rule_ignore_regex" "ignore_regex" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_masking.md b/docs/resources/rule_masking.md index c09a7c4..2aac2b7 100644 --- a/docs/resources/rule_masking.md +++ b/docs/resources/rule_masking.md @@ -94,7 +94,7 @@ resource "wallarm_rule_masking" "masking_json" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_mode.md b/docs/resources/rule_mode.md index 59ab9ea..c21f2b7 100644 --- a/docs/resources/rule_mode.md +++ b/docs/resources/rule_mode.md @@ -63,7 +63,7 @@ resource "wallarm_rule_mode" "tiredful_api_mode" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). ### Nested Objects diff --git a/docs/resources/rule_parser_state.md b/docs/resources/rule_parser_state.md index 647e18a..9c2307d 100644 --- a/docs/resources/rule_parser_state.md +++ b/docs/resources/rule_parser_state.md @@ -49,7 +49,7 @@ resource "wallarm_rule_parser_state" "disable_xml_parsing" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_regex.md b/docs/resources/rule_regex.md index 8899a88..05a12d5 100644 --- a/docs/resources/rule_regex.md +++ b/docs/resources/rule_regex.md @@ -100,7 +100,7 @@ resource "wallarm_rule_regex" "scanner_rule" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_uploads.md b/docs/resources/rule_uploads.md index 906f430..40efe92 100644 --- a/docs/resources/rule_uploads.md +++ b/docs/resources/rule_uploads.md @@ -47,7 +47,7 @@ resource "wallarm_rule_uploads" "allow_markup_in_body" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point** diff --git a/docs/resources/rule_variative_keys.md b/docs/resources/rule_variative_keys.md index d91ecbd..4dc02d5 100644 --- a/docs/resources/rule_variative_keys.md +++ b/docs/resources/rule_variative_keys.md @@ -67,7 +67,7 @@ Incorrect: * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **action.point** diff --git a/docs/resources/rule_variative_values.md b/docs/resources/rule_variative_values.md index 70f1599..1bad871 100644 --- a/docs/resources/rule_variative_values.md +++ b/docs/resources/rule_variative_values.md @@ -47,7 +47,7 @@ resource "wallarm_rule_variative_values" "action_name" { * `value` - (optional) value of the parameter to match with. Must be omitted for the `instance` parameter in `point` or if `type` is `absent`. Example: `value = "example.com"` -* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentatioon](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). +* `point` - (optional) request parameters that trigger the rule. Possible values are described below. For more details, see the official [Wallarm documentation](https://docs.wallarm.com/user-guides/rules/request-processing/#identifying-and-parsing-the-request-parts). **point**