diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bf57e21..b6881e4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -74,7 +74,7 @@ jobs: # these need root sudo -E $(which uv) run pytest ./tests/install/no_crowdsec # these need a running crowdsec - docker run -d --name crowdsec -e CI_TESTING=true -e DISABLE_ONLINE_API=true -p 8080:8080 -ti crowdsecurity/crowdsec + docker run -d --name crowdsec -e CROWDSEC_BYPASS_DB_VOLUME_CHECK=true -e CI_TESTING=true -e DISABLE_ONLINE_API=true -p 8080:8080 -ti crowdsecurity/crowdsec install -m 0755 /dev/stdin /usr/local/bin/cscli <<'EOT' #!/bin/sh docker exec crowdsec cscli "$@" diff --git a/pkg/cfg/config.go b/pkg/cfg/config.go index d3b2743..6167af0 100644 --- a/pkg/cfg/config.go +++ b/pkg/cfg/config.go @@ -28,6 +28,8 @@ type bouncerConfig struct { CertPath string `yaml:"cert_path"` CAPath string `yaml:"ca_cert_path"` SupportedActions []string `yaml:"supported_actions"` + DisableIPv4 *bool `yaml:"disable_ipv4"` + DisableIPv6 *bool `yaml:"disable_ipv6"` } type AclConfig struct { @@ -44,6 +46,8 @@ type AclConfig struct { CloudWatchEnabled bool `yaml:"cloudwatch_enabled"` CloudWatchMetricName string `yaml:"cloudwatch_metric_name"` SampleRequests bool `yaml:"sample_requests"` + DisableIPv4 *bool `yaml:"disable_ipv4"` + DisableIPv6 *bool `yaml:"disable_ipv6"` } var ValidActions = []string{"ban", "captcha", "count"} @@ -124,6 +128,22 @@ func getConfigFromEnv(config *bouncerConfig) { log.Warnf("Invalid value for %s: %s, defaulting to false", key, value) acl.SampleRequests = false } + case "DISABLE_IPV4": + b, err := strconv.ParseBool(value) + if err != nil { + log.Warnf("Invalid value for %s: %s, defaulting to false", key, value) + acl.DisableIPv4 = aws.Bool(false) + } else { + acl.DisableIPv4 = aws.Bool(b) + } + case "DISABLE_IPV6": + b, err := strconv.ParseBool(value) + if err != nil { + log.Warnf("Invalid value for %s: %s, defaulting to false", key, value) + acl.DisableIPv6 = aws.Bool(false) + } else { + acl.DisableIPv6 = aws.Bool(b) + } } } else { switch key { @@ -178,6 +198,22 @@ func getConfigFromEnv(config *bouncerConfig) { config.CAPath = value case "BOUNCER_SUPPORTED_ACTIONS": config.SupportedActions = strings.Split(value, ",") + case "BOUNCER_DISABLE_IPV4": + b, err := strconv.ParseBool(value) + if err != nil { + log.Warnf("Invalid value for %s: %s, defaulting to false", key, value) + config.DisableIPv4 = aws.Bool(false) + } else { + config.DisableIPv4 = aws.Bool(b) + } + case "BOUNCER_DISABLE_IPV6": + b, err := strconv.ParseBool(value) + if err != nil { + log.Warnf("Invalid value for %s: %s, defaulting to false", key, value) + config.DisableIPv6 = aws.Bool(false) + } else { + config.DisableIPv6 = aws.Bool(b) + } } } } @@ -223,6 +259,14 @@ func (c *bouncerConfig) ValidateAndSetDefaults() error { return fmt.Errorf("waf_config is required") } + // Default root-level IPv4/IPv6 disable flags to false if not set + if c.DisableIPv4 == nil { + c.DisableIPv4 = aws.Bool(false) + } + if c.DisableIPv6 == nil { + c.DisableIPv6 = aws.Bool(false) + } + for i, aclConfig := range c.WebACLConfig { if aclConfig.FallbackAction == "" { return fmt.Errorf("fallback_action is required") @@ -278,6 +322,14 @@ func (c *bouncerConfig) ValidateAndSetDefaults() error { if aclConfig.Capacity == 0 { c.WebACLConfig[i].Capacity = 300 } + + // Inherit IPv4/IPv6 disable flags from root when not set on WAF config + if aclConfig.DisableIPv4 == nil { + c.WebACLConfig[i].DisableIPv4 = c.DisableIPv4 + } + if aclConfig.DisableIPv6 == nil { + c.WebACLConfig[i].DisableIPv6 = c.DisableIPv6 + } } return nil diff --git a/pkg/waf/waf.go b/pkg/waf/waf.go index 48cf282..d7767e7 100644 --- a/pkg/waf/waf.go +++ b/pkg/waf/waf.go @@ -547,43 +547,47 @@ func (w *WAF) Init(ctx context.Context) error { func (w *WAF) UpdateSetsContent(ctx context.Context, d Decisions) error { var err error - for action, ips := range d.V4Add { - if action == "fallback" { - action = strings.ToLower(w.config.FallbackAction) - } + if w.config.DisableIPv4 == nil || !*w.config.DisableIPv4 { + for action, ips := range d.V4Add { + if action == "fallback" { + action = strings.ToLower(w.config.FallbackAction) + } - for _, ip := range ips { - w.ipsetManager.AddIp(*ip, action) + for _, ip := range ips { + w.ipsetManager.AddIp(*ip, action) + } } - } - for action, ips := range d.V4Del { - if action == "fallback" { - action = strings.ToLower(w.config.FallbackAction) - } + for action, ips := range d.V4Del { + if action == "fallback" { + action = strings.ToLower(w.config.FallbackAction) + } - for _, ip := range ips { - w.ipsetManager.DeleteIp(*ip, action) + for _, ip := range ips { + w.ipsetManager.DeleteIp(*ip, action) + } } } - for action, ips := range d.V6Add { - if action == "fallback" { - action = strings.ToLower(w.config.FallbackAction) - } + if w.config.DisableIPv6 == nil || !*w.config.DisableIPv6 { + for action, ips := range d.V6Add { + if action == "fallback" { + action = strings.ToLower(w.config.FallbackAction) + } - for _, ip := range ips { - w.ipsetManager.AddIp(*ip, action) + for _, ip := range ips { + w.ipsetManager.AddIp(*ip, action) + } } - } - for action, ips := range d.V6Del { - if action == "fallback" { - action = strings.ToLower(w.config.FallbackAction) - } + for action, ips := range d.V6Del { + if action == "fallback" { + action = strings.ToLower(w.config.FallbackAction) + } - for _, ip := range ips { - w.ipsetManager.DeleteIp(*ip, action) + for _, ip := range ips { + w.ipsetManager.DeleteIp(*ip, action) + } } }