这是indexloc提供的服务,不要输入任何密码
Skip to content

[firewall config resource] Add bot filter support #313

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/firewall_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ type FirewallConfig struct {
CRS map[string]CoreRuleSet `json:"crs,omitempty"`
}
type ManagedRule struct {
Active bool `json:"active"`
Active bool `json:"active"`
Action string `json:"action,omitempty"`
}

type FirewallRule struct {
Expand Down
17 changes: 16 additions & 1 deletion docs/resources/firewall_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ resource "vercel_firewall_config" "managed" {
rfi = { action = "deny" }
gen = { action = "deny" }
}

bot_filter {
action = "log"
active = true
}
}
}

Expand Down Expand Up @@ -230,8 +235,18 @@ Read-Only:

Optional:

- `bot_filter` (Block, Optional) Enable the bot_filter managed ruleset and select action (see [below for nested schema](#nestedblock--managed_rulesets--bot_filter))
- `owasp` (Block, Optional) Enable the owasp managed rulesets and select ruleset behaviors (see [below for nested schema](#nestedblock--managed_rulesets--owasp))

<a id="nestedblock--managed_rulesets--bot_filter"></a>
### Nested Schema for `managed_rulesets.bot_filter`

Optional:

- `action` (String)
- `active` (Boolean)


<a id="nestedblock--managed_rulesets--owasp"></a>
### Nested Schema for `managed_rulesets.owasp`

Expand Down Expand Up @@ -404,7 +419,7 @@ Required:

Optional:

- `action_duration` (String) Forward persistence of a rule aciton
- `action_duration` (String) Forward persistence of a rule action
- `rate_limit` (Attributes) Behavior or a rate limiting action. Required if action is rate_limit (see [below for nested schema](#nestedatt--rules--rule--action--rate_limit))
- `redirect` (Attributes) How to redirect a request. Required if action is redirect (see [below for nested schema](#nestedatt--rules--rule--action--redirect))

Expand Down
5 changes: 5 additions & 0 deletions examples/resources/vercel_firewall_config/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ resource "vercel_firewall_config" "managed" {
rfi = { action = "deny" }
gen = { action = "deny" }
}

bot_filter {
action = "log"
active = true
}
}
}

Expand Down
46 changes: 40 additions & 6 deletions vercel/resource_firewall_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@ Define Custom Rules to shape the way your traffic is handled by the Vercel Edge
},
},
},
"bot_filter": schema.SingleNestedBlock{
Description: "Enable the bot_filter managed ruleset and select action",
Attributes: map[string]schema.Attribute{
"active": schema.BoolAttribute{
Optional: true,
},
"action": schema.StringAttribute{
Optional: true,
},
},
},
},
},
"rules": schema.SingleNestedBlock{
Expand Down Expand Up @@ -255,7 +266,7 @@ Define Custom Rules to shape the way your traffic is handled by the Vercel Edge
},
},
"action_duration": schema.StringAttribute{
Description: "Forward persistence of a rule aciton",
Description: "Forward persistence of a rule action",
Optional: true,
},
},
Expand Down Expand Up @@ -443,7 +454,8 @@ type FirewallConfig struct {
}

type FirewallManagedRulesets struct {
OWASP *CRSRule `tfsdk:"owasp"`
OWASP *CRSRule `tfsdk:"owasp"`
BotFilter *BotFilterConfig `tfsdk:"bot_filter"`
}

