A python lookup package and command-line tool for infrastructure equipment.
Go to file
2021-07-11 17:16:45 -06:00
bin Added multiple filter support 2021-06-01 17:36:34 -06:00
ifxlookup Fixed a bug in error reprting of the new 'include_parent' feature 2021-07-11 17:16:45 -06:00
config_sample.yml Upgraded bluecat plugin 2021-05-10 13:24:02 -06:00
README.md Improved Documentation 2021-07-06 12:58:45 -06:00
requirements.txt Code cleanup 2020-05-28 12:07:55 -06:00
setup.py Improved Documentation 2021-07-06 12:58:45 -06:00

ifxlookup

A python lookup package and command-line tool for infrastructure equipment.

IFXLookup takes search terms (subjects) such as IP addresses, hostnames, mac addresses, and other identifiers and performs queries against various infrastructure equipment to return datasets for those subjects. Information on some subjects may be found across multiple services. For example, the Bluecat server and the Aruba controller may both have information on an IP address. Including -b and -w will retrieve information on the IP address from both services.

IFXLookup is extensible, so that anyone can write plugins for their specific service to be included in the lookup. By default, several plugins are included.

Installation

  • Clone the repository
  • pip3 install ./ifxlookup
  • cp ifxlookup/config_sample.yml ~/.config/ifxlookup.yml
  • Fill out missing values in ~/.config/ifxlookup.yml
  • ifxlookup -h

Command-Line Tool (ifxlookup)

Usage

usage: ifxlookup [-h] [-c CONFIG] [-f FILTER] [-j] [-cg] [-b] [-l] [-gc] [-d] [-cms] [-vm] [-r] [-w] [-s] [-fw] [-m] [-v]
                 subjects [subjects ...]

positional arguments:
  subjects              IP's, hostnames, MAC's, usernames, or other strings to look up.

optional arguments:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        Specify a config file (~/.config/ifxlookup.yml by default)
  -f FILTER, --filter FILTER
                        Apply a JSONPath filter to the results (multiple filters may be specified)
  -j, --json            Format output as json
  -cg, --vip            VIP information about the subject (f5)
  -b, --bluecat         Bluecat information about the subject (bluecat)
  -l, --ldap            LDAP information about the subject (ldap)
  -gc, --guid_channels  Working channels for GUID
  -d, --dns             DNS resolution about the subject (dns)
  -cms, --channel       CMS channel info about the subject (cms)
  -vm, --vm             VMWare information about the subject (vmware)
  -r, --vpn             VPN log information about the subject (openvpn)
  -w, --wifi            Wireless connection information about the subject (aruba)
  -s, --shodan          Shodan information about the subject (dns)
  -fw, --rules          Firewall addresses, groups, and rules relating to the subject
  -m, --mac             Vendor OUI from a MAC address (mac)
  -v, --debug           Include debug information in the output. Add 'v's for more output.

Configuring

The configuration file for the command line tool is located at ~/.config/ifxlookup.yml by default, though a custom path may be specified on the command line. This config file may be a JSON or YAML file with an entry for each plugin in the plugins directory. A sample configuration file is provided in the repository for convenience. The config file is loaded and parsed for configuration info for all plugins in the plugins folder. Each plugin requires specific configuration options to work properly, and some plugins have optional configuration options. Every plugin used by the command line tool must have a line in the configuration file, even if that configuration is {}. For example, the DNS plugin has an optional configuration option of 'resolver' that takes an array of IP addresses. While this option is not required, an entry for DNS in the configuration file is required to use the plugin. Therefore, the configuration file might look something like this:

dns:
  resolver:
    - 1.1.1.1
    - 8.8.8.8

If you wish to use a plugin that accepts no configuration, the entry would be simply:

dns: {}

Sample Config

I've provided a template config file, config_sample.yml that includes many of the options from my own config file, and can be filled out with a few addresses and credentials to get up and going right away. Don't forget to name it ~/.config/ifxlookup.yml to use the command line tool without specifying -c.

Using filters

IFXLookup may filter the results returned by any and all plugins by applying a JSONPath filter to the results. For example, to only return the MX records of a DNS lookup for all search terms, the command would be:

ifxlookup -d -f '*.dns.mx' sling.com dish.com

You can specify multiple filters with -f, however, all filters run on the results dataset separately. Filters cannot be stacked due to the nature of JSONPath.

Examples

To find the DHCP assigned gateway for a the IP 10.124.24.130:

ifxlookup -b 10.124.24.130 -f '*.bluecat.[*].parent.gateway'

To find the timestamps of the latest Shodan scans for the IP 67.21.62.46:

ifxlookup --shodan 67.21.62.46 -f '*.shodan.data[*].timestamp'

To find the MAC address of the wireless client connected with an IP of 10.124.24.131:

ifxlookup -w 10.124.24.131 -f '*.*.sta_mac_address'

To find what IP addresses are part of the VIP pool for the IP 74.206.195.149:

ifxlookup -cg 74.206.195.149 -f '*.*.members[*].address' -v

To find the manufacturing company of an ethernet device with the MAC address 38:F9:D3:A6:88:C7:

ifxlookup -m "38:F9:D3:A6:88:C7" -f "*.mac.company"

To find the email addresses of all LDAP users whose username starts with 'daniel':

ifxlookup -l daniel -f '*.ldap.*.mail[0]'

