class OpenVPNConfigurator::RouteGatherer
Constants
- AWS_IP_RANGES_URL
Public Instance Methods
extend_template(options)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 20 def extend_template(options) template = read_file options[:input_path] old_output = read_file options[:output_path], nonexistent_behavior: :empty_string routes = gather_routes options reduced = reduce_routes routes rendered = render_routes reduced, client: !!options[:client] result = format "%s\n\n\n# Added by OpenVPN Configurator v%s at %s\n%s", template, VERSION, Time.now.iso8601(6), rendered if result != old_output logger.info "Output content changed, rewriting file #{options[:output_path].inspect}" write_file options[:output_path], result change_actions options else logger.info 'Output content unchanged, no actions taken.' end end
Private Instance Methods
aws_ip_ranges()
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 42 def aws_ip_ranges @aws_ip_ranges ||= begin logger.trace "Fetching AWS IP ranges from #{AWS_IP_RANGES_URL.inspect}" data = RestClient.get AWS_IP_RANGES_URL JSON.parse data, symbolize_names: true end end
change_actions(options)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 51 def change_actions(options) options[:restart_systemd].each { |service| restart_systemd service } end
gather_routes(options)
click to toggle source
@return [Hash<String, Array<NetAddr::IPv4Net, NetAddr::IPv6Net>]
# File lib/openvpn_configurator/route_gatherer.rb, line 57 def gather_routes(options) result = {} options[:route_v4_aws_region].each { |region| result.merge! gather_v4_aws_region(region) } options[:route_v4_dns].each { |name| result.merge! gather_v4_dns(name) } result end
gather_v4_aws_region(region)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 65 def gather_v4_aws_region(region) networks = aws_ip_ranges[:prefixes].select { |p| p[:region] == region } routes = networks.map { |p| NetAddr.parse_net p[:ip_prefix] } { "route-v4-aws-region=#{region}" => routes } end
gather_v4_dns(name)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 74 def gather_v4_dns(name) { "route-v4-dns=#{name}" => resolve_v4(name).map { |a| NetAddr.parse_net "#{a}/32" } } end
read_file(path, nonexistent_behavior: :raise)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 81 def read_file(path, nonexistent_behavior: :raise) File.read path rescue Errno::ENOENT => e case nonexistent_behavior when :empty_string '' else logger.error "Error reading file #{path.inspect}", e raise end end
reduce_routes(routes)
click to toggle source
@return [Hash<String, Array<NetAddr::IPv4Net, NetAddr::IPv6Net>]
# File lib/openvpn_configurator/route_gatherer.rb, line 101 def reduce_routes(routes) seen_v4 = {} seen_v6 = {} reduction = false result = {} routes.each_pair do |name, entries| result[name] = [] entries.each do |entry| seen = case entry when NetAddr::IPv4Net seen_v4 when NetAddr::IPv6Net seen_v6 else nil end if seen covered = nil seen.each_pair do |seen_name, seen_entries| found_entry = seen_entries.find { |s| [1, 0].include? s.rel(entry) } if found_entry covered = [seen_name, found_entry] break end end if covered reduction = true result[name].push Comment.new("Route #{entry} already covered by route #{covered[1]} (#{covered[0]})") else seen[name] ||= [] seen[name].push entry result[name].push entry end else result[name].push entry end end end if reduction reduce_routes result else result end end
render_routes(routes, client: false)
click to toggle source
@param routes [Hash<String, Array<NetAddr::IPv4Net, NetAddr::IPv6Net>>] { “Configuration Source Name” => [NetAddr::IPv4Net, NetAddr::IPv6Net] }
# File lib/openvpn_configurator/route_gatherer.rb, line 167 def render_routes(routes, client: false) indent = "\t\t\t" directive_indent = client ? indent : ' ' prefix = client ? '' : "push#{indent}\"" postfix = client ? '' : '"' result = [] routes.keys.sort.each do |source| result << "##{source}" routes[source].sort_by(&:to_s).each do |route| directive = case route when NetAddr::IPv4Net format '%sroute%s%s%s', prefix, directive_indent, route.extended, postfix when NetAddr::IPv6Net format '%sroute-ipv6%s%s%s', prefix, directive_indent, route.to_s, postfix when Comment format '# %s', route.to_s else raise "Only supporting IPv4 and IPv6 networks presently, got #{route.inspect} instead" end result << directive end result << '' end result.join "\n" end
resolve_v4(name)
click to toggle source
For tests, this method is stubbable @return [Array<NetAddr::IPv4, NetAddr::IPv6>]
# File lib/openvpn_configurator/route_gatherer.rb, line 149 def resolve_v4(name) logger.trace "Performing DNS lookup for hostname #{name.inspect}" Resolv.getaddresses(name).map { |a| NetAddr.parse_ip a }.select { |a| a.is_a? NetAddr::IPv4 } end
restart_systemd(service_name)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 155 def restart_systemd(service_name) logger.info "Restarting systemd service #{service_name.inspect}" system 'systemctl', 'restart', service_name end
write_file(path, contents)
click to toggle source
# File lib/openvpn_configurator/route_gatherer.rb, line 161 def write_file(path, contents) File.write path, contents end