This commit is contained in:
Dan Milne
2025-11-14 16:35:49 +11:00
parent df94ac9720
commit 6433f6c5bb
30 changed files with 833 additions and 245 deletions

View File

@@ -18,13 +18,13 @@ class WafPolicy < ApplicationRecord
# Validations
validates :name, presence: true, uniqueness: true
validates :policy_type, presence: true, inclusion: { in: POLICY_TYPES }
validates :action, presence: true, inclusion: { in: ACTIONS }
validates :policy_action, presence: true, inclusion: { in: ACTIONS }
validates :targets, presence: true
validate :targets_must_be_array
validates :user, presence: true
validate :validate_targets_by_type
validate :validate_redirect_configuration, if: :redirect_action?
validate :validate_challenge_configuration, if: :challenge_action?
validate :validate_redirect_configuration, if: :redirect_policy_action?
validate :validate_challenge_configuration, if: :challenge_policy_action?
# Scopes
scope :enabled, -> { where(enabled: true) }
@@ -59,19 +59,36 @@ validate :targets_must_be_array
# Action methods
def allow_action?
action == 'allow'
policy_action == 'allow'
end
def deny_action?
action == 'deny'
policy_action == 'deny'
end
def redirect_action?
action == 'redirect'
policy_action == 'redirect'
end
def challenge_action?
action == 'challenge'
policy_action == 'challenge'
end
# Policy action methods (to avoid confusion with Rails' action methods)
def allow_policy_action?
policy_action == 'allow'
end
def deny_policy_action?
policy_action == 'deny'
end
def redirect_policy_action?
policy_action == 'redirect'
end
def challenge_policy_action?
policy_action == 'challenge'
end
# Lifecycle methods
@@ -118,7 +135,7 @@ validate :targets_must_be_array
rule = Rule.create!(
rule_type: 'network',
action: action,
action: policy_action,
network_range: network_range,
waf_policy: self,
user: user,
@@ -148,45 +165,45 @@ validate :targets_must_be_array
end
# Class methods for creating common policies
def self.create_country_policy(countries, action: 'deny', user:, **options)
def self.create_country_policy(countries, policy_action: 'deny', user:, **options)
create!(
name: "#{action.capitalize} #{countries.join(', ')}",
name: "#{policy_action.capitalize} #{countries.join(', ')}",
policy_type: 'country',
targets: Array(countries),
action: action,
policy_action: policy_action,
user: user,
**options
)
end
def self.create_asn_policy(asns, action: 'deny', user:, **options)
def self.create_asn_policy(asns, policy_action: 'deny', user:, **options)
create!(
name: "#{action.capitalize} ASNs #{asns.join(', ')}",
name: "#{policy_action.capitalize} ASNs #{asns.join(', ')}",
policy_type: 'asn',
targets: Array(asns).map(&:to_i),
action: action,
policy_action: policy_action,
user: user,
**options
)
end
def self.create_company_policy(companies, action: 'deny', user:, **options)
def self.create_company_policy(companies, policy_action: 'deny', user:, **options)
create!(
name: "#{action.capitalize} #{companies.join(', ')}",
name: "#{policy_action.capitalize} #{companies.join(', ')}",
policy_type: 'company',
targets: Array(companies),
action: action,
policy_action: policy_action,
user: user,
**options
)
end
def self.create_network_type_policy(types, action: 'deny', user:, **options)
def self.create_network_type_policy(types, policy_action: 'deny', user:, **options)
create!(
name: "#{action.capitalize} #{types.join(', ')}",
name: "#{policy_action.capitalize} #{types.join(', ')}",
policy_type: 'network_type',
targets: Array(types),
action: action,
policy_action: policy_action,
user: user,
**options
)
@@ -226,7 +243,7 @@ validate :targets_must_be_array
active_rules: active_rules_count,
rules_last_7_days: recent_rules.count,
policy_type: policy_type,
action: action,
policy_action: policy_action,
targets_count: targets&.length || 0
}
end