Files
baffle-hub/app/jobs/process_waf_analytics_job.rb

125 lines
3.8 KiB
Ruby

# frozen_string_literal: true
class ProcessWafAnalyticsJob < ApplicationJob
queue_as :waf_analytics
def perform(event_id:)
event = Event.find(event_id)
# Analyze event patterns
analyze_traffic_patterns(event)
analyze_geographic_distribution(event)
analyze_attack_vectors(event)
# Update global analytics cache
update_analytics_cache
rescue => e
Rails.logger.error "Error processing WAF analytics: #{e.message}"
Rails.logger.error e.backtrace.join("\n")
end
private
def analyze_traffic_patterns(event)
# Look for unusual traffic spikes
recent_events = Event.where(timestamp: 5.minutes.ago..Time.current)
# Use a default threshold since we no longer have project-specific thresholds
threshold = 1000 # Default threshold
if recent_events.count > threshold * 5
# High traffic detected - create an issue
Issue.create!(
title: "High Traffic Spike Detected",
description: "Detected #{recent_events.count} requests in the last 5 minutes",
severity: "medium",
event_id: event.id,
metadata: {
event_count: recent_events.count,
time_window: "5 minutes",
threshold: threshold * 5
}
)
end
end
def analyze_geographic_distribution(event)
return unless event.has_geo_data?
country_code = event.lookup_country
return unless country_code.present?
# Check if this country is unusual globally by joining through network ranges
country_events = Event
.joins("JOIN network_ranges ON events.ip_address <<= network_ranges.network")
.where("network_ranges.country = ?", country_code)
.where(timestamp: 1.hour.ago..Time.current)
# If this is the first event from this country or unusual spike
if country_events.count == 1 || country_events.count > 100
Rails.logger.info "Unusual geographic activity from #{country_code}"
end
end
def analyze_attack_vectors(event)
return unless event.blocked?
# Analyze common attack patterns
analyze_ip_reputation(event)
analyze_user_agent_patterns(event)
analyze_path_attacks(event)
end
def analyze_ip_reputation(event)
return unless event.ip_address.present?
# Count recent blocks from this IP
recent_blocks = Event
.by_ip(event.ip_address)
.blocked
.where(timestamp: 1.hour.ago..Time.current)
if recent_blocks.count >= 5
# Log IP reputation issue - no automatic IP blocking without projects
Rails.logger.warn "IP with poor reputation detected: #{event.ip_address} (#{recent_blocks.count} blocks in 1 hour)"
end
end
def analyze_user_agent_patterns(event)
return unless event.user_agent.present?
# Look for common bot/user agent patterns
suspicious_patterns = [
/bot/i, /crawler/i, /spider/i, /scanner/i,
/python/i, /curl/i, /wget/i, /nmap/i
]
if suspicious_patterns.any? { |pattern| event.user_agent.match?(pattern) }
# Log suspicious user agent for potential rule generation
Rails.logger.info "Suspicious user agent detected: #{event.user_agent}"
end
end
def analyze_path_attacks(event)
return unless event.request_path.present?
# Look for common attack paths
attack_patterns = [
/\.\./, # Directory traversal
/admin/i, # Admin panel access
/wp-admin/i, # WordPress admin
/\.php/i, # PHP files
/union.*select/i, # SQL injection
/script.*>/i # XSS attempts
]
if attack_patterns.any? { |pattern| event.request_path.match?(pattern) }
Rails.logger.info "Potential attack path detected: #{event.request_path}"
end
end
def update_analytics_cache
# Update cached analytics for faster dashboard loading
Rails.cache.delete("global_analytics")
end
end