diff --git a/ifxlookup b/ifxlookup index 39e5f4d..27ca960 100755 --- a/ifxlookup +++ b/ifxlookup @@ -17,16 +17,12 @@ import importlib yaml.Dumper.ignore_aliases = lambda *args : True - class IFXLookup(): DEFAULT_CONFIG = '~/.config/ifxlookup.yml' - _errorinfo = {} - _warninfo = {} _plugin_map = {} _delegate_map = {} - _internal_messages = {} _debug_level = 0 _config = {} _caching = False @@ -38,7 +34,7 @@ class IFXLookup(): pass def __add_plugin(self,plugin,reload) : - """Adds a given ServiceBase plugin to the instance, reinitializing it if it already exists and such is specified.""" + """Adds a given ServiceBase plugin and instance, reinitializing one if it already exists and such is specified.""" plugin_name = plugin.__module__.split('.')[-1] if not reload and plugin_name in self._plugin_map.keys(): pass @@ -52,22 +48,23 @@ class IFXLookup(): self._plugin_map.update({plugin_name:plugin}) self._delegate_map.update({plugin_name:plugin()}) - def __init_once(self,plugin_obj) : - if plugin_obj not in self._initialized_plugins : - plugin_obj.startup() - self._initialized_plugins.append(plugin_obj) + def __init_once(self,instance) : + """Runs the startup function on the instance once.""" + if instance not in self._initialized_plugins : + instance.startup() + self._initialized_plugins.append(instance) def __shutdown_plugins(self) : """Shutdown all plugins.""" - for plugin in self._delegate_map.values() : - plugin.shutdown() + for instance in self._delegate_map.values() : + instance.shutdown() def __namespace(self) : """Generate map of ifxlookup runtime values that should be made available to plugins.""" return {'debug' : self._debug_level,'caching': self._caching} def __filter_and_return(self,subjects,dataset,filter) : - """Returns the submitted dataset""" + """Returns the submitted dataset, applying the given filter.""" final_result = {} if 'error' in dataset or 'warn' in dataset : final_result['status'] = {} @@ -80,7 +77,6 @@ class IFXLookup(): for plugin in [x for x in dataset if x != 'error' and x != 'warn'] : subjectdataset.update({plugin:dataset[plugin][subject]}) final_result.update({subject:subjectdataset}) - # Apply Filter if filter : jsonpath_filter = jsonpath_ng.parse(filter) @@ -93,25 +89,15 @@ class IFXLookup(): if type(plugins) is not list : raise ValueError('argument \'plugins\' should be of type list') for plugin in plugins : - # Check if the plugin is a string or a descendent of the ServiceBase class + # Check if the plugin is a string or a descendent of a ServiceBase class if type(plugin) is not str and 'ServiceBase' not in [x.__name__ for x in inspect.getmro(plugin)] : raise ValueError('unkown type for plugin') # Find plugins by name using a default path if type(plugin) is str : - pluginfolder = 'plugins' - testpath = os.path.realpath(__file__) - filedir = '/'.join(testpath.split('/')[:-1]) - pluginpath = filedir + '/' + pluginfolder - pluginfiles = [x for x in os.listdir(pluginpath) if plugin in x and x.endswith('.py')] - pluginfiles = sorted(pluginfiles) - if len(pluginfiles) == 0 : + available_plugins = [y for x,y in self.search_plugins().items() if x == plugin and 'ServiceBase' in [z.__name__ for z in inspect.getmro(y)]] + if len(available_plugins) is 0 : raise FileNotFoundError(plugin + '.py not found') - importlib.import_module(pluginfolder) - for pluginfile in pluginfiles : - plugin = getattr(importlib.import_module(pluginfolder+"."+pluginfile.split('.')[0]),'ServiceDelegate') - self.__add_plugin(plugin,reload) - continue - # Load normal ServiceBase classes + plugin = available_plugins[0] if 'ServiceBase' in [x.__name__ for x in inspect.getmro(plugin)] : self.__add_plugin(plugin,reload) continue @@ -146,11 +132,11 @@ class IFXLookup(): file_descriptor = open(os.path.normpath(os.path.expanduser(os.path.expandvars(config)))) try : file_descriptor = open(os.path.normpath(os.path.expanduser(os.path.expandvars(config)))) - totalconfig = json.load(file_descriptor) + total_config = json.load(file_descriptor) except json.decoder.JSONDecodeError as exception : file_descriptor = open(os.path.normpath(os.path.expanduser(os.path.expandvars(config)))) - totalconfig = yaml.safe_load(file_descriptor) - self._config.update(totalconfig) + total_config = yaml.safe_load(file_descriptor) + self._config.update(total_config) def dump_config(self) : """Returns the current configuration state. This likely contains sensitive information such as API keys.""" @@ -166,9 +152,11 @@ class IFXLookup(): def set_debug_level(self,level) : """Sets the debug level""" - if not level : + try: + level = int(level) + except Exception: level = 0 - self._debug_level = int(level) + self._debug_level = level return self def debug_level(self) : @@ -243,19 +231,19 @@ if __name__ == '__main__': available_plugins = search.search_plugins() # Define constants - configdir = os.path.expanduser('~/.config') - configfilename = 'ifxlookup.yml' - servicetemplate = {'hosts':[],'username':'','key':''} - configtemplate = {'bluecat':servicetemplate,'f5':servicetemplate,'paloalto':servicetemplate,'aruba':servicetemplate,'openvpn':servicetemplate} - configerror = {'config': 'There was a problem reading your config file, aborting.'} - errorinfo = {} + config_dir = os.path.expanduser('~/.config') + config_filename = 'ifxlookup.yml' + service_template = {'hosts':[],'username':'','key':''} + config_template = {'bluecat':service_template,'f5':service_template,'paloalto':service_template,'aruba':service_template,'openvpn':service_template} + config_error = {'config': 'There was a problem reading your config file, aborting.'} + error_info = {} # Gather Argument options parser = argparse.ArgumentParser() parser.add_argument('-c', '--config', action='store', help='Specify a config file (~/.config/ifxlookup.yml by default)') parser.add_argument('-f', '--filter', action='store', default=None, help='Apply a JSONPath filter to the results') parser.add_argument('-j', '--json', action='store_true', help='Return results as a json object') - # parser.add_argument('-l', '--link', action='store_true', help="Return physical link information about the subject") + # parser.add_argument('-l', '--link', action='store_true', help='Return physical link information about the subject') for delegate in available_plugins.values() : arguments = delegate().get_arguments() if arguments and len(arguments) == 4 : @@ -267,7 +255,6 @@ if __name__ == '__main__': # Load plugins based on submitted args selected_plugins = [] - if vars(args)['all'] : for delegate in available_plugins.values() : selected_plugins.append(delegate) @@ -289,46 +276,46 @@ if __name__ == '__main__': if args.config : # TODO: this section throws a yaml error if a json doc can't be found, errors should be more specific. try: - # totalconfig = yaml.safe_load(open(os.path.normpath(args.config))) config = config=os.path.normpath(args.config) except Exception as exception : - errorinfo.update(configerror) + error_info.update(config_error) else : try: - config = config=os.path.normpath(configdir + '/' + configfilename) + config = config=os.path.normpath(config_dir + '/' + config_filename) except FileNotFoundError as exception : - if not os.path.exists(os.path.normpath(configdir)): - os.makedirs(os.path.normpath(configdir)) - if not os.path.exists(os.path.normpath(configdir + '/' + configfilename)): - with open(configdir + '/' + configfilename, 'w') as output : - yaml.dump(configtemplate, output) - errorinfo.update({'config': 'Config file ' + configdir + '/' + configfilename + ' is empty, aborting.'}) + if not os.path.exists(os.path.normpath(config_dir)): + os.makedirs(os.path.normpath(config_dir)) + if not os.path.exists(os.path.normpath(config_dir + '/' + config_filename)): + with open(config_dir + '/' + config_filename, 'w') as output : + yaml.dump(config_template, output) + error_info.update({'config': 'Config file ' + config_dir + '/' + config_filename + ' is empty, populating with a template.'}) else : - errorinfo.update(configerror) + error_info.update(config_error) except Exception as exception : - errorinfo.update(configerror) + error_info.update(config_error) if not config : - with open(configdir + '/' + configfilename, 'w') as output : - yaml.dump(configtemplate, output) - errorinfo.update({'config': 'Config file ' + configdir + '/' + configfilename + ' is empty, populating with a template.'}) + with open(config_dir + '/' + config_filename, 'w') as output : + yaml.dump(config_template, output) + error_info.update({'config': 'Config file ' + config_dir + '/' + config_filename + ' is empty, populating with a template.'}) # Stop on initialization error if not config : - errorinfo.update(configerror) + error_info.update(config_error) try : file_descriptor = open(os.path.normpath(os.path.expanduser(os.path.expandvars(config)))) - totalconfig = json.load(file_descriptor) + total_config = json.load(file_descriptor) except json.decoder.JSONDecodeError as exception : file_descriptor = open(os.path.normpath(os.path.expanduser(os.path.expandvars(config)))) - totalconfig = yaml.safe_load(file_descriptor) + total_config = yaml.safe_load(file_descriptor) for plugin_name in search.get_plugins().keys() : - if plugin_name not in totalconfig.keys() : - errorinfo.update({'config': 'Config file is missing information for plugin ' + plugin_name}) - if errorinfo != {} : - print(subjects,{'error':errorinfo}) + if plugin_name not in total_config.keys() : + error_info.update({'config': 'Config file is missing information for plugin ' + plugin_name}) + if error_info != {} : + print(subjects,{'error':error_info}) exit(1) - search.configure(totalconfig) - + search.configure(total_config) search.set_debug_level(args.debug) + + # Run search report = search.lookup(args.subjects,filter=args.filter) if args.json : print(json.dumps(report)) diff --git a/plugins/aruba.py b/plugins/aruba.py index 4a3f332..95e446c 100644 --- a/plugins/aruba.py +++ b/plugins/aruba.py @@ -18,7 +18,7 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" - return ['-w', '--wifi', 'store_true', "Return wireless connection information about the subject (aruba)"] + return ['-w', '--wifi', 'store_true', 'Return wireless connection information about the subject (aruba)'] def startup(self) : for requirement in ['host','username','key'] : @@ -35,11 +35,11 @@ class ServiceDelegate(ServiceBase) : apssortfield = 'mon_ssid' apsfilter = 'mon_ap_status equals 1' apsdevicetype = 'mon_bssid' - self.debug("Retrieving list of Aruba's detected basestations...",1) + self.debug('Retrieving list of Aruba\'s detected basestations...',1) self.aruba_basestations = self.perform_list_query(apsquery,self.aps_fields,apssortfield,apsfilter,apsdevicetype) - self.debug("Retrieving list of Aruba connected clients...",1) + self.debug('Retrieving list of Aruba connected clients...',1) self.aruba_hosts = self.perform_list_query(clientsquery,self.clients_fields,clientssortfield,clientsfilter,clientsdevicetype) - self.debug("Searching Aruba information...",1) + self.debug('Searching Aruba information...',1) def lookup(self,subject) : # We return the first result that matches the subject out of our lists of Aruba information. @@ -75,17 +75,17 @@ class ServiceDelegate(ServiceBase) : if subject.lower() in str(value) : return entry # Not found - return {} + return None def start_session(self,host,username,key) : - headers = { "Content-Type": "application/x-www-form-urlencoded" } - data = "opcode=login&uid=" + username + "&passwd=" + key - self.api_session.post("https://" + host + "/screens/wms/wms.login",verify=False,headers=headers,data=data) + headers = { 'Content-Type': 'application/x-www-form-urlencoded' } + data = 'opcode=login&uid=' + username + '&passwd=' + key + self.api_session.post('https://' + host + '/screens/wms/wms.login',verify=False,headers=headers,data=data) if 'SESSION' in self.api_session.cookies.get_dict() : self.session_key = self.api_session.cookies.get_dict()['SESSION'] def perform_list_query(self,queryname,columnlist,sortfield,queryfilter,devicetype) : - """Performs a list-type XML query against the Aruba UI API""" + """"Performs a list-type XML query against the Aruba UI API""" # So uncivilized. # Build the basic object for our list query. Takes the parameters that the Aruba controller needs for it's # XML api, performs the query, and returns a list of results. @@ -129,9 +129,9 @@ class ServiceDelegate(ServiceBase) : while not finished : start_row.text = str(nextstart) num_rows.text = str(self.query_page_size) - datapayload = "".join(['query=',tostring(aruba_queries).decode(),'&UIDARUBA=',self.session_key]) - page = self.api_session.post("https://" + self.host + "/screens/cmnutil/execUiQuery.xml",verify=False,timeout=1,data=datapayload) - self.debug("Got a page of results from Aruba host...",3) + datapayload = ''.join(['query=',tostring(aruba_queries).decode(),'&UIDARUBA=',self.session_key]) + page = self.api_session.post('https://' + self.host + '/screens/cmnutil/execUiQuery.xml',verify=False,timeout=1,data=datapayload) + self.debug('Got a page of results from Aruba host...',3) if page.status_code == 100 or page.status_code == 200 : pagecontents = ElementTree.fromstring(page.text) rows = pagecontents.iter('row') @@ -154,5 +154,5 @@ class ServiceDelegate(ServiceBase) : nextstart = nextstart + self.query_page_size else : finished = True - self.debug("Retrieved " + str((len(allitems))) + " results from query",2) + self.debug('Retrieved ' + str((len(allitems))) + ' results from query',2) return allitems diff --git a/plugins/bluecat.py b/plugins/bluecat.py index 7f3d9c4..91580e3 100644 --- a/plugins/bluecat.py +++ b/plugins/bluecat.py @@ -10,7 +10,7 @@ class ServiceDelegate(ServiceBase) : host = None def get_arguments(cls) : - return ['-b', '--bluecat', 'store_true', "Return network information about the subject (bluecat)"] + return ['-b', '--bluecat', 'store_true', 'Return network information about the subject (bluecat)'] def startup(self) : for requirement in ['host','username','key'] : @@ -19,43 +19,48 @@ class ServiceDelegate(ServiceBase) : return self.host = self.config['host'] self.current_auth_header = self.get_bc_auth_header(self.config['host'],self.config['username'],self.config['key']) - self.debug("Searching BlueCat for hosts...",1) + self.debug('Searching BlueCat for hosts...',1) def lookup(self,subject) : self.return_payload = {} if self.current_auth_header : object = self.search_bc_object(subject) - self.return_payload.update({'object':object}) + if object : + self.return_payload.update({'object':object}) parent = self.search_bc_parent_object(subject) - self.return_payload.update({'parent':parent}) - return self.return_payload + if parent : + self.return_payload.update({'parent':parent}) + if len(self.return_payload) > 0 : + return self.return_payload + else : + return None else : - return self.return_payload + return None def shutdown(self) : if self.host and self.current_auth_header : - logout = requests.get("https://" + self.host + "/Services/REST/v1/logout",headers=self.current_auth_header) - if not logout.text.endswith("successfully logged out.\"") : + logout = requests.get('https://' + self.host + '/Services/REST/v1/logout',headers=self.current_auth_header) + if not logout.text.endswith('successfully logged out.\"') : self.error.append('Unable to log out of BlueCat API session') def get_bc_auth_header(self,host,username,password) : - auth_token = requests.get("https://" + host + "/Services/REST/v1/login?username=" + username + "&password=" + password).text[17:71] + auth_token = requests.get('https://' + host + '/Services/REST/v1/login?username=' + username + '&password=' + password).text[17:71] if auth_token.startswith('BAMAuthToken') : - return { "Authorization" : auth_token } + return { 'Authorization' : auth_token } else : return None def search_bc_object(self,subject) : """Searches BC for the subject.""" # Search by IP - response = requests.get("https://" + self.host + "/Services/REST/v1/searchByObjectTypes?keyword=" + subject + "&types=IP4Address,IP6Address&start=0&count=10",headers=self.current_auth_header) + response = requests.get('https://' + self.host + '/Services/REST/v1/searchByObjectTypes?keyword=' + subject + '&types=IP4Address,IP6Address&start=0&count=10',headers=self.current_auth_header) return self.clean_response(response) def search_bc_parent_object(self,subject) : """Search for and return information about the objects parent, if any""" if 'object' in self.return_payload and type(self.return_payload['object']) is dict and 'id' in self.return_payload['object'] : - response = requests.get("https://" + self.host + "/Services/REST/v1/getParent?entityId=" + str(self.return_payload['object']['id']), headers=self.current_auth_header) + response = requests.get('https://' + self.host + '/Services/REST/v1/getParent?entityId=' + str(self.return_payload['object']['id']), headers=self.current_auth_header) return self.clean_response(response) # Make a guess that it belongs to a static net that hasn't been put in bluecat elif subject != '' : @@ -63,7 +68,7 @@ class ServiceDelegate(ServiceBase) : try : ip = ipaddress.IPv4Network(subject + net,strict=False) network = str(ip.network_address) - response = requests.get("https://" + self.host + "/Services/REST/v1/searchByObjectTypes?keyword=" + network + "&types=IP4Network,IP4Block&start=0&count=10",headers=self.current_auth_header) + response = requests.get('https://' + self.host + '/Services/REST/v1/searchByObjectTypes?keyword=' + network + '&types=IP4Network,IP4Block&start=0&count=10',headers=self.current_auth_header) if not response.text.startswith('[]') : return self.clean_response(response) except: @@ -80,11 +85,11 @@ class ServiceDelegate(ServiceBase) : parsed = parsed[0] if type(parsed) is dict : if 'properties' in parsed : - parsed["properties"] = parsed["properties"][:-1] - bad_delim_props = [x for x in parsed["properties"].split("|") if x.count('=') > 1] + parsed['properties'] = parsed['properties'][:-1] + bad_delim_props = [x for x in parsed['properties'].split('|') if x.count('=') > 1] if len(bad_delim_props) > 0 : - parsed.update({"unknown":bad_delim_props}) - attributes = dict(x.split("=") for x in parsed["properties"].split("|") if x.count('=') == 1) - parsed.pop("properties", None) + parsed.update({'unknown':bad_delim_props}) + attributes = dict(x.split('=') for x in parsed['properties'].split('|') if x.count('=') == 1) + parsed.pop('properties', None) parsed.update(attributes) return parsed diff --git a/plugins/dns.py b/plugins/dns.py index 2406684..6de8e21 100644 --- a/plugins/dns.py +++ b/plugins/dns.py @@ -8,7 +8,7 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" - return [ '-d', '--dns', 'store_true', "Return DNS resolution about the subject (dns)" ] + return [ '-d', '--dns', 'store_true', 'Return DNS resolution about the subject (dns)' ] def startup(self) : self.resolver = dns.resolver.Resolver() @@ -29,11 +29,11 @@ class ServiceDelegate(ServiceBase) : subjecttuple = socket.gethostbyname_ex(subject) except socket.gaierror : # Not a valid host or IP - self.error.append("Unable to resolve " + subject) + self.error.append('Unable to resolve ' + subject) subjecttuple = [subject,[],['']] # Can't make IPv4 out of it except socket.gaierror : - self.error.append("Unable to resolve " + subject) + self.error.append('Unable to resolve ' + subject) subjecttuple = [subject,[],['']] # Get additional records return_dict = {} diff --git a/plugins/f5.py b/plugins/f5.py index 6c394b8..9ba7b86 100644 --- a/plugins/f5.py +++ b/plugins/f5.py @@ -13,7 +13,7 @@ class ServiceDelegate(ServiceBase) : _partition = 'Common' def get_arguments(cls) : - return ['-cg', '--vip', 'store_true', "Return VIP information about the subject (f5)"] + return ['-cg', '--vip', 'store_true', 'Return VIP information about the subject (f5)'] def startup(self) : for requirement in ['hosts','username','key'] : @@ -21,7 +21,7 @@ class ServiceDelegate(ServiceBase) : self.error.append('Missing required config option ' + requirement) return self.hosts = self.config['hosts'] - self.debug("Logging into F5's and searching for hosts, this make take some time.",1) + self.debug('Logging into F5\'s and searching for hosts, this make take some time.',1) def lookup(self,subject) : self.return_payload = {} @@ -30,7 +30,7 @@ class ServiceDelegate(ServiceBase) : if logincandidates == {} : # Idk what to do here, do we give up or do we log in to all of them? self.error.append('Unable to find an LB to log into to check host ' + str(subject)) - return self.return_payload + return None for host in logincandidates.keys() : auth_header = self.get_iq_auth_header(host,self.config['username'],self.config['key']) @@ -42,7 +42,7 @@ class ServiceDelegate(ServiceBase) : vips = self.get_vip(host,auth_header); # If it's a VIP, return it and the host and let's be done if vips : - self.debug("Got vips from " + host,3) + self.debug('Got vips from ' + host,3) vip_match = [ x for x in vips if x['destination'].split('/' + self._partition + '/')[1].startswith(subject)] all_vips = [ x['destination'] for x in vips ] if len(vip_match) > 0 : @@ -54,15 +54,15 @@ class ServiceDelegate(ServiceBase) : self.return_payload.update(pool_info) break else : - self.debug("Unable to find VIP in VIPs from host " + host,2) + self.debug('Unable to find VIP in VIPs from host ' + host,2) else : # Otherwise, get all nodes. # If it's in the nodes, we have to start all over and find where. # Take all vips and get all pools # Check if address is in the pool. If it is, return the node, pool, vip, and host. # Naw, I'll just give up. - self.debug("Unable to get VIPs from " + host,2) - if self.return_payload == {} : + self.debug('Unable to get VIPs from ' + host,2) + if len(self.return_payload) is 0 : self.return_payload = None return self.return_payload @@ -71,50 +71,50 @@ class ServiceDelegate(ServiceBase) : def get_iq_auth_header(self,host,username,password) : - assumed_login_provider = "tmos" + assumed_login_provider = 'tmos' token = None try : - payload = { "username" : username, "password" : password, "loginProviderName" : assumed_login_provider } + payload = { 'username' : username, 'password' : password, 'loginProviderName' : assumed_login_provider } login = requests.post('https://' + host + '/mgmt/shared/authn/login', json=payload,verify=False,timeout=2) if 'token' in json.loads(login.text) : token = json.loads(login.text)['token']['token'] except Exception as exception: - self.debug("Exception getting auth header for host " + host + ": \n" + str(exception),2) + self.debug('Exception getting auth header for host ' + host + ': \n' + str(exception),2) return None if token : - return { "X-F5-Auth-Token" : token } + return { 'X-F5-Auth-Token' : token } else : return None def get_vip(self,host,header) : """Given a host and an authorization header, gets all the vips for that host""" # Please don't give me empty auth headers, I don't want to check it everywhere - self.debug("Trying VIP info for " + host,2) + self.debug('Trying VIP info for ' + host,2) try : - vips = requests.get("https://" + host + '/mgmt/tm/ltm/virtual',headers=header,verify=False,timeout=10) + vips = requests.get('https://' + host + '/mgmt/tm/ltm/virtual',headers=header,verify=False,timeout=10) if vips.status_code == 200 : return json.loads(vips.text)['items'] - self.debug("Response not OK for " + vips.history[0].url,3) + self.debug('Response not OK for ' + vips.history[0].url,3) return None except Exception as exception : - self.debug("Exception getting VIPs for host " + host + ": \n" + str(exception),2) + self.debug('Exception getting VIPs for host ' + host + ': \n' + str(exception),2) return None def get_pool(self,host,header,pool) : """Given a host, auth header, and pool, return the pool and it's members from the host""" try : - pools = requests.get("https://" + host + "/mgmt/tm/ltm/pool/~" + self._partition + "~" + pool,headers=header,verify=False,timeout=5) + pools = requests.get('https://' + host + '/mgmt/tm/ltm/pool/~' + self._partition + '~' + pool,headers=header,verify=False,timeout=5) if pools.status_code == 200 : poolobj = json.loads(pools.text) - members = requests.get("https://" + host + "/mgmt/tm/ltm/pool/~" + self._partition + "~" + pool + "/members",headers=header,verify=False,timeout=10) + members = requests.get('https://' + host + '/mgmt/tm/ltm/pool/~' + self._partition + '~' + pool + '/members',headers=header,verify=False,timeout=10) if members.status_code == 200 : membersobj = json.loads(members.text)['items'] return {'pool':poolobj,'members':membersobj} return {'pool':poolobj} - elf.debug("Response not OK for " + pool.history[0].url,3) + elf.debug('Response not OK for ' + pool.history[0].url,3) return None except Exception as exception: - self.debug("Exception getting pool for host " + host + ": \n" + str(exception),2) + self.debug('Exception getting pool for host ' + host + ': \n' + str(exception),2) return None def choose_host(self,subject) : @@ -132,7 +132,7 @@ class ServiceDelegate(ServiceBase) : hosts.update({host:self.hosts[host]}) if hosts != {} : return hosts - self.debug("Unable to determine DC from subject name: " + subject,3) + self.debug('Unable to determine DC from subject name: ' + subject,3) # No hostname match, maybe we have info from bluecat? if 'bluecat' in self.hints and subject in self.hints['bluecat'] and self.hints['bluecat'][subject]['object'] : if 'locationCode' in self.hints['bluecat'][subject]['object'] : @@ -142,6 +142,6 @@ class ServiceDelegate(ServiceBase) : for host in self.hosts.keys() : if potentialdc.lower() in host.lower() : hosts.update({host:self.hosts[host]}) - self.debug("Got additional host info from the BlueCat plugin!",3) + self.debug('Got additional host info from the BlueCat plugin!',3) return hosts return hosts diff --git a/plugins/guid_channels.py b/plugins/guid_channels.py index c5b40cc..a1902d5 100644 --- a/plugins/guid_channels.py +++ b/plugins/guid_channels.py @@ -7,7 +7,7 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" - return [ '-gc','--guid_channels', 'store_true', "Return working channels for GUID" ] + return [ '-gc','--guid_channels', 'store_true', 'Return working channels for GUID' ] def startup(self) : @@ -46,7 +46,7 @@ class ServiceDelegate(ServiceBase) : 'env': 'production', 'user_id': user_guid, 'channel_id': channel_guid, - 'message': [8,4] + 'message': self.sample_pssh } drm_req = requests.post('http://p-drmwv.movetv.com/widevine/proxy', json=payload) if drm_req.status_code == 200 : @@ -55,3 +55,5 @@ class ServiceDelegate(ServiceBase) : verbosity = 3 self.debug('Got ' + str(drm_req.status_code) + ' for channel ' + str(channel_guid) + ' for user ' + str(user_guid) + ' (' + str(self.progress) + '/' + str(self.goal) + ')',verbosity) return drm_req.status_code + + sample_pssh = [8,1,18,129,29,18,82,10,80,10,58,8,1,18,32,99,53,101,53,48,55,51,100,51,102,48,50,52,49,98,102,56,97,99,54,48,99,101,101,48,55,101,98,49,48,98,100,26,7,115,108,105,110,103,116,118,34,4,84,79,80,67,42,5,83,68,95,72,68,16,1,26,16,153,14,129,143,185,186,160,15,125,191,37,127,114,2,45,119,24,1,32,219,170,139,246,5,48,21,66,160,28,10,20,108,105,99,101,110,115,101,46,119,105,100,101,118,105,110,101,46,99,111,109,18,16,23,5,185,23,204,18,4,134,139,6,51,58,47,119,42,140,26,224,25,242,201,29,158,43,232,104,47,129,35,98,111,59,142,28,129,168,11,159,148,192,74,217,38,158,149,123,124,72,122,19,71,206,205,76,213,223,123,198,219,23,213,18,39,213,25,52,46,198,133,224,164,73,42,243,6,44,171,203,212,53,91,230,221,217,48,148,27,33,76,27,51,113,59,125,242,195,48,97,118,233,143,4,132,225,136,102,186,116,83,234,142,98,8,83,121,192,168,147,199,233,89,148,112,35,177,163,120,112,230,129,236,221,183,216,136,207,116,84,131,93,15,86,32,19,237,4,169,196,47,20,229,103,15,66,206,74,163,5,136,242,117,69,135,82,84,97,190,131,1,1,34,35,106,219,137,17,188,11,135,21,244,56,79,147,162,63,87,166,72,2,210,190,1,52,134,186,87,4,36,231,178,252,130,192,1,76,6,232,131,8,126,174,178,89,80,209,155,229,63,19,216,64,207,163,50,222,67,59,209,74,26,136,219,144,26,125,177,76,57,167,51,55,25,88,181,240,106,71,3,168,199,52,16,92,125,143,181,216,176,220,85,29,105,213,190,39,189,17,206,21,16,58,138,180,8,36,164,30,234,19,226,32,101,191,225,145,203,126,148,100,38,237,66,15,192,3,187,144,100,204,50,72,28,20,84,226,184,97,199,129,192,14,60,133,136,19,17,246,202,132,87,137,198,159,129,134,221,203,103,213,32,32,40,65,194,251,102,113,245,137,251,143,142,146,219,114,149,203,81,11,63,39,170,142,134,141,139,15,119,83,228,248,60,183,176,134,161,234,138,65,179,175,142,116,172,223,235,184,0,103,53,80,123,177,252,255,197,47,244,176,70,119,69,45,197,49,74,25,131,141,119,34,145,218,139,157,218,255,163,48,198,74,106,99,92,33,30,220,41,170,88,250,247,198,53,45,226,41,51,192,140,221,78,180,1,72,253,97,191,209,250,154,243,103,142,102,37,56,49,69,77,73,26,252,69,168,42,74,177,127,233,147,53,193,209,152,5,73,81,0,50,247,97,204,107,54,200,64,152,96,144,148,103,59,207,82,44,124,58,191,130,223,41,202,54,74,146,190,170,24,73,208,49,49,87,31,176,67,152,211,135,247,30,107,168,183,168,139,84,198,24,164,48,93,253,119,179,19,127,249,214,57,74,254,122,55,226,202,175,195,211,123,27,255,204,171,152,87,223,3,191,135,245,252,238,78,22,209,184,110,47,65,23,154,204,5,61,249,213,234,30,246,46,71,130,94,250,11,105,74,185,126,40,63,115,160,62,121,128,215,24,170,226,97,22,79,183,65,124,40,245,229,92,87,154,214,74,193,66,69,90,21,191,121,70,130,54,125,85,136,186,85,67,21,92,231,119,15,166,132,135,159,53,67,99,38,79,141,29,177,63,64,10,178,28,229,205,22,217,178,196,56,234,170,168,235,249,66,22,248,103,180,158,5,159,24,104,196,1,146,246,168,84,200,210,81,172,130,103,70,63,201,165,76,16,152,32,106,26,32,60,42,122,122,165,171,204,134,214,194,215,14,85,26,37,87,240,151,191,160,170,53,85,20,253,6,11,72,73,240,207,68,230,145,86,180,126,254,204,59,189,120,5,200,32,140,94,230,115,93,136,175,74,94,152,81,57,187,157,206,159,44,50,59,106,254,196,226,63,184,11,58,24,248,125,78,39,169,60,97,10,231,37,158,162,4,216,238,79,89,45,149,53,88,86,179,101,112,42,202,186,120,238,58,103,202,78,136,224,63,16,108,71,38,49,185,240,1,158,35,79,228,58,25,32,170,59,140,93,89,136,47,10,24,220,1,141,219,200,90,234,176,221,7,242,189,243,113,44,240,16,44,40,156,53,242,123,52,139,108,215,7,148,219,253,39,234,89,38,151,178,26,154,72,26,226,84,207,170,236,25,1,205,210,20,223,95,243,157,87,252,210,38,82,230,148,60,254,182,81,128,14,41,209,153,3,152,190,221,87,224,59,190,58,26,3,245,64,18,175,146,66,34,193,241,56,97,152,155,82,226,155,180,16,126,135,71,137,228,141,199,52,220,143,73,216,92,236,224,57,11,138,240,242,252,113,246,197,111,42,202,134,57,48,114,0,101,11,47,90,195,166,204,55,96,78,47,151,198,203,46,130,220,149,99,181,166,20,90,125,245,211,68,241,51,75,32,96,223,111,10,128,213,87,79,202,246,49,238,43,6,151,77,175,29,36,183,190,92,57,177,69,71,89,18,145,188,73,3,72,225,229,42,34,209,66,241,244,193,200,250,179,29,13,230,226,194,150,29,220,64,12,85,238,133,101,215,192,30,40,174,32,56,50,56,23,84,222,18,48,20,199,92,143,101,99,142,8,34,131,87,123,12,156,144,99,141,153,210,250,112,233,18,43,7,70,156,178,208,187,67,124,85,19,120,181,27,18,9,123,150,227,101,238,19,179,24,86,3,157,23,128,30,21,225,119,120,230,253,239,53,161,161,69,133,56,184,44,133,2,154,81,201,93,116,48,86,7,102,249,12,179,202,237,66,54,110,125,9,14,157,77,184,122,144,193,69,60,246,102,70,219,244,162,9,3,184,53,42,8,197,160,252,150,121,146,7,174,114,137,185,86,192,111,4,158,66,29,200,68,114,1,230,208,23,131,63,122,206,145,202,245,125,217,238,80,62,208,158,199,175,177,196,242,138,246,129,186,19,19,133,152,56,94,47,185,13,59,75,136,154,126,8,66,240,68,82,105,26,112,102,150,161,244,103,54,188,226,114,52,107,76,201,26,243,155,182,15,234,168,176,107,83,189,174,4,160,11,218,254,118,33,209,108,212,61,232,168,201,204,147,205,198,80,205,68,233,118,182,244,203,235,12,49,104,170,26,243,78,78,22,95,230,209,178,64,102,143,219,184,253,133,38,124,144,48,116,124,247,199,118,160,94,128,205,188,92,5,37,134,68,212,218,163,170,165,15,155,114,198,146,251,70,12,7,43,12,114,152,161,208,4,159,177,153,107,129,53,172,35,179,98,102,73,81,249,123,128,116,197,97,150,63,103,205,198,102,95,86,102,114,153,138,155,103,151,94,241,115,221,212,48,196,196,15,168,22,143,169,33,223,23,104,209,10,237,158,250,6,230,45,196,13,124,35,194,150,255,131,57,140,93,235,140,13,136,192,216,66,5,49,90,7,126,38,92,166,107,37,38,202,109,69,215,95,48,26,251,220,209,228,171,151,3,222,95,221,155,66,22,228,198,208,15,58,170,92,105,203,36,35,184,136,0,241,209,55,247,122,19,39,177,222,51,37,251,194,203,111,138,231,179,40,140,156,140,173,22,12,206,28,51,116,150,34,185,145,58,62,160,125,229,193,62,161,208,16,173,193,7,38,150,254,196,143,60,211,103,204,107,31,170,124,67,35,64,195,12,216,211,234,74,16,63,104,119,190,105,209,39,223,94,110,30,246,28,164,243,64,99,83,198,190,84,114,174,126,183,227,232,165,29,96,236,219,0,195,228,14,93,47,129,112,16,93,248,157,23,195,126,29,46,224,56,144,128,29,13,245,248,215,209,89,116,70,2,28,145,104,185,98,122,197,159,248,194,143,98,18,100,180,74,159,65,157,3,208,30,141,129,250,69,50,61,58,172,166,116,163,132,118,202,215,5,27,244,211,136,148,209,63,147,148,161,106,177,196,128,121,86,214,128,66,202,143,79,40,25,147,136,102,23,95,8,140,54,239,194,226,29,137,171,96,164,190,42,223,70,159,28,198,54,74,197,5,123,37,85,73,51,228,42,123,224,149,79,13,237,175,32,15,147,68,46,76,73,155,122,222,194,216,227,230,67,40,143,41,219,240,72,225,83,172,142,148,235,89,206,59,62,153,149,84,147,132,183,74,41,113,236,238,129,206,237,24,27,11,81,21,137,213,37,203,83,215,193,155,125,239,165,63,42,151,92,176,181,9,210,10,79,248,38,165,23,111,229,195,188,126,77,169,110,174,193,216,228,126,231,38,89,238,59,43,82,154,187,194,170,113,207,187,63,156,214,185,58,9,137,223,43,245,198,12,238,178,194,160,121,109,227,163,233,44,34,0,188,57,14,156,239,198,212,170,132,38,168,166,158,213,177,154,210,175,14,68,93,68,119,98,204,238,154,17,81,62,243,74,204,35,246,51,109,14,106,15,219,138,46,40,104,16,90,20,96,22,204,82,223,43,139,183,121,125,191,91,38,90,156,16,219,29,196,52,138,129,162,157,155,133,161,214,248,83,186,80,54,59,112,247,145,121,222,205,122,158,157,222,103,79,255,106,84,124,204,69,15,141,130,121,9,1,179,194,13,169,90,184,149,242,89,241,5,147,106,75,132,99,160,186,88,23,54,33,212,226,82,89,98,121,105,153,151,114,8,31,54,29,143,212,165,16,123,178,132,239,19,116,129,85,216,98,25,62,127,54,118,214,120,226,28,100,191,34,31,6,145,46,148,221,228,74,201,35,186,243,49,246,22,53,233,28,12,113,210,88,111,245,142,70,121,18,1,68,204,186,28,220,209,233,170,144,153,184,235,114,233,202,78,49,196,23,241,95,238,33,179,170,1,170,98,231,137,95,114,254,63,237,122,89,184,203,18,37,221,83,253,27,96,60,56,89,29,95,209,184,146,40,80,20,99,193,167,106,97,28,43,230,12,159,76,119,30,9,141,114,95,163,186,148,120,64,154,5,158,191,48,32,57,150,24,122,239,147,46,230,136,90,85,178,141,134,125,246,160,65,213,89,57,54,253,50,191,229,180,114,12,152,104,254,144,98,213,55,8,252,109,174,242,180,17,115,199,191,139,44,2,92,109,80,155,4,165,90,88,73,7,123,38,173,80,163,56,139,45,190,197,135,48,73,210,249,96,200,178,194,128,240,89,129,13,4,4,54,43,56,80,147,161,99,4,40,119,215,161,215,240,112,224,231,102,112,78,84,59,243,58,88,144,100,54,244,103,217,31,44,11,225,245,53,187,53,164,8,24,208,213,212,169,2,199,151,215,183,4,146,1,110,190,54,50,182,33,194,251,158,248,140,150,64,24,152,94,36,48,11,195,8,144,159,142,64,163,204,121,97,254,220,104,219,55,52,41,164,190,204,1,116,131,143,127,17,174,190,235,171,143,128,68,105,183,249,54,67,70,226,173,143,250,167,114,69,83,115,8,177,140,241,99,86,25,129,56,171,93,189,87,47,238,165,162,193,39,233,245,152,35,126,134,95,162,210,48,243,215,213,83,164,169,148,245,65,254,233,117,123,223,223,81,186,131,77,12,71,96,25,203,60,152,55,136,247,227,187,15,119,13,15,153,173,201,3,135,207,220,131,113,3,244,61,89,208,212,206,255,242,147,239,230,229,138,181,74,245,61,22,203,69,183,197,95,206,134,200,35,153,34,252,219,84,200,109,110,254,29,225,192,70,196,119,49,141,123,14,196,68,96,109,32,122,244,190,220,176,193,97,44,29,171,187,163,217,139,208,196,104,120,227,192,3,221,122,103,102,247,17,115,95,42,31,195,125,183,55,171,244,57,241,58,237,47,94,117,214,147,21,40,42,2,176,175,43,168,5,122,68,40,4,80,104,53,247,214,149,28,1,230,234,16,236,3,107,84,114,172,192,246,41,105,156,97,57,10,72,176,18,105,212,131,138,86,232,4,202,124,45,158,5,36,137,91,203,147,250,97,86,144,149,4,239,134,168,121,15,106,179,214,0,237,237,199,16,217,33,67,164,137,42,170,174,29,219,157,154,86,232,59,39,179,213,213,23,50,238,150,143,197,104,239,46,192,59,65,132,223,235,106,99,88,159,228,133,92,143,166,92,48,22,43,143,171,132,98,52,72,239,217,140,54,164,164,117,179,230,13,197,137,137,145,49,249,64,189,13,161,98,178,83,236,77,127,96,64,84,8,156,150,38,206,159,1,33,221,13,201,219,168,221,253,182,246,174,122,39,172,88,98,141,98,36,174,154,232,9,0,23,222,145,33,75,140,132,17,42,10,205,167,8,167,249,86,153,37,249,199,161,192,165,41,215,157,243,251,113,76,90,21,21,15,209,141,9,33,40,138,6,38,164,16,136,174,243,6,163,151,225,131,159,24,29,177,190,226,2,48,17,65,128,84,22,84,175,168,183,20,142,240,222,118,126,212,94,232,79,147,166,107,84,56,231,199,174,17,176,2,222,57,86,99,205,14,244,15,167,109,174,103,133,227,22,61,228,102,164,9,131,210,45,67,103,85,3,6,109,132,7,24,113,93,201,235,23,40,226,107,0,34,207,6,228,205,41,97,12,223,108,49,173,201,18,165,120,228,139,148,9,240,115,160,3,11,100,203,11,119,11,150,172,168,207,155,194,71,142,118,126,244,245,255,204,138,35,131,73,235,6,22,69,129,6,182,143,99,160,48,176,6,19,143,114,153,96,250,231,131,97,123,29,150,106,159,201,138,249,55,94,240,253,241,1,164,66,114,16,119,231,243,122,218,70,248,241,9,17,155,198,179,150,134,0,116,72,208,178,189,55,231,37,20,155,4,57,214,56,67,245,245,105,105,105,46,125,242,195,233,11,118,196,95,180,34,34,163,115,26,229,217,88,77,233,0,70,163,21,197,153,243,50,41,149,207,151,243,132,224,36,85,17,228,245,122,111,91,115,25,51,39,133,155,200,103,196,152,66,163,87,77,248,53,50,244,85,34,95,125,154,1,189,198,74,84,91,65,132,160,57,121,13,208,88,32,147,66,224,18,155,78,175,194,239,226,92,138,192,54,102,72,203,165,150,145,167,46,232,137,74,8,186,105,240,143,148,42,113,74,190,40,252,134,111,5,232,65,112,208,158,112,82,52,212,158,56,11,46,252,69,117,79,38,64,177,183,114,154,113,68,22,254,191,108,187,168,149,11,139,170,21,73,0,128,156,36,71,71,7,13,142,210,42,6,80,175,141,62,195,134,80,15,28,66,211,165,180,235,89,203,154,175,103,136,9,89,58,45,204,202,183,252,78,207,133,40,149,168,157,252,94,252,72,68,55,214,71,175,12,254,223,36,138,20,193,164,121,22,45,209,100,166,214,168,143,189,117,113,106,94,63,79,179,168,223,66,92,126,200,199,160,173,251,168,198,18,236,62,57,99,214,92,36,120,121,17,182,214,200,250,73,233,10,233,127,15,255,229,152,199,24,172,245,187,152,34,158,1,95,17,47,105,211,6,111,155,28,121,33,167,114,42,127,66,94,246,247,0,70,120,116,138,231,224,40,36,59,89,84,134,227,193,159,52,196,233,76,140,43,98,134,112,195,126,113,161,92,11,52,39,100,237,101,143,122,116,181,74,69,138,47,100,192,21,163,94,135,73,54,22,201,31,80,90,65,35,126,117,29,13,172,93,86,189,4,178,222,34,43,91,34,16,131,40,29,122,238,75,53,169,1,204,97,81,177,114,7,140,42,128,2,10,221,39,176,107,106,132,161,154,35,249,212,246,234,161,232,193,86,30,129,120,184,23,168,2,179,180,66,125,138,105,212,199,149,195,96,252,118,170,117,253,216,45,216,217,164,149,200,232,179,154,215,195,74,224,71,153,255,144,90,230,249,189,185,243,155,22,75,23,48,164,152,185,184,205,172,141,141,57,172,255,33,168,176,134,194,177,25,217,236,108,222,100,129,228,89,9,83,0,43,80,16,196,223,77,44,210,224,43,19,219,221,96,134,7,197,48,97,198,137,162,62,149,120,8,53,136,210,79,82,0,146,128,112,211,87,248,28,239,201,250,217,134,203,158,32,111,143,249,47,255,119,48,111,247,209,91,186,201,129,64,202,134,179,209,120,199,206,235,41,134,212,163,201,44,98,62,136,230,144,34,209,146,220,118,132,10,130,138,207,11,147,52,207,176,183,195,5,233,88,171,75,23,220,230,161,116,109,67,22,13,153,26,145,185,17,157,10,46,75,86,87,95,117,0,140,177,10,199,139,250,105,150,252,36,72,174,213,245,106,115,219,179,213,68,234,129,221,246,54,122,203,18,164,240,156,26,128,2,201,143,22,22,131,169,155,49,90,144,153,184,166,171,255,139,92,126,36,72,216,88,99,201,112,152,156,255,188,190,52,193,217,127,69,82,234,10,180,199,5,247,46,29,140,164,172,117,121,96,198,58,28,8,13,207,168,234,150,165,224,177,199,159,183,57,238,63,102,151,118,140,138,38,114,183,237,19,64,161,71,53,97,187,84,156,141,170,35,78,123,186,58,94,117,182,118,231,253,13,188,152,10,225,103,82,118,250,213,241,2,120,62,174,112,231,252,236,90,183,220,141,178,135,206,162,168,215,160,132,7,184,244,66,255,199,57,72,109,163,182,213,54,148,133,212,166,155,22,119,46,249,177,18,7,249,247,241,251,130,210,246,203,133,223,122,242,111,66,201,192,108,247,191,74,70,5,250,225,15,238,31,191,219,4,186,110,213,46,93,61,243,49,48,207,97,223,81,241,163,69,2,69,23,156,226,127,168,11,29,214,3,73,93,9,206,107,45,165,103,238,202,140,5,250,146,18,39,219,246,202,222,119,203,0,15,18,16,60,149,118,117,97,118,117,203,84,22,210,215,99,1,79,96,55,206] diff --git a/plugins/openvpn.py b/plugins/openvpn.py index 9eb90d2..7d02ab2 100644 --- a/plugins/openvpn.py +++ b/plugins/openvpn.py @@ -8,7 +8,7 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" - return ['-r', '--vpn','store_true',"Return VPN information about the subject (openvpn)"] + return ['-r', '--vpn','store_true','Return VPN information about the subject (openvpn)'] def startup(self) : for requirement in ['hosts','username','key'] : @@ -16,26 +16,26 @@ class ServiceDelegate(ServiceBase) : self.error.append('Missing required config option ' + requirement) return self.hosts = self.config['hosts'] - self.debug("Logging into OpenVPN servers...",1) - connections = [] + self.debug('Logging into OpenVPN servers...',1) + connections = {} for host in self.config['hosts'] : try : sshclient = paramiko.SSHClient() sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshclient.connect(host,22,username=self.config['username'],password=self.config['key']) - connections.append(sshclient) + connections.update({host:sshclient}) except Exception as exception : - self.error.append("Unable to ssh into " + host + ': ' + str(exception)) + self.error.append('Unable to ssh into ' + host + ': ' + str(exception)) self.connections = connections def shutdown(self) : - for connection in self.connections : + for connection in self.connections.values() : connection.close() def lookup(self,subject) : - search_command = "sudo -S cat /etc/openvpn/openvpn-*p.log | grep 'primary virtual IP for' | grep '" + subject + "' | tail -n 1" - for connection in self.connections : + search_command = 'sudo -S cat /var/log/openvpn/openvpn.log | grep \'primary virtual IP for\' | grep \'' + subject + '\' | tail -n 1' + for host,connection in self.connections.items() : try: stdin,stdout,stderr=connection.exec_command(search_command) stdin.write(self.config['key'] + '\n') @@ -45,17 +45,18 @@ class ServiceDelegate(ServiceBase) : self.debug('Retrieved line from ssh session: \n' + result[0],2) result = result[0] else : - result = "" - items = {'nat_address': r'.*\ ([0-9a-fA-F\.\:]*)$', 'source_address': r'.*/([0-9a-fA-F\.\:]*)\ .*', 'user_name': r'.*us=[0-9]*\ ([a-zA-Z0-9\.]*)/.*', 'timestamp': r'(.*)\ us=.*'} + result = '' + items = {'nat_address': r'.*\ ([0-9a-fA-F\.\:]*)$', 'source_address': r'.*/([0-9a-fA-F\.]*)\:.*', 'user_name': r'.*primary\ virtual\ IP\ for\ ([a-zA-Z0-9\.]*)/.*', 'timestamp': r'^([a-zA-Z]{3}\ +[0-9]{1,2}\ [0-9:]*)\ .*'} return_dictionary = {} for item in items.keys() : matches = re.match(items[item],result) if matches and len(matches.groups()) and matches[1] : return_dictionary.update({item: matches[1]}) - if return_dictionary is not {} : + if len(return_dictionary) > 0 : + return_dictionary.update({'host':host}) return return_dictionary else : return None except Exception as exception : - self.error.append("Unable to get results from ssh: " + str(exception)) + self.error.append('Unable to get results from ssh: ' + str(exception)) pass diff --git a/plugins/paloalto.py b/plugins/paloalto.py index a10d5ad..8e5ad08 100644 --- a/plugins/paloalto.py +++ b/plugins/paloalto.py @@ -4,8 +4,8 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" # [ ,,, ] - # Example return: [ '-n', '--net', 'store_true', "Return network information about the subject" ] - return ['-fw', '--rules', 'store_true', "Return Firewall rules relating to the subject"] + # Example return: [ '-n', '--net', 'store_true', 'Return network information about the subject' ] + return ['-fw', '--rules', 'store_true', 'Return Firewall rules relating to the subject'] def get_pa_auth_header(host,username,password) : """Given authentication information, return the authenticated header for use in REST requests to a Palo Alto device.""" diff --git a/plugins/shodan.py b/plugins/shodan.py index 3df236e..febed10 100644 --- a/plugins/shodan.py +++ b/plugins/shodan.py @@ -11,7 +11,7 @@ class ServiceDelegate(ServiceBase) : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" - return [ '-s', '--shodan', 'store_true', "Return Shodan information about the subject (dns)" ] + return [ '-s', '--shodan', 'store_true', 'Return Shodan information about the subject (dns)' ] def startup(self) : for requirement in ['keys'] : @@ -20,7 +20,7 @@ class ServiceDelegate(ServiceBase) : return keys = self.config['keys'] self._api_sessions = [shodan.Shodan(x) for x in keys] - self.debug("Searching Shodan for hosts...",1) + self.debug('Searching Shodan for hosts...',1) def lookup(self,subject) : @@ -31,7 +31,7 @@ class ServiceDelegate(ServiceBase) : clean = self._clean_newlines(host) return host except shodan.exception.APIError as e: - self.debug("Unable to search for " + subject + " on shodan",1) + self.debug('Unable to search for ' + subject + ' on shodan: ' + str(e),1) pass def _clean_newlines(self,structure) : diff --git a/servicebase.py b/servicebase.py index 0d5faf0..e59a917 100644 --- a/servicebase.py +++ b/servicebase.py @@ -35,7 +35,7 @@ class ServiceBase : def get_arguments(cls) : """Returns an array of information used to construct an argumentparser argument.""" # [ ,,, ] - # Example return: [ '-n', '--net', 'store_true', "Output network information about the subject" ] + # Example return: [ '-n', '--net', 'store_true', 'Output network information about the subject' ] return None def startup(self) :