Add WafPolicies
This commit is contained in:
@@ -7,12 +7,13 @@
|
||||
class Rule < ApplicationRecord
|
||||
# Rule types and actions
|
||||
RULE_TYPES = %w[network rate_limit path_pattern].freeze
|
||||
ACTIONS = %w[allow deny rate_limit redirect log].freeze
|
||||
SOURCES = %w[manual auto:scanner_detected auto:rate_limit_exceeded auto:bot_detected imported default manual:surgical_block manual:surgical_exception].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
|
||||
belongs_to :user
|
||||
belongs_to :network_range, optional: true
|
||||
belongs_to :waf_policy, optional: true
|
||||
|
||||
# Validations
|
||||
validates :rule_type, presence: true, inclusion: { in: RULE_TYPES }
|
||||
@@ -39,6 +40,8 @@ class Rule < ApplicationRecord
|
||||
scope :by_source, ->(source) { where(source: source) }
|
||||
scope :surgical_blocks, -> { where(source: "manual:surgical_block") }
|
||||
scope :surgical_exceptions, -> { where(source: "manual:surgical_exception") }
|
||||
scope :policy_generated, -> { where(source: "policy") }
|
||||
scope :from_waf_policy, ->(waf_policy) { where(waf_policy: waf_policy) }
|
||||
|
||||
# Sync queries
|
||||
scope :since, ->(timestamp) { where("updated_at >= ?", Time.at(timestamp)).order(:updated_at, :id) }
|
||||
@@ -94,6 +97,37 @@ class Rule < ApplicationRecord
|
||||
source == "manual:surgical_exception"
|
||||
end
|
||||
|
||||
# Policy-generated rule methods
|
||||
def policy_generated?
|
||||
source == "policy"
|
||||
end
|
||||
|
||||
# Action-specific methods
|
||||
def redirect_action?
|
||||
action == "redirect"
|
||||
end
|
||||
|
||||
def challenge_action?
|
||||
action == "challenge"
|
||||
end
|
||||
|
||||
# Redirect/challenge convenience methods
|
||||
def redirect_url
|
||||
metadata&.dig('redirect_url')
|
||||
end
|
||||
|
||||
def redirect_status
|
||||
metadata&.dig('redirect_status') || 302
|
||||
end
|
||||
|
||||
def challenge_type
|
||||
metadata&.dig('challenge_type') || 'captcha'
|
||||
end
|
||||
|
||||
def challenge_message
|
||||
metadata&.dig('challenge_message')
|
||||
end
|
||||
|
||||
def related_surgical_rules
|
||||
if surgical_block?
|
||||
# Find the corresponding exception rule
|
||||
@@ -365,6 +399,12 @@ class Rule < ApplicationRecord
|
||||
unless metadata&.dig("redirect_url").present?
|
||||
errors.add(:metadata, "must include 'redirect_url' for redirect action")
|
||||
end
|
||||
when "challenge"
|
||||
# Challenge is flexible - can use defaults
|
||||
challenge_type_value = metadata&.dig("challenge_type")
|
||||
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")
|
||||
|
||||
Reference in New Issue
Block a user