diff --git a/.changelog/2159.txt b/.changelog/2159.txt new file mode 100644 index 0000000000..761b0ef936 --- /dev/null +++ b/.changelog/2159.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/cloudflare_teams_rules: adds egress rule settings. +``` \ No newline at end of file diff --git a/docs/resources/teams_rule.md b/docs/resources/teams_rule.md index 75a8dc2652..64ec37ab8c 100644 --- a/docs/resources/teams_rule.md +++ b/docs/resources/teams_rule.md @@ -32,7 +32,7 @@ resource "cloudflare_teams_rule" "example" { ### Required - `account_id` (String) The account identifier to target for the resource. -- `action` (String) The action executed by matched teams rule. Available values: `allow`, `block`, `safesearch`, `ytrestricted`, `on`, `off`, `scan`, `noscan`, `isolate`, `noisolate`, `override`, `l4_override`. +- `action` (String) The action executed by matched teams rule. Available values: `allow`, `block`, `safesearch`, `ytrestricted`, `on`, `off`, `scan`, `noscan`, `isolate`, `noisolate`, `override`, `l4_override`, `egress`. - `description` (String) The description of the teams rule. - `name` (String) The name of the teams rule. - `precedence` (Number) The evaluation precedence of the teams rule. @@ -61,6 +61,7 @@ Optional: - `block_page_enabled` (Boolean) Indicator of block page enablement. - `block_page_reason` (String) The displayed reason for a user being blocked. - `check_session` (Block List, Max: 1) Configure how session check behaves. (see [below for nested schema](#nestedblock--rule_settings--check_session)) +- `egress` (Block List, Max: 1) Configure how Proxy traffic egresses. Can be set for rules with Egress action and Egress filter. Can be omitted to indicate local egress via Warp IPs. (see [below for nested schema](#nestedblock--rule_settings--egress)) - `insecure_disable_dnssec_validation` (Boolean) Disable DNSSEC validation (must be Allow rule). - `l4override` (Block List, Max: 1) Settings to forward layer 4 traffic. (see [below for nested schema](#nestedblock--rule_settings--l4override)) - `override_host` (String) The host to override matching DNS queries with. @@ -87,6 +88,19 @@ Required: - `enforce` (Boolean) Enable session enforcement for this rule. + +### Nested Schema for `rule_settings.egress` + +Required: + +- `ipv4` (String) The IPv4 address to be used for egress. +- `ipv6` (String) The IPv6 range to be used for egress. + +Optional: + +- `ipv4_fallback` (String) The IPv4 address to be used for egress in the event of an error egressing with the primary IPv4. Can be '0.0.0.0' to indicate local egreass via Warp IPs. + + ### Nested Schema for `rule_settings.l4override` diff --git a/internal/provider/resource_cloudflare_teams_rules.go b/internal/provider/resource_cloudflare_teams_rules.go index cd7c439ab3..4b873bda59 100644 --- a/internal/provider/resource_cloudflare_teams_rules.go +++ b/internal/provider/resource_cloudflare_teams_rules.go @@ -205,6 +205,7 @@ func flattenTeamsRuleSettings(settings *cloudflare.TeamsRuleSettings) []interfac "check_session": flattenTeamsCheckSessionSettings(settings.CheckSession), "add_headers": flattenTeamsAddHeaders(settings.AddHeaders), "insecure_disable_dnssec_validation": settings.InsecureDisableDNSSECValidation, + "egress": flattenTeamsEgressSettings(settings.EgressSettings), }} } @@ -230,6 +231,7 @@ func inflateTeamsRuleSettings(settings interface{}) *cloudflare.TeamsRuleSetting checkSessionSettings := inflateTeamsCheckSessionSettings(settingsMap["check_session"].([]interface{})) addHeaders := inflateTeamsAddHeaders(settingsMap["add_headers"].(map[string]interface{})) insecureDisableDNSSECValidation := settingsMap["insecure_disable_dnssec_validation"].(bool) + egressSettings := inflateTeamsEgressSettings(settingsMap["egress"].([]interface{})) return &cloudflare.TeamsRuleSettings{ BlockPageEnabled: enabled, @@ -241,6 +243,7 @@ func inflateTeamsRuleSettings(settings interface{}) *cloudflare.TeamsRuleSetting CheckSession: checkSessionSettings, AddHeaders: addHeaders, InsecureDisableDNSSECValidation: insecureDisableDNSSECValidation, + EgressSettings: egressSettings, } } @@ -363,6 +366,33 @@ func inflateTeamsL4Override(settings interface{}) *cloudflare.TeamsL4OverrideSet } } +func flattenTeamsEgressSettings(settings *cloudflare.EgressSettings) []interface{} { + if settings == nil { + return nil + } + return []interface{}{map[string]interface{}{ + "ipv4": settings.Ipv4, + "ipv6": settings.Ipv6Range, + "ipv4_fallback": settings.Ipv4Fallback, + }} +} + +func inflateTeamsEgressSettings(settings interface{}) *cloudflare.EgressSettings { + settingsList := settings.([]interface{}) + if len(settingsList) != 1 { + return nil + } + settingsMap := settingsList[0].(map[string]interface{}) + ipv4 := settingsMap["ipv4"].(string) + ipv6 := settingsMap["ipv6"].(string) + ipv4Fallback := settingsMap["ipv4_fallback"].(string) + return &cloudflare.EgressSettings{ + Ipv4: ipv4, + Ipv6Range: ipv6, + Ipv4Fallback: ipv4Fallback, + } +} + func providerToApiRulePrecedence(provided int64, ruleName string) int64 { return provided*rulePrecedenceFactor + int64(hashCodeString(ruleName))%rulePrecedenceFactor } diff --git a/internal/provider/resource_cloudflare_teams_rules_test.go b/internal/provider/resource_cloudflare_teams_rules_test.go index b1ec7436a7..678185c566 100644 --- a/internal/provider/resource_cloudflare_teams_rules_test.go +++ b/internal/provider/resource_cloudflare_teams_rules_test.go @@ -43,6 +43,8 @@ func TestAccCloudflareTeamsRuleBasic(t *testing.T) { resource.TestCheckResourceAttr(name, "rule_settings.0.block_page_enabled", "false"), resource.TestCheckResourceAttr(name, "rule_settings.0.block_page_reason", "cuz"), resource.TestCheckResourceAttr(name, "rule_settings.0.insecure_disable_dnssec_validation", "false"), + resource.TestCheckResourceAttr(name, "rule_settings.0.egress.0.ipv4", "203.0.113.1"), + resource.TestCheckResourceAttr(name, "rule_settings.0.egress.0.ipv6", "2001:db8::/32"), ), }, }, @@ -63,6 +65,10 @@ resource "cloudflare_teams_rule" "%[1]s" { block_page_enabled = false block_page_reason = "cuz" insecure_disable_dnssec_validation = false + egress { + ipv4 = "203.0.113.1" + ipv6 = "2001:db8::/32" + } } } `, rnd, accountID) diff --git a/internal/provider/schema_cloudflare_teams_rules.go b/internal/provider/schema_cloudflare_teams_rules.go index 1cd8706753..36710c8289 100644 --- a/internal/provider/schema_cloudflare_teams_rules.go +++ b/internal/provider/schema_cloudflare_teams_rules.go @@ -140,6 +140,33 @@ var teamsRuleSettings = map[string]*schema.Schema{ Optional: true, Description: "Disable DNSSEC validation (must be Allow rule).", }, + "egress": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: egressSettings, + }, + Description: "Configure how Proxy traffic egresses. Can be set for rules with Egress action and Egress filter. Can be omitted to indicate local egress via Warp IPs.", + }, +} + +var egressSettings = map[string]*schema.Schema{ + "ipv6": { + Type: schema.TypeString, + Required: true, + Description: "The IPv6 range to be used for egress.", + }, + "ipv4": { + Type: schema.TypeString, + Required: true, + Description: "The IPv4 address to be used for egress.", + }, + "ipv4_fallback": { + Type: schema.TypeString, + Optional: true, + Description: "The IPv4 address to be used for egress in the event of an error egressing with the primary IPv4. Can be '0.0.0.0' to indicate local egreass via Warp IPs.", + }, } var teamsL4OverrideSettings = map[string]*schema.Schema{