Skip to content

Commit

Permalink
Adding unknownClientsChallenge and blockNonEssentialBots to the waf s…
Browse files Browse the repository at this point in the history
…ecurity ddos rules
  • Loading branch information
Pavel-Koev committed Sep 25, 2024
1 parent 6fdadbe commit 9f35c10
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 31 deletions.
10 changes: 6 additions & 4 deletions examples/example.tf
Original file line number Diff line number Diff line change
Expand Up @@ -444,10 +444,12 @@ resource "incapsula_security_rule_exception" "example-waf-cross-site-scripting-r

# api.acl.ddos Security Rule (one instance per site)
resource "incapsula_waf_security_rule" "example-waf-ddos-rule" {
site_id = incapsula_site.example-site.id
rule_id = "api.threats.ddos"
activation_mode = "api.threats.ddos.activation_mode.on"
ddos_traffic_threshold = "5000"
site_id = incapsula_site.example-site.id
rule_id = "api.threats.ddos"
activation_mode = "api.threats.ddos.activation_mode.on"
ddos_traffic_threshold = "5000"
unknown_clients_challenge = "none"
block_non_essential_bots = "false"
}

# api.threats.ddos Security Rule Sample Exception
Expand Down
4 changes: 3 additions & 1 deletion examples/security_rules.tf
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ resource "incapsula_waf_security_rule" "example-waf-ddos-rule" {
site_id = incapsula_site.example-site.id
rule_id = "api.threats.ddos"
activation_mode = "api.threats.ddos.activation_mode.on"
ddos_traffic_threshold = "5000"
ddos_traffic_threshold = "5000"
unknown_clients_challenge = "none"
block_non_essential_bots = "false"
}

