Tidy up homepage and navigation
This commit is contained in:
@@ -15,7 +15,6 @@ class EventNormalizationJob < ApplicationJob
|
||||
events = Event.where(request_host_id: nil)
|
||||
.limit(batch_size)
|
||||
.offset(offset)
|
||||
.includes(:project)
|
||||
|
||||
break if events.empty?
|
||||
|
||||
|
||||
@@ -3,21 +3,20 @@
|
||||
class GenerateWafRulesJob < ApplicationJob
|
||||
queue_as :waf_rules
|
||||
|
||||
def perform(project_id:, event_id:)
|
||||
project = Project.find(project_id)
|
||||
def perform(event_id:)
|
||||
event = Event.find(event_id)
|
||||
|
||||
# Only analyze blocked events for rule generation
|
||||
return unless event.blocked?
|
||||
|
||||
# Generate different types of rules based on patterns
|
||||
generate_ip_rules(project, event)
|
||||
generate_path_rules(project, event)
|
||||
generate_user_agent_rules(project, event)
|
||||
generate_parameter_rules(project, event)
|
||||
generate_ip_rules(event)
|
||||
generate_path_rules(event)
|
||||
generate_user_agent_rules(event)
|
||||
generate_parameter_rules(event)
|
||||
|
||||
# Notify project of new rules
|
||||
project.broadcast_rules_refresh
|
||||
# Broadcast rule updates globally
|
||||
ActionCable.server.broadcast("rules", { type: "refresh" })
|
||||
|
||||
rescue => e
|
||||
Rails.logger.error "Error generating WAF rules: #{e.message}"
|
||||
@@ -26,30 +25,23 @@ class GenerateWafRulesJob < ApplicationJob
|
||||
|
||||
private
|
||||
|
||||
def generate_ip_rules(project, event)
|
||||
def generate_ip_rules(event)
|
||||
return unless event.ip_address.present?
|
||||
|
||||
# Check if this IP has multiple violations
|
||||
violation_count = project.events
|
||||
violation_count = Event
|
||||
.by_ip(event.ip_address)
|
||||
.blocked
|
||||
.where(timestamp: 24.hours.ago..Time.current)
|
||||
.count
|
||||
|
||||
# Auto-block IPs with 10+ violations in 24 hours
|
||||
if violation_count >= 10 && !project.blocked_ips.include?(event.ip_address)
|
||||
project.add_ip_rule(
|
||||
event.ip_address,
|
||||
'block',
|
||||
expires_at: 7.days.from_now,
|
||||
reason: "Auto-generated: #{violation_count} violations in 24 hours"
|
||||
)
|
||||
|
||||
Rails.logger.info "Auto-blocked IP #{event.ip_address} for project #{project.slug}"
|
||||
# Log high-violation IPs - no automatic blocking without projects
|
||||
if violation_count >= 10
|
||||
Rails.logger.info "IP with high violation count: #{event.ip_address} (#{violation_count} violations in 24 hours)"
|
||||
end
|
||||
end
|
||||
|
||||
def generate_path_rules(project, event)
|
||||
def generate_path_rules(event)
|
||||
return unless event.request_path.present?
|
||||
|
||||
# Look for repeated attack patterns on specific paths
|
||||
@@ -65,7 +57,7 @@ class GenerateWafRulesJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def generate_user_agent_rules(project, event)
|
||||
def generate_user_agent_rules(event)
|
||||
return unless event.user_agent.present?
|
||||
|
||||
# Look for malicious user agents
|
||||
@@ -81,7 +73,7 @@ class GenerateWafRulesJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def generate_parameter_rules(project, event)
|
||||
def generate_parameter_rules(event)
|
||||
params = event.query_params
|
||||
return unless params.present?
|
||||
|
||||
|
||||
@@ -3,17 +3,16 @@
|
||||
class ProcessWafAnalyticsJob < ApplicationJob
|
||||
queue_as :waf_analytics
|
||||
|
||||
def perform(project_id:, event_id:)
|
||||
project = Project.find(project_id)
|
||||
def perform(event_id:)
|
||||
event = Event.find(event_id)
|
||||
|
||||
# Analyze event patterns
|
||||
analyze_traffic_patterns(project, event)
|
||||
analyze_geographic_distribution(project, event)
|
||||
analyze_attack_vectors(project, event)
|
||||
analyze_traffic_patterns(event)
|
||||
analyze_geographic_distribution(event)
|
||||
analyze_attack_vectors(event)
|
||||
|
||||
# Update project analytics cache
|
||||
update_project_analytics(project)
|
||||
# Update global analytics cache
|
||||
update_analytics_cache
|
||||
|
||||
rescue => e
|
||||
Rails.logger.error "Error processing WAF analytics: #{e.message}"
|
||||
@@ -22,14 +21,15 @@ class ProcessWafAnalyticsJob < ApplicationJob
|
||||
|
||||
private
|
||||
|
||||
def analyze_traffic_patterns(project, event)
|
||||
def analyze_traffic_patterns(event)
|
||||
# Look for unusual traffic spikes
|
||||
recent_events = project.events.where(timestamp: 5.minutes.ago..Time.current)
|
||||
recent_events = Event.where(timestamp: 5.minutes.ago..Time.current)
|
||||
|
||||
if recent_events.count > project.rate_limit_threshold * 5
|
||||
# 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!(
|
||||
project: project,
|
||||
title: "High Traffic Spike Detected",
|
||||
description: "Detected #{recent_events.count} requests in the last 5 minutes",
|
||||
severity: "medium",
|
||||
@@ -37,56 +37,51 @@ class ProcessWafAnalyticsJob < ApplicationJob
|
||||
metadata: {
|
||||
event_count: recent_events.count,
|
||||
time_window: "5 minutes",
|
||||
threshold: project.rate_limit_threshold * 5
|
||||
threshold: threshold * 5
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def analyze_geographic_distribution(project, event)
|
||||
def analyze_geographic_distribution(event)
|
||||
return unless event.country_code.present?
|
||||
|
||||
# Check if this country is unusual for this project
|
||||
country_events = project.events
|
||||
# Check if this country is unusual globally
|
||||
country_events = Event
|
||||
.where(country_code: event.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 #{event.country_code} for project #{project.slug}"
|
||||
Rails.logger.info "Unusual geographic activity from #{event.country_code}"
|
||||
end
|
||||
end
|
||||
|
||||
def analyze_attack_vectors(project, event)
|
||||
def analyze_attack_vectors(event)
|
||||
return unless event.blocked?
|
||||
|
||||
# Analyze common attack patterns
|
||||
analyze_ip_reputation(project, event)
|
||||
analyze_user_agent_patterns(project, event)
|
||||
analyze_path_attacks(project, event)
|
||||
analyze_ip_reputation(event)
|
||||
analyze_user_agent_patterns(event)
|
||||
analyze_path_attacks(event)
|
||||
end
|
||||
|
||||
def analyze_ip_reputation(project, event)
|
||||
def analyze_ip_reputation(event)
|
||||
return unless event.ip_address.present?
|
||||
|
||||
# Count recent blocks from this IP
|
||||
recent_blocks = project.events
|
||||
recent_blocks = Event
|
||||
.by_ip(event.ip_address)
|
||||
.blocked
|
||||
.where(timestamp: 1.hour.ago..Time.current)
|
||||
|
||||
if recent_blocks.count >= 5
|
||||
# Suggest automatic IP block
|
||||
project.add_ip_rule(
|
||||
event.ip_address,
|
||||
'block',
|
||||
expires_at: 24.hours.from_now,
|
||||
reason: "Automated block: #{recent_blocks.count} violations in 1 hour"
|
||||
)
|
||||
# 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(project, event)
|
||||
def analyze_user_agent_patterns(event)
|
||||
return unless event.user_agent.present?
|
||||
|
||||
# Look for common bot/user agent patterns
|
||||
@@ -101,7 +96,7 @@ class ProcessWafAnalyticsJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def analyze_path_attacks(project, event)
|
||||
def analyze_path_attacks(event)
|
||||
return unless event.request_path.present?
|
||||
|
||||
# Look for common attack paths
|
||||
@@ -119,8 +114,8 @@ class ProcessWafAnalyticsJob < ApplicationJob
|
||||
end
|
||||
end
|
||||
|
||||
def update_project_analytics(project)
|
||||
def update_analytics_cache
|
||||
# Update cached analytics for faster dashboard loading
|
||||
Rails.cache.delete("project_#{project.id}_analytics")
|
||||
Rails.cache.delete("global_analytics")
|
||||
end
|
||||
end
|
||||
@@ -3,9 +3,7 @@
|
||||
class ProcessWafEventJob < ApplicationJob
|
||||
queue_as :waf_events
|
||||
|
||||
def perform(project_id:, event_data:, headers:)
|
||||
project = Project.find(project_id)
|
||||
|
||||
def perform(event_data:, headers:)
|
||||
# Handle both single event and events array
|
||||
events_to_process = []
|
||||
|
||||
@@ -26,7 +24,7 @@ class ProcessWafEventJob < ApplicationJob
|
||||
event_id = single_event_data['event_id'] || SecureRandom.uuid
|
||||
|
||||
# Create the WAF event record
|
||||
event = Event.create_from_waf_payload!(event_id, single_event_data, project)
|
||||
event = Event.create_from_waf_payload!(event_id, single_event_data)
|
||||
|
||||
# Enrich with geo-location data if missing
|
||||
if event.ip_address.present? && event.country_code.blank?
|
||||
@@ -38,12 +36,12 @@ class ProcessWafEventJob < ApplicationJob
|
||||
end
|
||||
|
||||
# Trigger analytics processing
|
||||
ProcessWafAnalyticsJob.perform_later(project_id: project_id, event_id: event.id)
|
||||
ProcessWafAnalyticsJob.perform_later(event_id: event.id)
|
||||
|
||||
# Check for automatic rule generation opportunities
|
||||
GenerateWafRulesJob.perform_later(project_id: project_id, event_id: event.id)
|
||||
GenerateWafRulesJob.perform_later(event_id: event.id)
|
||||
|
||||
Rails.logger.info "Processed WAF event #{event_id} for project #{project.slug}"
|
||||
Rails.logger.info "Processed WAF event #{event_id}"
|
||||
rescue ActiveRecord::RecordInvalid => e
|
||||
Rails.logger.error "Failed to create WAF event: #{e.message}"
|
||||
Rails.logger.error e.record.errors.full_messages.join(", ")
|
||||
@@ -54,8 +52,8 @@ class ProcessWafEventJob < ApplicationJob
|
||||
end
|
||||
|
||||
# Broadcast real-time updates once per batch
|
||||
project.broadcast_events_refresh
|
||||
ActionCable.server.broadcast("events", { type: "refresh" })
|
||||
|
||||
Rails.logger.info "Processed #{events_to_process.count} WAF events for project #{project.slug}"
|
||||
Rails.logger.info "Processed #{events_to_process.count} WAF events"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user