Path matching
This commit is contained in:
@@ -9,11 +9,13 @@ class Event < ApplicationRecord
|
||||
has_one :waf_policy, through: :rule
|
||||
|
||||
# Enums for fixed value sets
|
||||
# Canonical WAF action order - aligned with Rule and Agent models
|
||||
enum :waf_action, {
|
||||
allow: 0, # allow/pass
|
||||
deny: 1, # deny/block
|
||||
deny: 0, # deny/block
|
||||
allow: 1, # allow/pass
|
||||
redirect: 2, # redirect
|
||||
challenge: 3 # challenge (future implementation)
|
||||
challenge: 3, # challenge (CAPTCHA, JS challenge, etc.)
|
||||
log: 4 # log only, no action (monitoring mode)
|
||||
}, default: :allow, scopes: false
|
||||
|
||||
enum :request_method, {
|
||||
@@ -42,7 +44,7 @@ class Event < ApplicationRecord
|
||||
scope :by_waf_action, ->(waf_action) { where(waf_action: waf_action) }
|
||||
scope :blocked, -> { where(waf_action: :deny) }
|
||||
scope :allowed, -> { where(waf_action: :allow) }
|
||||
scope :rate_limited, -> { where(waf_action: 'rate_limit') }
|
||||
scope :logged, -> { where(waf_action: :log) }
|
||||
|
||||
# Tag-based filtering scopes using PostgreSQL array operators
|
||||
scope :with_tag, ->(tag) { where("tags @> ARRAY[?]", tag.to_s) }
|
||||
@@ -346,8 +348,8 @@ class Event < ApplicationRecord
|
||||
waf_action.in?(['allow', 'pass'])
|
||||
end
|
||||
|
||||
def rate_limited?
|
||||
waf_action == 'rate_limit'
|
||||
def logged?
|
||||
waf_action == 'log'
|
||||
end
|
||||
|
||||
def challenged?
|
||||
|
||||
@@ -6,12 +6,10 @@
|
||||
# Network rules are associated with NetworkRange objects for rich context.
|
||||
class Rule < ApplicationRecord
|
||||
# Rule enums (prefix needed to avoid rate_limit collision)
|
||||
enum :waf_action, { allow: 0, deny: 1, rate_limit: 2, redirect: 3, log: 4, challenge: 5 }, prefix: :action
|
||||
# Canonical WAF action order - aligned with Agent and Event models
|
||||
enum :waf_action, { deny: 0, allow: 1, redirect: 2, challenge: 3, log: 4 }, prefix: :action
|
||||
enum :waf_rule_type, { network: 0, rate_limit: 1, path_pattern: 2 }, prefix: :type
|
||||
|
||||
# Legacy string constants for backward compatibility
|
||||
RULE_TYPES = %w[network rate_limit path_pattern].freeze
|
||||
ACTIONS = %w[allow deny rate_limit redirect log challenge].freeze
|
||||
SOURCES = %w[manual auto:scanner_detected auto:rate_limit_exceeded auto:bot_detected imported default manual:surgical_block manual:surgical_exception policy].freeze
|
||||
|
||||
# Associations
|
||||
@@ -27,14 +25,6 @@ class Rule < ApplicationRecord
|
||||
validates :enabled, inclusion: { in: [true, false] }
|
||||
validates :source, inclusion: { in: SOURCES }
|
||||
|
||||
# Legacy enum definitions (disabled to prevent conflicts)
|
||||
# enum :action, { allow: "allow", deny: "deny", rate_limit: "rate_limit", redirect: "redirect", log: "log", challenge: "challenge" }, scopes: false
|
||||
# enum :rule_type, { network: "network", rate_limit: "rate_limit", path_pattern: "path_pattern" }, scopes: false
|
||||
|
||||
# Legacy validations for backward compatibility during transition
|
||||
# validates :rule_type, presence: true, inclusion: { in: RULE_TYPES }, allow_nil: true
|
||||
# validates :action, presence: true, inclusion: { in: ACTIONS }, allow_nil: true
|
||||
|
||||
# Custom validations
|
||||
validate :validate_conditions_by_type
|
||||
validate :validate_metadata_by_action
|
||||
@@ -356,12 +346,12 @@ class Rule < ApplicationRecord
|
||||
[block_rule, exception_rule]
|
||||
end
|
||||
|
||||
def self.create_rate_limit_rule(cidr, limit:, window:, user: nil, **options)
|
||||
def self.create_rate_limit_rule(cidr, limit:, window:, user: nil, action: 'deny', **options)
|
||||
network_range = NetworkRange.find_or_create_by_cidr(cidr, user: user, source: 'user_created')
|
||||
|
||||
create!(
|
||||
waf_rule_type: 'rate_limit',
|
||||
waf_action: 'rate_limit',
|
||||
waf_action: action, # Action to take when rate limit exceeded (deny, redirect, challenge, log)
|
||||
network_range: network_range,
|
||||
conditions: { cidr: cidr, scope: 'ip' },
|
||||
metadata: {
|
||||
@@ -514,10 +504,6 @@ class Rule < ApplicationRecord
|
||||
if challenge_type_value && !%w[captcha javascript proof_of_work].include?(challenge_type_value)
|
||||
errors.add(:metadata, "challenge_type must be one of: captcha, javascript, proof_of_work")
|
||||
end
|
||||
when "rate_limit"
|
||||
unless metadata&.dig("limit").present? && metadata&.dig("window").present?
|
||||
errors.add(:metadata, "must include 'limit' and 'window' for rate_limit action")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user