####################################################################
Expand Down
22 changes: 12 additions & 10 deletions incapsula/client_site.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,18 @@ type SiteStatusResponse struct {
Security struct {
Waf struct {
Rules []struct {
Action string `json:"action,omitempty"`
ActionText string `json:"action_text,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
BlockBadBots bool `json:"block_bad_bots,omitempty"`
ChallengeSuspectedBots bool `json:"challenge_suspected_bots,omitempty"`
ActivationMode string `json:"activation_mode,omitempty"`
ActivationModeText string `json:"activation_mode_text,omitempty"`
DdosTrafficThreshold int `json:"ddos_traffic_threshold,omitempty"`
Exceptions []struct {
Action string `json:"action,omitempty"`
ActionText string `json:"action_text,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
BlockBadBots bool `json:"block_bad_bots,omitempty"`
ChallengeSuspectedBots bool `json:"challenge_suspected_bots,omitempty"`
ActivationMode string `json:"activation_mode,omitempty"`
ActivationModeText string `json:"activation_mode_text,omitempty"`
DdosTrafficThreshold int `json:"ddos_traffic_threshold,omitempty"`
UnknownClientsChallenge string `json:"unknown_clients_challenge,omitempty"`
BlockNonEssentialBots bool `json:"block_non_essential_bots,omitempty"`
Exceptions []struct {
Values []struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Expand Down
11 changes: 9 additions & 2 deletions incapsula/client_waf_security_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const botAccessControlRuleID = "api.threats.bot_access_control"
const customRuleDefaultActionID = "api.threats.customRule"

// ConfigureWAFSecurityRule adds an WAF rule
func (c *Client) ConfigureWAFSecurityRule(siteID int, ruleID, securityRuleAction, activationMode, ddosTrafficThreshold, blockBadBots, challengeSuspectedBots string) (*SiteStatusResponse, error) {
func (c *Client) ConfigureWAFSecurityRule(siteID int, ruleID, securityRuleAction, activationMode, ddosTrafficThreshold, unknownClientsChallenge, blockNonEssentialBots, blockBadBots, challengeSuspectedBots string) (*SiteStatusResponse, error) {
// Base URL values
values := url.Values{
"site_id": {strconv.Itoa(siteID)},
Expand All @@ -37,7 +37,14 @@ func (c *Client) ConfigureWAFSecurityRule(siteID int, ruleID, securityRuleAction
} else if ruleID == ddosRuleID {
values.Add("activation_mode", activationMode)
values.Add("ddos_traffic_threshold", ddosTrafficThreshold)
log.Printf("[INFO] Configuring Incapsula WAF rule id (%s) with activation mode (%s) and DDoS traffic threshold (%s) for site id (%d)\n", ruleID, activationMode, ddosTrafficThreshold, siteID)

if unknownClientsChallenge != "" {
values.Add("unknown_clients_challenge", unknownClientsChallenge)
}
if blockNonEssentialBots != "" {
values.Add("block_non_essential_bots", blockNonEssentialBots)
}
log.Printf("[INFO] Configuring Incapsula WAF rule id (%s) with activation mode (%s), DDoS traffic threshold (%s), unknown clients challenge (%s) and block non essential bots (%s) for site id (%d)\n", ruleID, activationMode, ddosTrafficThreshold, unknownClientsChallenge, blockNonEssentialBots, siteID)
} else if ruleID == botAccessControlRuleID {
values.Add("block_bad_bots", blockBadBots)
values.Add("challenge_suspected_bots", challengeSuspectedBots)
Expand Down
24 changes: 14 additions & 10 deletions incapsula/client_waf_security_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestClientConfigureWAFSecurityRuleBadConnection(t *testing.T) {
siteID := 1234
ruleID := "api.threats.backdoor"
securityRuleAction := "badRuleAction"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -50,7 +50,7 @@ func TestClientConfigureWAFSecurityRuleBadJSON(t *testing.T) {
siteID := 1234
ruleID := "api.threats.backdoor"
securityRuleAction := "badRuleAction"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -78,7 +78,7 @@ func TestClientConfigureWAFSecurityRuleInvalidRuleID(t *testing.T) {
siteID := 1234
ruleID := "bad_rule_id"
securityRuleAction := "bad_rule_action"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -106,7 +106,7 @@ func TestClientConfigureWAFSecurityRuleInvalidRuleAction(t *testing.T) {
siteID := 1234
ruleID := "api.threats.backdoor"
securityRuleAction := "bad_rule_action"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -135,7 +135,9 @@ func TestClientConfigureWAFSecurityRuleInvalidRule_activationMode(t *testing.T)
ruleID := backdoorRuleID
activationMode := "api.threats.ddos.activation_mode.on"
ddosTrafficThreshold := "123"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", activationMode, ddosTrafficThreshold, "", "")
unknownClientsChallenge := "none"
blockNonEssentialBots := "false"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", activationMode, ddosTrafficThreshold, unknownClientsChallenge, blockNonEssentialBots, "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -164,7 +166,9 @@ func TestClientConfigureWAFSecurityRuleInvalidRule_ddosThreshold(t *testing.T) {
ruleID := ddosRuleID
activationMode := "api.threats.ddos.activation_mode.on"
ddosTrafficThreshold := "123"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", activationMode, ddosTrafficThreshold, "", "")
unknownClientsChallenge := "none"
blockNonEssentialBots := "false"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", activationMode, ddosTrafficThreshold, unknownClientsChallenge, blockNonEssentialBots, "", "")
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -193,7 +197,7 @@ func TestClientConfigureWAFSecurityRuleInvalidRule_blockBadBots(t *testing.T) {
ruleID := botAccessControlRuleID
challengeSuspectedBots := "true"
blockBadBots := "123"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", "", "", blockBadBots, challengeSuspectedBots)
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", "", "", "", "", blockBadBots, challengeSuspectedBots)
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -222,7 +226,7 @@ func TestClientConfigureWAFSecurityRuleInvalidRule_challengeSuspectedBots(t *tes
ruleID := botAccessControlRuleID
challengeSuspectedBots := "123"
blockBadBots := "true"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", "", "", blockBadBots, challengeSuspectedBots)
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, "", "", "", "", "", blockBadBots, challengeSuspectedBots)
if err == nil {
t.Errorf("Should have received an error")
}
Expand Down Expand Up @@ -254,7 +258,7 @@ func TestClientConfigureWAFSecurityRuleValidRule(t *testing.T) {
siteID := 1234
ruleID := backdoorRuleID
securityRuleAction := "api.threats.action.quarantine_url"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err != nil {
t.Errorf("Should not have received an error")
}
Expand All @@ -279,7 +283,7 @@ func TestClientConfigureWAFSecurityRuleResultCodeStringValidRule(t *testing.T) {
siteID := 1234
ruleID := backdoorRuleID
securityRuleAction := "api.threats.action.quarantine_url"
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "")
configureWAFSecurityRuleResponse, err := client.ConfigureWAFSecurityRule(siteID, ruleID, securityRuleAction, "", "", "", "", "", "")
if err != nil {
t.Errorf("Should not have received an error")
}
Expand Down
43 changes: 41 additions & 2 deletions incapsula/resource_waf_security_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package incapsula

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"log"
"strconv"
"strings"
Expand All @@ -18,6 +19,8 @@ const remoteFileInclusionRuleIDDefaultAction = "api.threats.action.block_request
const sqlInjectionRuleIDDefaultAction = "api.threats.action.block_request"
const ddosRuleIDDefaultActivationMode = "api.threats.ddos.activation_mode.auto"
const ddosRuleIDDefaultDDOSTrafficThreshold = "1000"
const ddosRuleIDDefaultDDOSUnknownClientsChallenge = "cookies"
const ddosRuleIDDefaultDDOSBlockNonEssentialBots = "false"
const botAccessControlBlockBadBotsDefaultAction = "true"
const botAccessControlChallengeSuspectedBotsDefaultAction = "false"

Expand Down Expand Up @@ -79,6 +82,20 @@ func resourceWAFSecurityRule() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"unknown_clients_challenge": {
Description: "Defines a method used for challenging suspicious bots. Possible values: none, cookies, javascript, captcha",
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"none", "cookies", "javascript", "captcha"}, false),
},
"block_non_essential_bots": {
Description: "If non-essential bots should be blocked or not. Possible values: true, false",
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"true", "false"}, false),
},

// Required for rule_id: api.threats.bot_access_control
"block_bad_bots": {
Expand Down Expand Up @@ -111,6 +128,8 @@ func resourceWAFSecurityRuleCreate(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not create Incapsula WAF Rule rule_id (%s) and security_rule_action (%s) on site_id (%d), %s\n", ruleID, d.Get("security_rule_action").(string), d.Get("site_id").(int), err)
Expand All @@ -123,11 +142,13 @@ func resourceWAFSecurityRuleCreate(d *schema.ResourceData, m interface{}) error
"",
d.Get("activation_mode").(string),
d.Get("ddos_traffic_threshold").(string),
d.Get("unknown_clients_challenge").(string),
d.Get("block_non_essential_bots").(string),
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not create Incapsula WAF Rule rule_id (%s) with activation_mode (%s) and ddos_traffic_threshold (%s) on site_id (%d), %s\n", ruleID, d.Get("activation_mode").(string), d.Get("ddos_traffic_threshold").(string), d.Get("site_id").(int), err)
log.Printf("[ERROR] Could not create Incapsula WAF Rule rule_id (%s) with activation_mode (%s), ddos_traffic_threshold (%s), unknown_clients_challenge (%s) and block_non_essential_bots (%s) on site_id (%d), %s\n", ruleID, d.Get("activation_mode").(string), d.Get("ddos_traffic_threshold").(string), d.Get("unknown_clients_challenge").(string), d.Get("block_non_essential_bots").(string), d.Get("site_id").(int), err)
return err
}
} else if ruleID == botAccessControlRuleID {
Expand All @@ -137,6 +158,8 @@ func resourceWAFSecurityRuleCreate(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
d.Get("block_bad_bots").(string),
d.Get("challenge_suspected_bots").(string),
)
Expand Down Expand Up @@ -197,6 +220,8 @@ func resourceWAFSecurityRuleRead(d *schema.ResourceData, m interface{}) error {
case ddosRuleID:
d.Set("activation_mode", entry.ActivationMode)
d.Set("ddos_traffic_threshold", strconv.FormatInt(int64(entry.DdosTrafficThreshold), 10))
d.Set("unknown_clients_challenge", entry.UnknownClientsChallenge)
d.Set("block_non_essential_bots", strconv.FormatBool(entry.BlockNonEssentialBots))
case botAccessControlRuleID:
d.Set("block_bad_bots", strconv.FormatBool(entry.BlockBadBots))
d.Set("challenge_suspected_bots", strconv.FormatBool(entry.ChallengeSuspectedBots))
Expand Down Expand Up @@ -260,6 +285,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with security_rule_action (%s) on site_id (%d) %s\n", ruleID, backdoorRuleIDDefaultAction, d.Get("site_id").(int), err)
Expand All @@ -274,6 +301,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with security_rule_action (%s) on site_id (%d) %s\n", ruleID, crossSiteScriptingRuleIDDefaultAction, d.Get("site_id").(int), err)
Expand All @@ -288,6 +317,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with security_rule_action (%s) on site_id (%d) %s\n", ruleID, illegalResourceAccessRuleIDDefaultAction, d.Get("site_id").(int), err)
Expand All @@ -302,6 +333,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with security_rule_action (%s) on site_id (%d) %s\n", ruleID, remoteFileInclusionRuleIDDefaultAction, d.Get("site_id").(int), err)
Expand All @@ -316,6 +349,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with security_rule_action (%s) on site_id (%d) %s\n", ruleID, sqlInjectionRuleIDDefaultAction, d.Get("site_id").(int), err)
Expand All @@ -328,11 +363,13 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
ddosRuleIDDefaultActivationMode,
ddosRuleIDDefaultDDOSTrafficThreshold,
ddosRuleIDDefaultDDOSUnknownClientsChallenge,
ddosRuleIDDefaultDDOSBlockNonEssentialBots,
"",
"",
)
if err != nil {
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with default_activation_mode (%s) and ddos_traffic_threshold (%s) on site_id (%d) %s\n", ruleID, ddosRuleIDDefaultActivationMode, ddosRuleIDDefaultDDOSTrafficThreshold, d.Get("site_id").(int), err)
log.Printf("[ERROR] Could not reset Incapsula WAF Rule rule_id (%s) with default_activation_mode (%s), ddos_traffic_threshold (%s), unknown_clients_challenge (%s) and block_non_essential_bots (%s) on site_id (%d) %s\n", ruleID, ddosRuleIDDefaultActivationMode, ddosRuleIDDefaultDDOSTrafficThreshold, ddosRuleIDDefaultDDOSUnknownClientsChallenge, ddosRuleIDDefaultDDOSBlockNonEssentialBots, d.Get("site_id").(int), err)
return err
}
case botAccessControlRuleID:
Expand All @@ -342,6 +379,8 @@ func resourceWAFSecurityRuleDelete(d *schema.ResourceData, m interface{}) error
"",
"",
"",
"",
"",
botAccessControlBlockBadBotsDefaultAction,
botAccessControlChallengeSuspectedBotsDefaultAction,
)
Expand Down
4 changes: 4 additions & 0 deletions incapsula/resource_waf_security_rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ resource "incapsula_waf_security_rule" "example-waf-ddos-rule" {
rule_id = "api.threats.ddos"
activation_mode = "api.threats.ddos.activation_mode.on"
ddos_traffic_threshold = "5000"
unknown_clients_challenge = "none"
block_non_essential_bots = "false"
}`, certificateName, siteResourceName,
)
}
Expand Down Expand Up @@ -271,6 +273,8 @@ resource "incapsula_waf_security_rule" "example-waf-ddos-rule" {
rule_id = "api.threats.ddos"
activation_mode = "bad_activation_mode"
ddos_traffic_threshold = "1234"
unknown_clients_challenge = "none"
block_non_essential_bots = "false"
}`, certificateName, siteResourceName,
)
}
Expand Down
Loading

0 comments on commit 9f35c10

Please sign in to comment.