More code cleanup

This commit is contained in:
Daniel Dayley 2020-05-26 12:26:01 -06:00
parent 89a643f218
commit 4f4b7f2bdc
10 changed files with 130 additions and 124 deletions

View File

@ -107,8 +107,10 @@ class IFXLookup():
"""Returns a map of plugins configured to use in the lookup.""" """Returns a map of plugins configured to use in the lookup."""
return self._delegate_map return self._delegate_map
def search_plugins(self,directory='/'.join(os.path.realpath(__file__).split('/')[:-1]) + '/' + 'plugins') : def search_plugins(self,directory=None) :
"""Searches a given directory for compatible plugins and returns a map of available plugin names and classes""" """Searches a given directory for compatible plugins and returns a map of available plugin names and classes"""
if not directory :
directory = '/'.join(os.path.realpath(__file__).split('/')[:-1]) + '/' + 'plugins'
directory = os.path.normpath(os.path.expanduser(os.path.expandvars(directory))) directory = os.path.normpath(os.path.expanduser(os.path.expandvars(directory)))
name_map = {} name_map = {}
candidates = {x.split('.')[0]:x for x in os.listdir(directory) if x.endswith('.py') and x != 'servicebase.py'} candidates = {x.split('.')[0]:x for x in os.listdir(directory) if x.endswith('.py') and x != 'servicebase.py'}
@ -126,18 +128,6 @@ class IFXLookup():
raise TypeError('argument \'config\' should be of type dict') raise TypeError('argument \'config\' should be of type dict')
self._config.update(config) self._config.update(config)
def load_config_from_file(self,config=DEFAULT_CONFIG) :
"""Loads a JSON or YAML file containing a configuration map for plugins. Used to configure several plugins at once."""
if config :
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))))
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))))
total_config = yaml.safe_load(file_descriptor)
self._config.update(total_config)
def dump_config(self) : def dump_config(self) :
"""Returns the current configuration state. This likely contains sensitive information such as API keys.""" """Returns the current configuration state. This likely contains sensitive information such as API keys."""
return self._config return self._config
@ -206,15 +196,19 @@ class IFXLookup():
report = {} report = {}
for subject in subjects : for subject in subjects :
report.update({subject:delegate.lookup(subject)}) report.update({subject:delegate.lookup(subject)})
if delegate.error != [] : if delegate._error != [] :
error_info.update({delegatename:delegate.error}) error_info.update({delegatename:delegate._error})
if delegate.warn != [] : if delegate._warn != [] :
warn_info.update({delegatename:delegate.warn}) warn_info.update({delegatename:delegate._warn})
report.update(error_info) report.update(error_info)
report.update(warn_info) report.update(warn_info)
if report and report != {}: if report and report != {}:
final_report.update({delegatename:report}) final_report.update({delegatename:report})
if len(error_info) > 0 :
final_report.update({'error':error_info})
if len(warn_info) > 0 :
final_report.update({'warning':warn_info})
# If caching is enabled prevent shutdown. Otherwise shutdown. # If caching is enabled prevent shutdown. Otherwise shutdown.
if not self._caching : if not self._caching :
self.__shutdown_plugins() self.__shutdown_plugins()

View File

@ -6,15 +6,15 @@ import xml.etree.ElementTree as ElementTree
class ServiceDelegate(ServiceBase) : class ServiceDelegate(ServiceBase) :
host = None _host = None
api_session = requests.session() _api_session = requests.session()
session_key = None _session_key = None
query_page_size = 200 _query_page_size = 200
clients_fields = ['sta_mac_address', 'client_ht_phy_type', 'openflow_state', 'client_ip_address', 'client_user_name', 'client_dev_type', 'client_ap_location', 'client_conn_port', 'client_conn_type', 'client_timestamp', 'client_role_name', 'client_active_uac', 'client_standby_uac', 'ap_cluster_name', 'client_health', 'total_moves', 'successful_moves', 'steer_capability', 'ssid', 'ap_name', 'channel', 'channel_str', 'channel_busy', 'tx_time', 'rx_time', 'channel_free', 'channel_interference', 'current_channel_utilization', 'radio_band', 'bssid', 'speed', 'max_negotiated_rate', 'noise_floor', 'radio_ht_phy_type', 'snr', 'total_data_frames', 'total_data_bytes', 'avg_data_rate', 'tx_avg_data_rate', 'rx_avg_data_rate', 'tx_frames_transmitted', 'tx_frames_dropped', 'tx_bytes_transmitted', 'tx_bytes_dropped', 'tx_time_transmitted', 'tx_time_dropped', 'tx_data_transmitted', 'tx_data_dropped', 'tx_data_retried', 'tx_data_transmitted_retried', 'tx_data_bytes_transmitted', 'tx_abs_data_bytes', 'tx_data_bytes_dropped', 'tx_time_data_transmitted', 'tx_time_data_dropped', 'tx_mgmt', 'rx_frames', 'rx_bytes', 'rx_data', 'rx_data_bytes', 'rx_abs_data_bytes', 'rx_data_retried', 'tx_data_frame_rate_dist', 'rx_data_frame_rate_dist', 'tx_data_bytes_rate_dist', 'rx_data_bytes_rate_dist', 'connection_type_classification', 'total_data_throughput', 'tx_data_throughput', 'rx_data_throughput', 'client_auth_type', 'client_auth_subtype', 'client_encrypt_type', 'client_fwd_mode'] _clients_fields = ['sta_mac_address', 'client_ht_phy_type', 'openflow_state', 'client_ip_address', 'client_user_name', 'client_dev_type', 'client_ap_location', 'client_conn_port', 'client_conn_type', 'client_timestamp', 'client_role_name', 'client_active_uac', 'client_standby_uac', 'ap_cluster_name', 'client_health', 'total_moves', 'successful_moves', 'steer_capability', 'ssid', 'ap_name', 'channel', 'channel_str', 'channel_busy', 'tx_time', 'rx_time', 'channel_free', 'channel_interference', 'current_channel_utilization', 'radio_band', 'bssid', 'speed', 'max_negotiated_rate', 'noise_floor', 'radio_ht_phy_type', 'snr', 'total_data_frames', 'total_data_bytes', 'avg_data_rate', 'tx_avg_data_rate', 'rx_avg_data_rate', 'tx_frames_transmitted', 'tx_frames_dropped', 'tx_bytes_transmitted', 'tx_bytes_dropped', 'tx_time_transmitted', 'tx_time_dropped', 'tx_data_transmitted', 'tx_data_dropped', 'tx_data_retried', 'tx_data_transmitted_retried', 'tx_data_bytes_transmitted', 'tx_abs_data_bytes', 'tx_data_bytes_dropped', 'tx_time_data_transmitted', 'tx_time_data_dropped', 'tx_mgmt', 'rx_frames', 'rx_bytes', 'rx_data', 'rx_data_bytes', 'rx_abs_data_bytes', 'rx_data_retried', 'tx_data_frame_rate_dist', 'rx_data_frame_rate_dist', 'tx_data_bytes_rate_dist', 'rx_data_bytes_rate_dist', 'connection_type_classification', 'total_data_throughput', 'tx_data_throughput', 'rx_data_throughput', 'client_auth_type', 'client_auth_subtype', 'client_encrypt_type', 'client_fwd_mode']
aps_fields = ['mon_ap', 'mon_bssid', 'mon_radio_phy_type', 'mon_ssid', 'mon_radio_band', 'mon_ap_current_channel', 'mon_ht_sec_channel', 'mon_sta_count', 'mon_ap_classification', 'mon_ap_match_conf_level', 'mon_ap_encr', 'mon_ap_encr_auth', 'mon_ap_encr_cipher', 'mon_ap_is_dos', 'mon_ap_type', 'mon_ap_status', 'mon_is_ibss', 'mon_ap_create_time', 'mon_ap_match_type', 'mon_ap_match_method', 'mon_ap_match_name', 'mon_ap_match_time', 'wms_event_count'] _aps_fields = ['mon_ap', 'mon_bssid', 'mon_radio_phy_type', 'mon_ssid', 'mon_radio_band', 'mon_ap_current_channel', 'mon_ht_sec_channel', 'mon_sta_count', 'mon_ap_classification', 'mon_ap_match_conf_level', 'mon_ap_encr', 'mon_ap_encr_auth', 'mon_ap_encr_cipher', 'mon_ap_is_dos', 'mon_ap_type', 'mon_ap_status', 'mon_is_ibss', 'mon_ap_create_time', 'mon_ap_match_type', 'mon_ap_match_method', 'mon_ap_match_name', 'mon_ap_match_time', 'wms_event_count']
justip_fields = ['client_ip_address'] _justip_fields = ['client_ip_address']
aruba_hosts = [] _aruba_hosts = []
aruba_basestations = [] _aruba_basestations = []
def get_arguments(cls) : def get_arguments(cls) :
"""Returns an array of information used to construct an argumentparser argument.""" """Returns an array of information used to construct an argumentparser argument."""
@ -22,11 +22,11 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
for requirement in ['host','username','key'] : for requirement in ['host','username','key'] :
if requirement not in self.config or (requirement in self.config and (self.config[requirement] is '' or type(self.config[requirement]) is not str)): if requirement not in self._config or (requirement in self._config and (self._config[requirement] is '' or type(self._config[requirement]) is not str)):
self.error.append('Missing required config option ' + requirement) self._error.append('Missing required config option ' + requirement)
return return
self.host = self.config['host'] self._host = self._config['host']
self.start_session(self.config['host'],self.config['username'],self.config['key']) self.start_session(self._config['host'],self._config['username'],self._config['key'])
clientsquery = 'backend-observer-sta-19' clientsquery = 'backend-observer-sta-19'
clientssortfield = 'client_user_name' clientssortfield = 'client_user_name'
clientsfilter = 'client_conn_type not_equals 0' clientsfilter = 'client_conn_type not_equals 0'
@ -36,9 +36,9 @@ class ServiceDelegate(ServiceBase) :
apsfilter = 'mon_ap_status equals 1' apsfilter = 'mon_ap_status equals 1'
apsdevicetype = 'mon_bssid' 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._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._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) : def lookup(self,subject) :
@ -50,11 +50,11 @@ class ServiceDelegate(ServiceBase) :
# By IP # By IP
if 'dns' in self.hints and subject in self.hints['dns'] and self.hints['dns'][subject]['addresses'] : if 'dns' in self.hints and subject in self.hints['dns'] and self.hints['dns'][subject]['addresses'] :
for ip in self.hints['dns'][subject]['addresses'] : for ip in self.hints['dns'][subject]['addresses'] :
for entry in self.aruba_basestations : for entry in self._aruba_basestations :
if ip in entry.values() : if ip in entry.values() :
return entry return entry
# By value # By value
for entry in self.aruba_basestations : for entry in self._aruba_basestations :
lowercase_values = [x.lower() for x in entry.values() if type(x) is str] lowercase_values = [x.lower() for x in entry.values() if type(x) is str]
all_values = lowercase_values + [x for x in entry.values() if type(x) is not str] all_values = lowercase_values + [x for x in entry.values() if type(x) is not str]
for value in all_values : for value in all_values :
@ -64,11 +64,11 @@ class ServiceDelegate(ServiceBase) :
# By IP # By IP
if 'dns' in self.hints and subject in self.hints['dns'] and self.hints['dns'][subject]['addresses'] : if 'dns' in self.hints and subject in self.hints['dns'] and self.hints['dns'][subject]['addresses'] :
for ip in self.hints['dns'][subject]['addresses'] : for ip in self.hints['dns'][subject]['addresses'] :
for entry in self.aruba_hosts : for entry in self._aruba_hosts :
if ip in entry.values() : if ip in entry.values() :
return entry return entry
# By value # By value
for entry in self.aruba_hosts : for entry in self._aruba_hosts :
lowercase_values = [x.lower() for x in entry.values() if type(x) is str] lowercase_values = [x.lower() for x in entry.values() if type(x) is str]
all_values = lowercase_values + [x for x in entry.values() if type(x) is not str] all_values = lowercase_values + [x for x in entry.values() if type(x) is not str]
for value in all_values : for value in all_values :
@ -80,9 +80,9 @@ class ServiceDelegate(ServiceBase) :
def start_session(self,host,username,key) : def start_session(self,host,username,key) :
headers = { 'Content-Type': 'application/x-www-form-urlencoded' } headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
data = 'opcode=login&uid=' + username + '&passwd=' + key data = 'opcode=login&uid=' + username + '&passwd=' + key
self.api_session.post('https://' + host + '/screens/wms/wms.login',verify=False,headers=headers,data=data) 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() : if 'SESSION' in self._api_session.cookies.get_dict() :
self.session_key = self.api_session.cookies.get_dict()['SESSION'] self._session_key = self._api_session.cookies.get_dict()['SESSION']
def perform_list_query(self,queryname,columnlist,sortfield,queryfilter,devicetype) : 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"""
@ -128,9 +128,9 @@ class ServiceDelegate(ServiceBase) :
allitems = [] allitems = []
while not finished : while not finished :
start_row.text = str(nextstart) start_row.text = str(nextstart)
num_rows.text = str(self.query_page_size) num_rows.text = str(self._query_page_size)
datapayload = ''.join(['query=',tostring(aruba_queries).decode(),'&UIDARUBA=',self.session_key]) 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) 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) self.debug('Got a page of results from Aruba host...',3)
if page.status_code == 100 or page.status_code == 200 : if page.status_code == 100 or page.status_code == 200 :
pagecontents = ElementTree.fromstring(page.text) pagecontents = ElementTree.fromstring(page.text)
@ -151,7 +151,7 @@ class ServiceDelegate(ServiceBase) :
finished = True finished = True
if page.status_code != 100 and page.status_code !=200 : if page.status_code != 100 and page.status_code !=200 :
finished = True finished = True
nextstart = nextstart + self.query_page_size nextstart = nextstart + self._query_page_size
else : else :
finished = True finished = True
self.debug('Retrieved ' + str((len(allitems))) + ' results from query',2) self.debug('Retrieved ' + str((len(allitems))) + ' results from query',2)

View File

@ -6,42 +6,42 @@ import json
class ServiceDelegate(ServiceBase) : class ServiceDelegate(ServiceBase) :
current_auth_header = None current_auth_header = None
return_payload = {} _return_payload = {}
host = None _host = None
def get_arguments(cls) : 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) : def startup(self) :
for requirement in ['host','username','key'] : for requirement in ['host','username','key'] :
if requirement not in self.config or (requirement in self.config and (self.config[requirement] is '' or type(self.config[requirement]) is not str)): if requirement not in self._config or (requirement in self._config and (self._config[requirement] is '' or type(self._config[requirement]) is not str)):
self.error.append('Missing required config option ' + requirement) self._error.append('Missing required config option ' + requirement)
return return
self.host = self.config['host'] self._host = self._config['host']
self.current_auth_header = self.get_bc_auth_header(self.config['host'],self.config['username'],self.config['key']) 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) : def lookup(self,subject) :
self.return_payload = {} self._return_payload = {}
if self.current_auth_header : if self._current_auth_header :
object = self.search_bc_object(subject) object = self.search_bc_object(subject)
if object : if object :
self.return_payload.update({'object':object}) self._return_payload.update({'object':object})
parent = self.search_bc_parent_object(subject) parent = self.search_bc_parent_object(subject)
if parent : if parent :
self.return_payload.update({'parent':parent}) self._return_payload.update({'parent':parent})
if len(self.return_payload) > 0 : if len(self._return_payload) > 0 :
return self.return_payload return self._return_payload
else : else :
return None return None
else : else :
return None return None
def shutdown(self) : def shutdown(self) :
if self.host and self.current_auth_header : if self._host and self._current_auth_header :
logout = requests.get('https://' + self.host + '/Services/REST/v1/logout',headers=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.\"') : if not logout.text.endswith('successfully logged out.\"') :
self.error.append('Unable to log out of BlueCat API session') self._error.append('Unable to log out of BlueCat API session')
def get_bc_auth_header(self,host,username,password) : def get_bc_auth_header(self,host,username,password) :
@ -54,13 +54,13 @@ class ServiceDelegate(ServiceBase) :
def search_bc_object(self,subject) : def search_bc_object(self,subject) :
"""Searches BC for the subject.""" """Searches BC for the subject."""
# Search by IP # 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) return self.clean_response(response)
def search_bc_parent_object(self,subject) : def search_bc_parent_object(self,subject) :
"""Search for and return information about the objects parent, if any""" """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'] : 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) return self.clean_response(response)
# Make a guess that it belongs to a static net that hasn't been put in bluecat # Make a guess that it belongs to a static net that hasn't been put in bluecat
elif subject != '' : elif subject != '' :
@ -68,7 +68,7 @@ class ServiceDelegate(ServiceBase) :
try : try :
ip = ipaddress.IPv4Network(subject + net,strict=False) ip = ipaddress.IPv4Network(subject + net,strict=False)
network = str(ip.network_address) 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('[]') : if not response.text.startswith('[]') :
return self.clean_response(response) return self.clean_response(response)
except: except:

View File

@ -12,8 +12,8 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
self.resolver = dns.resolver.Resolver() self.resolver = dns.resolver.Resolver()
if 'resolver' in self.config : if 'resolver' in self._config :
self.resolver.nameservers.append(self.config['resolver']) self.resolver.nameservers.append(self._config['resolver'])
def lookup(self,subject) : def lookup(self,subject) :
@ -29,7 +29,7 @@ class ServiceDelegate(ServiceBase) :
subjecttuple = socket.gethostbyname_ex(subject) subjecttuple = socket.gethostbyname_ex(subject)
except socket.gaierror : except socket.gaierror :
# Not a valid host or IP # Not a valid host or IP
self.error.append('Unable to resolve ' + subject) self._error.append('Unable to resolve ' + subject)
subjecttuple = [subject,[],['']] subjecttuple = [subject,[],['']]
# Can't make IPv4 out of it # Can't make IPv4 out of it
except socket.gaierror : except socket.gaierror :

View File

@ -8,8 +8,8 @@ urllib3.disable_warnings()
class ServiceDelegate(ServiceBase) : class ServiceDelegate(ServiceBase) :
return_payload = {} _return_payload = {}
hosts = None _hosts = None
_partition = 'Common' _partition = 'Common'
def get_arguments(cls) : def get_arguments(cls) :
@ -17,28 +17,28 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
for requirement in ['hosts','username','key'] : for requirement in ['hosts','username','key'] :
if requirement not in self.config or (requirement in self.config and self.config[requirement] is ''): if requirement not in self._config or (requirement in self._config and self._config[requirement] is ''):
self.error.append('Missing required config option ' + requirement) self._error.append('Missing required config option ' + requirement)
return return
self.hosts = self.config['hosts'] 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) : def lookup(self,subject) :
self.return_payload = {} self._return_payload = {}
logincandidates = self.choose_host(subject) logincandidates = self.choose_host(subject)
if logincandidates == {} : if logincandidates == {} :
# Idk what to do here, do we give up or do we log in to all of them? # 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)) self._error.append('Unable to find an LB to log into to check host ' + str(subject))
return None return None
for host in logincandidates.keys() : for host in logincandidates.keys() :
auth_header = self.get_iq_auth_header(host,self.config['username'],self.config['key']) auth_header = self.get_iq_auth_header(host,self._config['username'],self._config['key'])
if not auth_header : if not auth_header :
self.error.append('Unable to log in to ' + host) self._error.append('Unable to log in to ' + host)
continue continue
# Get all VIPs # Get all VIPs
if 'vip' not in self.return_payload : if 'vip' not in self._return_payload :
vips = self.get_vip(host,auth_header); vips = self.get_vip(host,auth_header);
# If it's a VIP, return it and the host and let's be done # If it's a VIP, return it and the host and let's be done
if vips : if vips :
@ -47,11 +47,11 @@ class ServiceDelegate(ServiceBase) :
all_vips = [ x['destination'] for x in vips ] all_vips = [ x['destination'] for x in vips ]
if len(vip_match) > 0 : if len(vip_match) > 0 :
selected_vip = vip_match[0] selected_vip = vip_match[0]
self.return_payload.update({'vip': selected_vip}) self._return_payload.update({'vip': selected_vip})
pool_name = selected_vip['pool'].split('/' + self._partition + '/')[1] pool_name = selected_vip['pool'].split('/' + self._partition + '/')[1]
pool_info = self.get_pool(host,auth_header,pool_name) pool_info = self.get_pool(host,auth_header,pool_name)
if pool_info : if pool_info :
self.return_payload.update(pool_info) self._return_payload.update(pool_info)
break break
else : 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)
@ -62,9 +62,9 @@ class ServiceDelegate(ServiceBase) :
# Check if address is in the pool. If it is, return the node, pool, vip, and host. # Check if address is in the pool. If it is, return the node, pool, vip, and host.
# Naw, I'll just give up. # Naw, I'll just give up.
self.debug('Unable to get VIPs from ' + host,2) self.debug('Unable to get VIPs from ' + host,2)
if len(self.return_payload) is 0 : if len(self._return_payload) is 0 :
self.return_payload = None self._return_payload = None
return self.return_payload return self._return_payload
def shutdown(self) : def shutdown(self) :
return return
@ -127,9 +127,9 @@ class ServiceDelegate(ServiceBase) :
else : else :
potentialdc = None potentialdc = None
if potentialdc : if potentialdc :
for host in self.hosts.keys() : for host in self._hosts.keys() :
if potentialdc.lower() in host.lower() : if potentialdc.lower() in host.lower() :
hosts.update({host:self.hosts[host]}) hosts.update({host:self._hosts[host]})
if hosts != {} : if hosts != {} :
return 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)
@ -139,9 +139,9 @@ class ServiceDelegate(ServiceBase) :
potentialdc = self.hints['bluecat'][subject]['object']['locationCode'].split(' ')[-1] potentialdc = self.hints['bluecat'][subject]['object']['locationCode'].split(' ')[-1]
elif 'parent' in self.hints['bluecat'][subject] and 'name' in self.hints['bluecat'][subject]['parent'] : elif 'parent' in self.hints['bluecat'][subject] and 'name' in self.hints['bluecat'][subject]['parent'] :
potentialdc = self.hints['bluecat'][subject]['parent']['name'].split(' ')[0] potentialdc = self.hints['bluecat'][subject]['parent']['name'].split(' ')[0]
for host in self.hosts.keys() : for host in self._hosts.keys() :
if potentialdc.lower() in host.lower() : if potentialdc.lower() in host.lower() :
hosts.update({host:self.hosts[host]}) 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
return hosts return hosts

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,11 @@
from servicebase import ServiceBase from servicebase import ServiceBase
import paramiko import paramiko
import datetime
import re import re
class ServiceDelegate(ServiceBase) : class ServiceDelegate(ServiceBase) :
connections = None _connections = None
def get_arguments(cls) : def get_arguments(cls) :
"""Returns an array of information used to construct an argumentparser argument.""" """Returns an array of information used to construct an argumentparser argument."""
@ -12,37 +13,38 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
for requirement in ['hosts','username','key'] : for requirement in ['hosts','username','key'] :
if requirement not in self.config or (requirement in self.config and self.config[requirement] is ''): if requirement not in self._config or (requirement in self._config and self._config[requirement] is ''):
self.error.append('Missing required config option ' + requirement) self._error.append('Missing required config option ' + requirement)
return rself._error
self.hosts = self.config['hosts'] self.hosts = self._config['hosts']
self.debug('Logging into OpenVPN servers...',1) self.debug('Logging into OpenVPN servers...',1)
connections = {} connections = {}
for host in self.config['hosts'] : for host in self._config['hosts'] :
try : try :
sshclient = paramiko.SSHClient() sshclient = paramiko.SSHClient()
sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sshclient.connect(host,22,username=self.config['username'],password=self.config['key']) sshclient.connect(host,22,username=self._config['username'],password=self._config['key'])
connections.update({host:sshclient}) connections.update({host:sshclient})
except Exception as exception : 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 self._connections = connections
def shutdown(self) : def shutdown(self) :
for connection in self.connections.values() : for connection in self._connections.values() :
connection.close() connection.close()
def lookup(self,subject) : def lookup(self,subject) :
search_command = 'sudo -S cat /var/log/openvpn/openvpn.log | grep \'primary virtual IP for\' | grep \'' + subject + '\' | tail -n 1' 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() : final_dictionary = {}
for host,connection in self._connections.items() :
try: try:
stdin,stdout,stderr=connection.exec_command(search_command) stdin,stdout,stderr=connection.exec_command(search_command)
stdin.write(self.config['key'] + '\n') stdin.write(self._config['key'] + '\n')
stdin.flush() stdin.flush()
result = stdout.readlines() result = stdout.readlines()
if len(result) > 0 : if len(result) > 0 :
self.debug('Retrieved line from ssh session: \n' + result[0],2) self.debug('Retrieved line from ssh session: \n' + result[0].strip(),2)
result = result[0] result = result[0]
else : else :
result = '' result = ''
@ -54,9 +56,23 @@ class ServiceDelegate(ServiceBase) :
return_dictionary.update({item: matches[1]}) return_dictionary.update({item: matches[1]})
if len(return_dictionary) > 0 : if len(return_dictionary) > 0 :
return_dictionary.update({'host':host}) return_dictionary.update({'host':host})
return return_dictionary
epoch = None
if 'timestamp' in final_dictionary.keys() and 'timestamp' in return_dictionary.keys() :
epoch = int(datetime.datetime.strptime(return_dictionary['timestamp'] + ' ' + str(datetime.datetime.now().year), '%b %d %H:%M:%S %Y').strftime('%s'))
if len(return_dictionary) > 0 :
if epoch :
if epoch > int(datetime.datetime.strptime(final_dictionary['timestamp'] + ' ' + str(datetime.datetime.now().year), '%b %d %H:%M:%S %Y').strftime('%s')) :
final_dictionary = {}
final_dictionary.update(return_dictionary)
else :
final_dictionary = return_dictionary
else : else :
return None self.debug('No results for ' + subject + ' on host ' + host,2)
except Exception as exception : except Exception as exception :
self.error.append('Unable to get results from ssh: ' + str(exception)) raise exception
pass self._error.append('Unable to get results from ssh: ' + str(exception))
if len(final_dictionary) > 0 :
return final_dictionary
else :
return None

View File

@ -15,10 +15,10 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
for requirement in ['keys'] : for requirement in ['keys'] :
if requirement not in self.config or (requirement in self.config and self.config[requirement] is ''): if requirement not in self._config or (requirement in self._config and self._config[requirement] is ''):
self.error.append('Missing required config option ' + requirement) self._error.append('Missing required config option ' + requirement)
return return
keys = self.config['keys'] keys = self._config['keys']
self._api_sessions = [shodan.Shodan(x) for x in 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)

View File

@ -10,14 +10,12 @@ class ServiceDelegate(ServiceBase) :
def startup(self) : def startup(self) :
self.resolver = dns.resolver.Resolver() self.resolver = dns.resolver.Resolver()
if 'resolver' in self.config : if 'resolver' in self._config :
self.resolver.nameservers.append(self.config['resolver']) self.resolver.nameservers.append(self._config['resolver'])
def lookup(self,subject) : def lookup(self,subject) :
# Note : hostname lookups always use system resolver. # Note : hostname lookups always use system resolver.
# TODO: Make host lookups use the config-sepcified resolver.
try : try :
subjecttuple = socket.gethostbyname_ex(subject) subjecttuple = socket.gethostbyname_ex(subject)
# Can't make an IP of the subject # Can't make an IP of the subject
@ -27,11 +25,11 @@ class ServiceDelegate(ServiceBase) :
subjecttuple = socket.gethostbyname_ex(subject) subjecttuple = socket.gethostbyname_ex(subject)
except socket.gaierror : except socket.gaierror :
# Not a valid host or IP # Not a valid host or IP
self.error.append("Unable to resolve " + subject) self._error.append("Unable to resolve " + subject)
subjecttuple = [subject,[],['']] subjecttuple = [subject,[],['']]
# Can't make IPv4 out of it # Can't make IPv4 out of it
except socket.gaierror : except socket.gaierror :
self.error.append("Unable to resolve " + subject) self._error.append("Unable to resolve " + subject)
subjecttuple = [subject,[],['']] subjecttuple = [subject,[],['']]
# Get additional records # Get additional records
return_dict = {} return_dict = {}

