Lots of updates
This commit is contained in:
@@ -133,25 +133,11 @@ class NetworkRange < ApplicationRecord
|
||||
|
||||
# Find nearest parent with intelligence data
|
||||
def parent_with_intelligence
|
||||
# Use Postgres network operators to find parent ranges directly
|
||||
cidr_str = network.to_s
|
||||
if cidr_str.include?('/')
|
||||
addr_parts = network_address.split('.')
|
||||
case addr_parts.length
|
||||
when 4 # IPv4
|
||||
new_prefix = [prefix_length - 8, 16].max
|
||||
parent_cidr = "#{addr_parts[0]}.#{addr_parts[1]}.#{addr_parts[2]}.0/#{new_prefix}"
|
||||
else # IPv6 - skip for now
|
||||
nil
|
||||
end
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
return nil unless parent_cidr
|
||||
|
||||
NetworkRange.where("network <<= ?::inet AND masklen(network) < ?", parent_cidr, prefix_length)
|
||||
.where.not(asn: nil)
|
||||
# Find all parent ranges (networks that contain this network)
|
||||
# and look for any with intelligence data, ordered by specificity
|
||||
NetworkRange.where("?::inet <<= network", network.to_s)
|
||||
.where("masklen(network) < ?", prefix_length)
|
||||
.where("(asn IS NOT NULL OR company IS NOT NULL OR country IS NOT NULL OR is_datacenter = true OR is_vpn = true OR is_proxy = true)")
|
||||
.order("masklen(network) DESC")
|
||||
.first
|
||||
end
|
||||
@@ -238,6 +224,28 @@ class NetworkRange < ApplicationRecord
|
||||
self.additional_data = hash.to_json
|
||||
end
|
||||
|
||||
# Network data accessors for different data sources
|
||||
# network_data is a JSONB column with namespaced data:
|
||||
# {
|
||||
# geolite: {...}, # MaxMind GeoLite2 data
|
||||
# ipapi: {...}, # IPAPI.is enrichment data
|
||||
# abuseipdb: {...}, # Future: AbuseIPDB data
|
||||
# shodan: {...} # Future: Shodan data
|
||||
# }
|
||||
def network_data_for(source)
|
||||
network_data&.dig(source.to_s) || {}
|
||||
end
|
||||
|
||||
def set_network_data(source, data)
|
||||
self.network_data ||= {}
|
||||
self.network_data[source.to_s] = data
|
||||
end
|
||||
|
||||
# Check if we have network data from a specific source
|
||||
def has_network_data_from?(source)
|
||||
network_data&.key?(source.to_s) && network_data[source.to_s].present?
|
||||
end
|
||||
|
||||
# String representations
|
||||
def to_s
|
||||
cidr
|
||||
@@ -267,6 +275,19 @@ class NetworkRange < ApplicationRecord
|
||||
rules.enabled.where("expires_at IS NULL OR expires_at > ?", Time.current)
|
||||
end
|
||||
|
||||
# Check if this network range needs WAF policy evaluation
|
||||
# Returns true if:
|
||||
# - Never been evaluated, OR
|
||||
# - Any WafPolicy has been updated since last evaluation
|
||||
def needs_policy_evaluation?
|
||||
return true if policies_evaluated_at.nil?
|
||||
|
||||
latest_policy_update = WafPolicy.maximum(:updated_at)
|
||||
return false if latest_policy_update.nil? # No policies exist
|
||||
|
||||
policies_evaluated_at < latest_policy_update
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_default_source
|
||||
|
||||
Reference in New Issue
Block a user