Skip to content

Instantly share code, notes, and snippets.

@grobie
Created March 19, 2013 20:17
Show Gist options
  • Save grobie/5199696 to your computer and use it in GitHub Desktop.
Save grobie/5199696 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'ipaddr'
# Creates a regexp of trusted IP addresses to be used by Rails'
# ActionController::Request::TRUSTED_PROXIES.
#
class TrustedProxyRegexpCreator
OCTET = '\d{1,3}'
EDGECAST_IP_FORMAT = /#{OCTET}\.#{OCTET}\.#{OCTET}\.(\*|#{OCTET})/
EDGECAST_RANGE_FORMAT = /#{EDGECAST_IP_FORMAT} - #{EDGECAST_IP_FORMAT}/
def initialize(list)
@ips = list.split("\n").inject([]) do |memo, line|
case line
when EDGECAST_RANGE_FORMAT
expand(line).each { |ip| memo << ip }
memo
when EDGECAST_IP_FORMAT
memo << sanitize(line)
else
raise ArgumentError, "Unsupported format: #{line.inspect}"
end
end
end
def create
combine(@ips)
end
def self.create(list)
new(list).create
end
protected
def sanitize(address)
address.split('.').map { |octet| octet == '*' ? OCTET : octet }
end
def expand(range)
low, high = range.split(' - ')
(IPAddr.new(low)..IPAddr.new(high)).map { |ip| sanitize ip.to_s }
end
def concat(prefix, suffix)
[prefix, suffix].compact.join('\.')
end
def block(elements)
elements.one? ? elements.first : "(?:#{elements.join('|')})"
end
def suffixable?(elements)
elements.all? { |octets| octets.size == 2 } && elements.group_by(&:last).one?
end
def suffix(elements)
elements.group_by(&:last).map do |group, octets|
concat(block(octets.map(&:first)), group)
end
end
def combine(addresses)
groups = if addresses.all?(&:one?)
addresses
else
addresses.group_by(&:first).map do |group, parts|
parts = parts.map { |octetes| octetes[1..-1] }
# shortcut, edgecast blocks can be mainly grouped by the third octet
concat(group, suffixable?(parts) ? block(suffix(parts)) : combine(parts))
end
end
block(groups)
end
end
if __FILE__ == $0
begin
puts TrustedProxyRegexpCreator.create($stdin.read)
rescue ArgumentError => error
$stderr.puts error.message
exit 1
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment