def __init__(self, device, parser, ssh_timeout=DEFAULT_TIMEOUT, ssh_max_bytes=DEFAULT_MAX_BYTES, ssh_max_attempts=DEFAULT_MAX_ATTEMPTS): self.network_parser = None self.device = device self.hostname = device.system_name self.ssh_timeout = ssh_timeout self.ssh_max_bytes = ssh_max_bytes self.ssh_max_attempts = ssh_max_attempts self._auth_manager = AuthManager(parser)
class AuthManagerTest(unittest.TestCase): mgr = AuthManager(None, MockUsersManager()) def test_hash_password(self): pwd = 'Ezekiel2517' expected_hash = 'C27E5A5B42AD5F7C1204E36DE2C569C37496FC41213960A147BE53B1DF2867FC' actual_hash = self.mgr.hash_password(pwd) assert expected_hash == actual_hash def test_compare_hashes(self): hash1 = 'C27E5A5B42AD5F7C1204E36DE2C569C37496FC41213960A147BE53B1DF2867FC' hash2 = 'C27E5A5B42AD5F7C1204E36DE2C569C37496FC41213960A147BE53B1DF2867FC' assert self.mgr.compare_hashes(hash1, hash2) is True assert self.mgr.compare_hashes(hash1 + '1', hash2) is False def test_check_auth(self): username = '******' password = '******' assert self.mgr.check_auth(username, password) is True assert self.mgr.check_auth(username, password + '1') is False assert self.mgr.check_auth(username + '1', password) is False def test_check_token(self): token = 'aGFycnk6RXpla2llbDI1MTc=' assert self.mgr.check_token(token) is True token = 'ZmFrZTpwYXNzd29yZA==' assert self.mgr.check_token(token) is False def test_generate_token(self): username = '******' password = '******' test_token = self.mgr.generate_token(username, password) real_token = 'aGFycnk6RXpla2llbDI1MTc=' print(test_token) assert test_token == real_token
if __name__ == '__main__': if len(sys.argv) != 4: print "$ stream_tweets_main [destinationFolder] [credentials] [tagList]" quit() try: DATA_DIRECTORY = os.path.join(sys.argv[1]) LOG_FILE_DIRECTORY = os.path.join(sys.argv[1], 'log') CREDENTIALS_FILE_PATH = os.path.join(sys.argv[2]) TAG_FILE_PATH = os.path.join(sys.argv[3]) if not os.path.exists(DATA_DIRECTORY): os.makedirs(DATA_DIRECTORY) if not os.path.exists(LOG_FILE_DIRECTORY): os.makedirs(LOG_FILE_DIRECTORY) auth_manager = AuthManager(CREDENTIALS_FILE_PATH) num_handlers = len(auth_manager.auth_handlers) tag_manager = TagManager(TAG_FILE_PATH, num_handlers) logger = Logger(LOG_FILE_DIRECTORY) for i in xrange(num_handlers): listener = CustomListener(i, DATA_DIRECTORY, sys.argv[0], logger) stream = CustomStream(listener, auth_manager.auth_handlers[i], tag_manager.distributed_tag_list[i]) stream.stream(async=True) except IOError: print '{0} stopped running...'.format(sys.argv[0]) except: logger.log(500, 0, 'Some run-time error has occurred. Restarting...') os.system('python {0} {1} {2} {3}'.format(sys.argv[0], sys.argv[1], sys.argv[2], sys.argv[3]))
def main(args): CREDENTIALS_FILE_PATH = os.path.join(args.c) auth_manager = AuthManager(CREDENTIALS_FILE_PATH) TweetsCollector(args.i, args.o, auth_manager)
class NetworkExplorer(object): """ This class will communicate with its assigned device in order to get the device's networking information such as its LLDP neighbors. """ def __init__(self, device, parser, ssh_timeout=DEFAULT_TIMEOUT, ssh_max_bytes=DEFAULT_MAX_BYTES, ssh_max_attempts=DEFAULT_MAX_ATTEMPTS): self.network_parser = None self.device = device self.hostname = device.system_name self.ssh_timeout = ssh_timeout self.ssh_max_bytes = ssh_max_bytes self.ssh_max_attempts = ssh_max_attempts self._auth_manager = AuthManager(parser) def explore_lldp(self, explored_devices, queue): """ Explores a device using the LLDP protocol in order to add its valid neighbors in the queue. :param explored_devices: The dict of the devices already explored :type explored_devices: {str : Device} :param queue: The queue of the next devices to explore :type queue: Queue() """ try: self._open_ssh_connection() except NoAuthRequested as e: logging.info("[%s] No auth requested", self.hostname) self.device.status = DeviceStatus.NO_AUTH_REQUESTED return except paramiko.AuthenticationException as pae: logging.error("[%s] Authentication failed: %s", self.hostname, pae) self.device.status = DeviceStatus.AUTH_FAILED return except Exception as e: logging.error("[%s] Could not open SSH connection: %s", self.hostname, e) self.device.status = DeviceStatus.UNREACHABLE return finally: if self.device.mac_address: explored_devices[self.device.mac_address] = self.device # Determining the type of the current device from the switch banner banner = self._receive_ssh_output() self.network_parser = NetworkOutputParser.get_parser_type(banner) if self.network_parser is None: logging.warning( "[%s] Unsupported device type. Prompt was: %s", self.hostname, banner) return # Preparing the switch, such as removing pagination self._prepare_switch() # Building current device's informations if missing if self.device is None or self.device.mac_address is None: local_report = self._get_lldp_local_report() try: self.device = self.network_parser.\ parse_device_from_lldp_local_info(local_report) if not self.device.mac_address: raise ValueError() except Exception as e: logging.error( "[%s] Unable to parse lldp local report using %s: %s", self.hostname, self.network_parser.__class__.__name__, e) return neighbors = self._build_lldp_neighbors() self._assign_vlans_to_interfaces() self._assign_trunks_to_device() self._assign_vms_to_device() self._close_ssh_connection() explored_devices[self.device.mac_address] = self.device for neighbor in neighbors: valid = neighbor.is_valid_lldp_device() explored = neighbor.mac_address in explored_devices if valid and not explored: explored_devices[neighbor.mac_address] = neighbor queue.put(neighbor) def _build_lldp_neighbors(self): """ Obtain the list of all lldp neighbors """ neighbors_result = self._get_lldp_neighbors() # With lldpd on Linux, the lldp summary already contains all details if self.network_parser.lldp_neighbors_detail_cmd is None: neighbors = self.network_parser\ .parse_devices_from_lldp_remote_info(self.device, neighbors_result) return neighbors self.device.interfaces = self.network_parser\ .parse_interfaces_from_lldp_remote_info(neighbors_result) if len(self.device.interfaces) == 0: neighbors = [] return neighbors lldp_neighbors_details = [] for interface in self.device.interfaces.values(): if interface.is_valid_lldp_interface(): port = interface.local_port detail = self._get_lldp_neighbor_detail(port) lldp_neighbors_details.append(detail) neighbors = self.network_parser.parse_devices_from_lldp_remote_info( self.device, lldp_neighbors_details) return neighbors def _assign_vlans_to_interfaces(self): """ Parse the vlans result and assign them to the interfaces. """ vlans_result = self._get_vlans() if vlans_result is None: return vlans = self.network_parser.parse_vlans(vlans_result) # Some devices do not need to parse vlans from the global info and # can assign the vlans directly to interfaces from the first result if len(vlans) == 0: self.network_parser.associate_vlans_to_interfaces( self.device.interfaces, vlans_result) # Other devices need to get specific information from each vlan before # assigning it one by one to the interfaces for vlan in vlans.values(): detail_str = self.network_parser.get_vlan_detail_str(vlan) specific_result = self._get_vlan_detail(detail_str) self.network_parser.associate_vlan_to_interfaces( self.device.interfaces, vlan, specific_result) def _assign_trunks_to_device(self): trunks_result = self._get_trunks() if trunks_result is None: return trunks = self.network_parser.parse_trunks(self.device.interfaces, trunks_result) self.device.trunks = trunks def _assign_vms_to_device(self): vms_result = self._get_virtual_machines() if vms_result is None: return vms = self.network_parser.parse_vms_list(vms_result) self.device.virtual_machines = vms def _get_lldp_local_report(self): command = self.network_parser.lldp_local_cmd return self._send_ssh_command(command) def _get_lldp_neighbors(self): command = self.network_parser.lldp_neighbors_cmd return self._send_ssh_command(command) def _get_lldp_neighbor_detail(self, port): command = self.network_parser.lldp_neighbors_detail_cmd.format(port) return self._send_ssh_command(command) def _get_trunks(self): command = self.network_parser.trunks_list_cmd return self._send_ssh_command(command) def _get_vlans(self): command = self.network_parser.vlans_global_cmd return self._send_ssh_command(command) def _get_vlan_detail(self, vlan_id): command = self.network_parser.vlans_specific_cmd.format(vlan_id) return self._send_ssh_command(command) def _get_virtual_machines(self): command = self.network_parser.vms_list_cmd return self._send_ssh_command(command) def _open_ssh_connection(self): """ Opens a SSH connection with the device """ kwargs = self._auth_manager.get_params(self.hostname, self.device.type) kwargs.update({ "hostname": self.hostname, "look_for_keys": False, "allow_agent": False, "timeout": self.ssh_timeout}) nb_attempts = 0 while nb_attempts <= 3: try: self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(**kwargs) except paramiko.AuthenticationException as pae: raise # Do not retry if authentication failed except Exception as e: nb_attempts += 1 else: break self.shell = self.ssh.invoke_shell() self.shell.set_combine_stderr(True) logging.info("[%s] SSH connection established", self.hostname) time.sleep(1) def _close_ssh_connection(self): """ Closes the connection with the current device. That connection must have been opened beforehand. """ try: self.shell.close() self.ssh.close() logging.debug("[%s] SSH connection closed", self.hostname) except Exception as e: logging.error("[%s] Could not close ssh connection: %s", self.hostname, e) def _send_ssh_command(self, command): """ Sends a command to the device in order to retrieve the output data. :param command: The command to execute (must end by a '\\n') :type command: str :return: Returns the (clean) result from the command's output :rtype: str """ if command is None: return None try: logging.debug("[%s] Sending: %s", self.hostname, repr(command)) self.shell.send(command) receive_buffer = "" wait_string = self.network_parser.wait_string length_when_mark_detected = 0 empty_buffer_count = 0 while True: temp_buffer = self._receive_ssh_output() receive_buffer += temp_buffer if not temp_buffer: empty_buffer_count += 1 else: empty_buffer_count = 0 if wait_string in receive_buffer[length_when_mark_detected:]: length_when_mark_detected = len(receive_buffer) if length_when_mark_detected > 0 and empty_buffer_count == 3: break time.sleep(0.1) logging.debug("[%s] Got response (len=%d)", self.hostname, length_when_mark_detected) return receive_buffer except Exception as e: logging.warning("[%s] Could not send command '%s': %s", self.hostname, command, e) def _receive_ssh_output(self): """ Receives the raw output from the device after a command has been sent and cleans it before returning. :return: Returns the cleaned output of the device :rtype: str """ if self.shell.recv_ready(): raw_output = self.shell.recv(self.ssh_max_bytes) return self._remove_ansi_escape_codes(raw_output.decode('utf8')) else: return "" def _remove_ansi_escape_codes(self, string): """ Cleans a string by removing all ANSI and VT100 escape characters using a regular expression. :param string: The string to clean :type string: str :return: Returns the cleaned string :rtype: str """ expression = r"\[\d{1,2}\;\d{1,2}[a-zA-Z]?\d?|\[\??\d{1,2}[a-zA-Z]" ansi_escape = re.compile(expression) return ansi_escape.sub('', string.replace(u"\u001b", "")) def _prepare_switch(self): """ Sends the preparation commands to the device such as pressing a key to skip the banner or as removing pagination. """ for cmd in self.network_parser.preparation_cmds: time.sleep(0.5) self._send_ssh_command(cmd)
from flask import Flask, jsonify, request, abort, render_template from database_connector import DatabaseConnector from auth_manager import AuthManager from accounts_manager import AccountsManager from transactions_manager import TransactionsManager import time database_connector = DatabaseConnector() auth_manager = AuthManager(database_connector) accounts_manager = AccountsManager(database_connector) transactions_manager = TransactionsManager(database_connector, accounts_manager) app = Flask(__name__) app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0 @app.route('/auth', methods=['POST']) def get_token(): """ HTTP POST /auth: { username: username, password: password } """ if 'username' not in request.form or 'password' not in request.form: abort(400, 'Username or password missing from form-data. ') username = request.form['username'] password = request.form['password']