diff --git a/docs/resources/firewall_config.md b/docs/resources/firewall_config.md index ba7f8b5d..96d16aa2 100644 --- a/docs/resources/firewall_config.md +++ b/docs/resources/firewall_config.md @@ -162,6 +162,11 @@ resource "vercel_firewall_config" "managed" { action = "log" active = true } + + ai_bots { + action = "log" + active = true + } } } @@ -235,9 +240,19 @@ Read-Only: Optional: +- `ai_bots` (Block, Optional) Enable the ai_bots managed ruleset and select action (see [below for nested schema](#nestedblock--managed_rulesets--ai_bots)) - `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)) + +### Nested Schema for `managed_rulesets.ai_bots` + +Optional: + +- `action` (String) +- `active` (Boolean) + + ### Nested Schema for `managed_rulesets.bot_filter` diff --git a/examples/resources/vercel_firewall_config/resource.tf b/examples/resources/vercel_firewall_config/resource.tf index 4b2099eb..8c45d2a3 100644 --- a/examples/resources/vercel_firewall_config/resource.tf +++ b/examples/resources/vercel_firewall_config/resource.tf @@ -147,6 +147,11 @@ resource "vercel_firewall_config" "managed" { action = "log" active = true } + + ai_bots { + action = "log" + active = true + } } } diff --git a/vercel/resource_firewall_config.go b/vercel/resource_firewall_config.go index eb9f10c4..ec4e9101 100644 --- a/vercel/resource_firewall_config.go +++ b/vercel/resource_firewall_config.go @@ -181,6 +181,17 @@ Define Custom Rules to shape the way your traffic is handled by the Vercel Edge }, }, }, + "ai_bots": schema.SingleNestedBlock{ + Description: "Enable the ai_bots managed ruleset and select action", + Attributes: map[string]schema.Attribute{ + "active": schema.BoolAttribute{ + Optional: true, + }, + "action": schema.StringAttribute{ + Optional: true, + }, + }, + }, }, }, "rules": schema.SingleNestedBlock{ @@ -456,6 +467,7 @@ type FirewallConfig struct { type FirewallManagedRulesets struct { OWASP *CRSRule `tfsdk:"owasp"` BotFilter *BotFilterConfig `tfsdk:"bot_filter"` + AiBots *AiBotsConfig `tfsdk:"ai_bots"` } type CRSRule struct { @@ -496,6 +508,11 @@ type BotFilterConfig struct { Action types.String `tfsdk:"action"` } +type AiBotsConfig struct { + Active types.Bool `tfsdk:"active"` + Action types.String `tfsdk:"action"` +} + type FirewallRules struct { Rules []FirewallRule `tfsdk:"rule"` } @@ -861,6 +878,7 @@ func fromClient(conf client.FirewallConfig, state FirewallConfig) (FirewallConfi 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{ @@ -869,6 +887,15 @@ func fromClient(conf client.FirewallConfig, state FirewallConfig) (FirewallConfi } cfg.ManagedRulesets.BotFilter = botFilterConf } + + aiBots, aiBotsExist := conf.ManagedRulesets["ai_bots"] + if aiBotsExist { + aiBotsConf := &AiBotsConfig{ + Active: types.BoolValue(aiBots.Active), + Action: types.StringValue(aiBots.Action), + } + cfg.ManagedRulesets.AiBots = aiBotsConf + } } return cfg, nil @@ -897,6 +924,7 @@ func (f *FirewallConfig) toClient() (client.FirewallConfig, error) { } } } + botFilter := f.ManagedRulesets.BotFilter if botFilter != nil { conf.ManagedRulesets["bot_filter"] = client.ManagedRule{ @@ -904,6 +932,14 @@ func (f *FirewallConfig) toClient() (client.FirewallConfig, error) { Action: botFilter.Action.ValueString(), } } + + aiBots := f.ManagedRulesets.AiBots + if aiBots != nil { + conf.ManagedRulesets["ai_bots"] = client.ManagedRule{ + Active: aiBots.Active.ValueBool(), + Action: aiBots.Action.ValueString(), + } + } } if f.Rules != nil && len(f.Rules.Rules) > 0 { for _, rule := range f.Rules.Rules { diff --git a/vercel/resource_firewall_config_test.go b/vercel/resource_firewall_config_test.go index 260404b2..dccfb04f 100644 --- a/vercel/resource_firewall_config_test.go +++ b/vercel/resource_firewall_config_test.go @@ -169,7 +169,6 @@ 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", @@ -178,6 +177,14 @@ func TestAcc_FirewallConfigResource(t *testing.T) { "vercel_firewall_config.botfilter", "managed_rulesets.bot_filter.active", "true"), + resource.TestCheckResourceAttr( + "vercel_firewall_config.aibots", + "managed_rulesets.ai_bots.action", + "challenge"), + resource.TestCheckResourceAttr( + "vercel_firewall_config.aibots", + "managed_rulesets.ai_bots.active", + "true"), ), }, { @@ -200,6 +207,11 @@ func TestAcc_FirewallConfigResource(t *testing.T) { ResourceName: "vercel_firewall_config.botfilter", ImportStateIdFunc: getFirewallImportID("vercel_firewall_config.botfilter"), }, + { + ImportState: true, + ResourceName: "vercel_firewall_config.aibots", + ImportStateIdFunc: getFirewallImportID("vercel_firewall_config.aibots"), + }, { Config: cfg(testAccFirewallConfigResourceUpdated(name)), Check: resource.ComposeAggregateTestCheckFunc( @@ -343,7 +355,6 @@ 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", @@ -352,6 +363,14 @@ func TestAcc_FirewallConfigResource(t *testing.T) { "vercel_firewall_config.botfilter", "managed_rulesets.bot_filter.active", "false"), + resource.TestCheckResourceAttr( + "vercel_firewall_config.aibots", + "managed_rulesets.ai_bots.action", + "deny"), + resource.TestCheckResourceAttr( + "vercel_firewall_config.aibots", + "managed_rulesets.ai_bots.active", + "false"), ), }, }, @@ -517,6 +536,21 @@ resource "vercel_firewall_config" "botfilter" { } } +resource "vercel_project" "aibots" { + name = "test-acc-%[1]s-aibots" +} + +resource "vercel_firewall_config" "aibots" { + project_id = vercel_project.aibots.id + + managed_rulesets { + ai_bots { + action = "challenge" + active = true + } + } +} + `, name) } @@ -694,5 +728,20 @@ resource "vercel_firewall_config" "botfilter" { } } } + +resource "vercel_project" "aibots" { + name = "test-acc-%[1]s-aibots" +} + +resource "vercel_firewall_config" "aibots" { + project_id = vercel_project.aibots.id + + managed_rulesets { + ai_bots { + action = "deny" + active = false + } + } +} `, name) }