View File

@ -1,22 +1,20 @@
import sys import sys
class ServiceBase : class ServiceBase :
config = {} _config = {}
namespace = {}
data = {}
error = [] error = []
warn = [] warn = []
_status = "Ready" _status = "Ready"
def __init__(self,hints={},config={}): def __init__(self,hints={},config={}):
self.config = config self._config = config
self.error = [] self._error = []
self.warn = [] self._warn = []
self.hints = hints self.hints = hints
pass pass
def _set_config(self,config) : def _set_config(self,config) :
"""Allows for post-initialization configuration""" """Allows for post-initialization configuration"""
self.config = config self._config = config
def _set_hints(self,hints) : def _set_hints(self,hints) :
"""Allows for post-initialization configuration of hint data""" """Allows for post-initialization configuration of hint data"""
@ -28,7 +26,7 @@ class ServiceBase :
def debug(self,message,verbosity_level) : def debug(self,message,verbosity_level) :
"""Prints the submitted message if the environment's verbosity level matches or is surpassed by the submitted level.""" """Prints the submitted message if the environment's verbosity level matches or is surpassed by the submitted level."""
if self.config['_namespace']['debug'] and self.config['_namespace']['debug'] >= verbosity_level : if self._config['_namespace']['debug'] and self._config['_namespace']['debug'] >= verbosity_level :
print(message,file=sys.stderr) print(message,file=sys.stderr)
@classmethod @classmethod