To find the callsign of a channel with channel id '24696f5c20ad4d1490111064f0b32dc1':

ifxlookup -cms 24696f5c20ad4d1490111064f0b32dc1 -f '*.cms.channels[0].yaml_configuration_version.channel_title'

To find the operating systems installed on all VM's with 'ifxes' in the name:

ifxlookup --vm ifxes -f "*.vmware[*].guest.full_name.default_message"

Library Documentation

class IFXLookup

configure(config)

ifxlookup.IFXLookup.configure(self,config)

Updates the configuration of the lookup with the given config.

debug_level()

ifxlookup.IFXLookup.debug_level(self)

Gets the debug level.

disable_caching()

ifxlookup.IFXLookup.disable_caching(self)

Disables results caching and enables auto-shutdown of plugins.

dump_config()

ifxlookup.IFXLookup.dump_config(self)

Returns the current configuration state. This likely contains sensitive information such as API keys.

dump_config_to_file(path,print_json)

ifxlookup.IFXLookup.dump_config_to_file(self,path,print_json=False)

Exports the current plugin configuration to a file.

enable_caching()

ifxlookup.IFXLookup.enable_caching(self)

Enables results caching and disables auto-shutdown of plugins.

finish()

ifxlookup.IFXLookup.finish(self)

In the case that caching has been enabled, this enables the plugins to be manually shut down.

get_plugins()

ifxlookup.IFXLookup.get_plugins(self)

Returns a map of plugins configured to use in the lookup.

lookup()

ifxlookup.IFXLookup.lookup(self,subjects,filters=None)

Performs a search with the configured plugins and filters and returns a dictionary of search data.

search_plugins(directory)

ifxlookup.IFXLookup.search_plugins(self,directory=None)

Searches a given directory for compatible plugins and returns a map of available plugin names and classes. Useful for loading plugins from a directory.

set_debug_level(level)

ifxlookup.IFXLookup.set_debug_level(self,level)

Sets the debug level.

use_plugins(plugins,reload)

ifxlookup.IFXLookup.use_plugins(self,plugins,reload=False)

Defines plugins that should be used in a lookup, optionally forcing them to reload.

Example Application

# Perform a DNS lookup with the DNS plugin
from ifxlookup import IFXLookup
lookup = IFXLookup()
lookup.configure({'dns':{'resolver':'1.1.1.1'}})
lookup.use_plugins(['dns'])
lookup.lookup(['google.com'])

Plugins

IFXLookup works by loading plugins in the form of ServiceDelegate objects. Plugins are executed in alphabetical order. ServiceDelegate objects are subclasses of the ServiceBase class, which includes the basic framework for loading your plugin into IFXLookup. The ServiceDelegate subclass is concise enough to make writing simple plugins straightforward and open enough to allow for complex implementations.

Writing a Plugin

Template

To write a new plugin, create a python file with the name of your plugin in the 'plugins' directory. If you don't need to use your plugin in the command-line tool, you can place it wherever you want and import it manually. The name of the plugin will be the name that appears in the plugin's report to the user. You can populate the file with the following template:

from servicebase import ServiceBase

class ServiceDelegate(ServiceBase) :
	def get_arguments(cls) :
		"""Returns an array of information used to construct an argumentparser argument."""
		# [ <short flag>,<unix flag>,<arg type>,<description> ]
        return [ '-nm', '--name', 'store_true', "Return the name of the subject" ]

	def lookup(self,subject) :
		"""Given a subject, return a dictionary or array of information about the subject."""
		return: {'name' : subject ]

The function get_arguments is used by the command line tool to determine when the plugin should be run, based on the arguments the user supplied. Plugins are loaded whenever the script is run.

The function lookup is called for every subject the user submits. The subjects are passed in as raw strings.

Within the lookup function, you should perform any lookups on the host and return a dictionary or array of information about the subject. To make sure that the results are serializable, be sure that dictionaries and arrays are the only data structures in your results.

Loading Configuration

Configuring the python module is similar to configuring the command line tool. Configurations consist of dictionaries with plugin names as the keys and are required for every plugin used in the lookup.

Convenience Functions

Your plugin may need to do some setup before executing lookups, such as logging into an API service or caching a dataset for use in lookups. The convenience functions startup() and shutdown() are called on your plugin before and after lookups are called on your plugin. This allows you to do any setup your plugin needs without overriding __init__(). It also allows you to perform any cleanup your plugin may need, such as logging out any outstanding sessions.

The self.debug() allows your plugin to print verbose output to the console if requested by the user. This output is printed to stderr and not added to your plugin's report.

Example:

self.debug("This message will be printed to the console when the user passes a -vv argument",2)

Your plugin can report errors and warnings by appending them to the list self._error and self._warn, respectively. They will be appended to the report for your plugin (or removed from the report if the user specifies).

Contributing

If you have a plugin for a piece of equipment that could be useful to others on the team, I'd love to add it to the project. Submit a pull request and let's get it added!


Justification

While reviewing reports from various network services I'd often find myself cross-referencing several sites to get the information I was lookup for on a particular IP, mac address or host. What's more, the information I gathered from each site had to be formatted by hand if I wanted to build a report of a particular host at a particular time. I wrote this tool to keep from opening a bunch of tabs and copy-pasting information from each into a text file for storage.

Known issues with this version:

  • Caching is not yet implemented