type CRSRule struct {
Expand Down Expand Up @@ -479,6 +491,11 @@ type CRSRuleConfig struct {
Action types.String `tfsdk:"action"`
}

type BotFilterConfig struct {
Active types.Bool `tfsdk:"active"`
Action types.String `tfsdk:"action"`
}

type FirewallRules struct {
Rules []FirewallRule `tfsdk:"rule"`
}
Expand Down Expand Up @@ -756,7 +773,7 @@ func fromCRS(conf map[string]client.CoreRuleSet, refMr *FirewallManagedRulesets)
if refMr != nil && refMr.OWASP != nil {
ref = refMr.OWASP
}
if conf == nil || ref == nil {
if conf == nil || ref == nil || refMr.OWASP == nil {
return nil
}
return &CRSRule{
Expand Down Expand Up @@ -838,10 +855,20 @@ func fromClient(conf client.FirewallConfig, state FirewallConfig) (FirewallConfi
cfg.IPRules = &IPRules{Rules: ipRules}
}

managedRulesets := &FirewallManagedRulesets{}
if conf.ManagedRulesets != nil && conf.CRS != nil {
if len(conf.ManagedRulesets) > 0 {
managedRulesets := &FirewallManagedRulesets{}
cfg.ManagedRulesets = managedRulesets
cfg.ManagedRulesets.OWASP = fromCRS(conf.CRS, state.ManagedRulesets)
if conf.CRS != nil && state.ManagedRulesets != nil {
cfg.ManagedRulesets.OWASP = fromCRS(conf.CRS, state.ManagedRulesets)
}
botFilter, botFilterExist := conf.ManagedRulesets["bot_filter"]
if botFilterExist {
botFilterConf := &BotFilterConfig{
Active: types.BoolValue(botFilter.Active),
Action: types.StringValue(botFilter.Action),
}
cfg.ManagedRulesets.BotFilter = botFilterConf
}
}

return cfg, nil
Expand Down Expand Up @@ -870,6 +897,13 @@ func (f *FirewallConfig) toClient() (client.FirewallConfig, error) {
}
}
}
botFilter := f.ManagedRulesets.BotFilter
if botFilter != nil {
conf.ManagedRulesets["bot_filter"] = client.ManagedRule{
Active: botFilter.Active.ValueBool(),
Action: botFilter.Action.ValueString(),
}
}
}
if f.Rules != nil && len(f.Rules.Rules) > 0 {
for _, rule := range f.Rules.Rules {
Expand Down
57 changes: 57 additions & 0 deletions vercel/resource_firewall_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,15 @@ func TestAcc_FirewallConfigResource(t *testing.T) {
"vercel_firewall_config.ips",
"ip_rules.rule.2.hostname",
"*"),

resource.TestCheckResourceAttr(
"vercel_firewall_config.botfilter",
"managed_rulesets.bot_filter.action",
"challenge"),
resource.TestCheckResourceAttr(
"vercel_firewall_config.botfilter",
"managed_rulesets.bot_filter.active",
"true"),
),
},
{
Expand All @@ -186,6 +195,11 @@ func TestAcc_FirewallConfigResource(t *testing.T) {
ResourceName: "vercel_firewall_config.ips",
ImportStateIdFunc: getFirewallImportID("vercel_firewall_config.ips"),
},
{
ImportState: true,
ResourceName: "vercel_firewall_config.botfilter",
ImportStateIdFunc: getFirewallImportID("vercel_firewall_config.botfilter"),
},
{
Config: testAccFirewallConfigResourceUpdated(name, teamIDConfig(t)),
Check: resource.ComposeAggregateTestCheckFunc(
Expand Down Expand Up @@ -329,6 +343,15 @@ func TestAcc_FirewallConfigResource(t *testing.T) {
"vercel_firewall_config.ips",
"ip_rules.rule.2.hostname",
"*"),

resource.TestCheckResourceAttr(
"vercel_firewall_config.botfilter",
"managed_rulesets.bot_filter.action",
"deny"),
resource.TestCheckResourceAttr(
"vercel_firewall_config.botfilter",
"managed_rulesets.bot_filter.active",
"false"),
),
},
},
Expand Down Expand Up @@ -485,6 +508,23 @@ resource "vercel_firewall_config" "ips" {
}
}

resource "vercel_project" "botfilter" {
name = "test-acc-%[1]s-botfilter"
%[2]s
}

resource "vercel_firewall_config" "botfilter" {
project_id = vercel_project.botfilter.id
%[2]s

managed_rulesets {
bot_filter {
action = "challenge"
active = true
}
}
}

`, name, teamID)
}

Expand Down Expand Up @@ -655,5 +695,22 @@ resource "vercel_firewall_config" "neg" {
}
}
}

resource "vercel_project" "botfilter" {
name = "test-acc-%[1]s-botfilter"
%[2]s
}

resource "vercel_firewall_config" "botfilter" {
project_id = vercel_project.botfilter.id
%[2]s

managed_rulesets {
bot_filter {
action = "deny"
active = false
}
}
}
`, name, teamID)
}