branch develop updated (b88b55e -> 440088c)
This is an automated email from the git hooks/post-receive script. New change to branch develop in repository mum. See http://git.chorem.org/mum.git from b88b55e clicking on status on the navbar now puts the right status filter new 2488f0f nmap detection can now be launch with a hostname + exception if the host doesn't exists handled new 7fe4e89 first part of ProcessMonitoring new 440088c monitoring automatique fonctionnel The 3 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 440088c864dcce0638ac1e0801a8b087781aca7b Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Thu Feb 26 11:06:38 2015 +0100 monitoring automatique fonctionnel commit 7fe4e89a17f134660bcb69a2c1e9fe2f78abee8b Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Wed Feb 25 15:28:05 2015 +0100 first part of ProcessMonitoring commit 2488f0fd400c522e27e563830ca7d4b4e1767edf Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Wed Feb 25 11:16:31 2015 +0100 nmap detection can now be launch with a hostname + exception if the host doesn't exists handled Summary of changes: app/app.py | 44 ++++---- app/module_loader.py | 70 ++++++++----- app/modules/HostNotFoundException.py | 13 +++ app/modules/detection_modules/nmap_detection.py | 28 +++++- app/modules/storage_modules/shelve_db.py | 127 +++++++++++++++++++----- app/process_monitoring.py | 79 +++++++++++++++ static/js/controllers/mainCtrl.js | 12 ++- views/dashboard.html | 2 +- views/hostpage.html | 1 + views/scan.html | 6 +- 10 files changed, 299 insertions(+), 83 deletions(-) create mode 100644 app/modules/HostNotFoundException.py create mode 100644 app/process_monitoring.py -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository mum. See http://git.chorem.org/mum.git commit 2488f0fd400c522e27e563830ca7d4b4e1767edf Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Wed Feb 25 11:16:31 2015 +0100 nmap detection can now be launch with a hostname + exception if the host doesn't exists handled --- app/app.py | 33 ++++++------- app/module_loader.py | 64 +++++++++++++++---------- app/modules/HostNotFoundException.py | 13 +++++ app/modules/detection_modules/nmap_detection.py | 28 +++++++++-- views/scan.html | 2 +- 5 files changed, 89 insertions(+), 51 deletions(-) diff --git a/app/app.py b/app/app.py index 4fb4db3..8fcddfe 100755 --- a/app/app.py +++ b/app/app.py @@ -28,24 +28,25 @@ ERROR = "40" # Pour lancer la detection nmap avec un nouveau thread class ThreadDetect(threading.Thread): - def __init__(self, ip_range, ws): + def __init__(self, param, ws): threading.Thread.__init__(self) - self.ip_range = ip_range + self.param = param self.ws = ws def run(self): db = module_loader.load_db() conn_mod_list = module_loader.get_conection_modules_list() - scanned_ip = module_loader.run_nmap_detection(self.ip_range, db, self.ws, + scanned_ip = module_loader.run_nmap_detection(self.param, db, self.ws, module_loader.get_conection_modules_list(), module_loader.get_info_mod_monitoring()) - self.ws.send(json.dumps({SUCCESS_MODULE: scanned_ip})) - # now launching full detection - for ip in json.loads(scanned_ip): - conn = module_loader.load_conn("ssh", ip, "aguilbaud", "/home/aguilbaud/.ssh/id_rsa") - module_loader.run_all_detection_modules(db.get_host_os(ip), conn, db, self.ws) - module_loader.run_all_monitoring_modules("unix", conn, db, self.ws) - print "done" + if scanned_ip is not None: + self.ws.send(json.dumps({SUCCESS_MODULE: scanned_ip})) + # now launching full detection + for ip in json.loads(scanned_ip): + conn = module_loader.load_conn("ssh", ip, "aguilbaud", "/home/aguilbaud/.ssh/id_rsa") + module_loader.run_all_detection_modules(db.get_host_os(ip), conn, db, self.ws) + module_loader.run_all_monitoring_modules("unix", conn, db, self.ws) + print "first monitoring done" @route('/') @@ -95,15 +96,9 @@ def angular(): # Lancement de la detection apres reception d'une plage d'ip -def start_first_detection(ip_range, ws): - # Verification que la plage d'ip est bien formatee - if re.search('^\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?$', ip_range): - # Si oui on lance la detection avec le module nmap_detection - t = ThreadDetect(ip_range, ws) - t.start() - else: - # Si non, on envoie un message d'erreur - ws.send(json.dumps({ERROR: "Ip range incorrectly formatted"})) +def start_first_detection(param, ws): + t = ThreadDetect(param, ws) + t.start() @error(404) def error404(error): diff --git a/app/module_loader.py b/app/module_loader.py index c8a0951..d79199f 100644 --- a/app/module_loader.py +++ b/app/module_loader.py @@ -4,10 +4,12 @@ import modules.connection_modules import modules.detection_modules import modules.monitoring_modules import modules.storage_modules -import modules.ModuleNotCompatibleException as moduleNotCompatibleException -import modules.CommandNotFoundException as commandNotFoundException +import modules.ModuleNotCompatibleException +import modules.CommandNotFoundException +import modules.HostNotFoundException import json +import re """ Loads dynamically modules from packages connection_modules, detection_modules, monitoring_modules, storage_modules. @@ -24,17 +26,27 @@ def load_db(): return db_instance -def run_nmap_detection(ip_range, db, ws, list_mod_conn, dict_mod_monitoring): +def run_nmap_detection(param, db, ws, list_mod_conn, dict_mod_monitoring): """ Instanciates the nmap_detection module from detection_modules, and runs the detection. - :param ip_range: addresses to execute the nmap detection + :param param: parameter to put in nmap command. can be a hostname, a ip address or a ip range :param db: an instance of a database module :param ws: a websocket connection :return: a list containing the IP adresses checked """ nmap_mod = __import__("modules.detection_modules.nmap_detection", fromlist=modules.detection_modules) - nmap_mod_instance = getattr(nmap_mod, "nmap_detection")(db, ws, list_mod_conn, dict_mod_monitoring) - return nmap_mod_instance.check_ip_range(ip_range) + nmap_mod_instance = getattr(nmap_mod, "nmap_detection")(db, ws, list_mod_conn, dict_mod_monitoring, + modules.HostNotFoundException) + try: + if re.search('^\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?[.]\d{1,3}(-\d{1,3})?$', param): + ip_range = nmap_mod_instance.check_ip_range(param) + else: + ip_range = nmap_mod_instance.launch_detection_with_hostname(param) + return ip_range + except modules.HostNotFoundException.HostNotFoundException as hnfe: + print hnfe.__str__() + ws.send(json.dumps({"40": hnfe.__str__()})) + return None def load_conn(conn_name, addr_host, username, key_location): # /home/aguilbaud/.ssh/id_rsa @@ -46,7 +58,7 @@ def load_conn(conn_name, addr_host, username, key_location): # /home/aguilbau :return: the instance of connection module created """ conn = __import__("modules.connection_modules." + conn_name, fromlist=modules.connection_modules) - conn_instance = getattr(conn, conn_name)(addr_host, username, key_location, commandNotFoundException) + conn_instance = getattr(conn, conn_name)(addr_host, username, key_location, modules.CommandNotFoundException) return conn_instance @@ -66,10 +78,10 @@ def run_all_detection_modules(os, conn, db, ws): mod_instance = getattr(mod, mod_name)(conn, db) # on appelle le constructeur try: mod_instance.run_detection() - except commandNotFoundException as cnfe: - print cnfe.__str__ + except modules.CommandNotFoundException.CommandNotFoundException as cnfe: + print cnfe.__str__() if ws is not None: - ws.send(json.dumps({"40": cnfe.__str__})) + ws.send(json.dumps({"40": cnfe.__str__()})) def run_all_monitoring_modules(os, conn, db, ws): @@ -84,18 +96,18 @@ def run_all_monitoring_modules(os, conn, db, ws): __import__("modules.monitoring_modules." + os) pack_mod_os = __import__("modules.monitoring_modules." + os, fromlist=modules.monitoring_modules.__all__) for mod_name in pack_mod_os.__all__: - mod = __import__ ("modules.monitoring_modules." + os + "." + mod_name, fromlist=modules.monitoring_modules.unix.__all__) # on charge le module - mod_instance = getattr(mod, mod_name)(conn, db, moduleNotCompatibleException) # on appelle le constructeur + mod = __import__("modules.monitoring_modules." + os + "." + mod_name, fromlist=modules.monitoring_modules.unix.__all__) # on charge le module + mod_instance = getattr(mod, mod_name)(conn, db, modules.ModuleNotCompatibleException) # on appelle le constructeur try: mod_instance.check() - except moduleNotCompatibleException as mnce: - print mnce.__str__ + except modules.ModuleNotCompatibleException.ModuleNotCompatibleException as mnce: + print mnce.__str__() if ws is not None: - ws.send(json.dumps({"40": mnce.__str__})) - except commandNotFoundException as cnfe: - print cnfe.__str__ + ws.send(json.dumps({"40": mnce.__str__()})) + except modules.CommandNotFoundException.CommandNotFoundException as cnfe: + print cnfe.__str__() if ws is not None: - ws.send(json.dumps({"40": cnfe.__str__})) + ws.send(json.dumps({"40": cnfe.__str__()})) def run_one_monitoring_module(mod_name, os, conn, db, ws): @@ -110,17 +122,17 @@ def run_one_monitoring_module(mod_name, os, conn, db, ws): """ __import__("modules.monitoring_modules." + os) mod = __import__("modules.monitoring_modules." + os + "." + mod_name, fromlist=modules.monitoring_modules.unix.__all__) - mod_instance = getattr(mod, mod_name)(conn, db, moduleNotCompatibleException) # on appelle le constructeur + mod_instance = getattr(mod, mod_name)(conn, db, modules.ModuleNotCompatibleException) # on appelle le constructeur try: mod_instance.check() - except moduleNotCompatibleException as mnce: - print mnce.__str__ + except modules.ModuleNotCompatibleException.ModuleNotCompatibleException as mnce: + print mnce.__str__() if ws is not None: - ws.send(json.dumps({"40": mnce.__str__})) - except commandNotFoundException as cnfe: - print cnfe.__str__ + ws.send(json.dumps({"40": mnce.__str__()})) + except modules.CommandNotFoundException.CommandNotFoundException as cnfe: + print cnfe.__str__() if ws is not None: - ws.send(json.dumps({"40": cnfe.__str__})) + ws.send(json.dumps({"40": cnfe.__str__()})) def get_info_mod_monitoring(): @@ -158,5 +170,5 @@ def create_global_conf(db): """ dict_mod = {} for os in modules.monitoring_modules.__all__: - dict_mod[os] = get_info_mod_monitoring(os) + dict_mod[os] = get_info_mod_monitoring() db.create_global_conf(dict_mod) \ No newline at end of file diff --git a/app/modules/HostNotFoundException.py b/app/modules/HostNotFoundException.py new file mode 100644 index 0000000..505e7cc --- /dev/null +++ b/app/modules/HostNotFoundException.py @@ -0,0 +1,13 @@ +__author__ = 'aguilbaud' + +""" +Raised if the address or hostname passed to nmap cannot have been found +""" + + +class HostNotFoundException(Exception): + def __init__(self, addr_host): + self.addr_host = addr_host + + def __str__(self): + return "Host '" + self.addr_host + "' seems to not exist." \ No newline at end of file diff --git a/app/modules/detection_modules/nmap_detection.py b/app/modules/detection_modules/nmap_detection.py index 3b4b6ec..fdb04fd 100644 --- a/app/modules/detection_modules/nmap_detection.py +++ b/app/modules/detection_modules/nmap_detection.py @@ -6,12 +6,13 @@ import json class nmap_detection: - def __init__(self, db, ws, list_mod_conn, dict_mod_monitoring): + def __init__(self, db, ws, list_mod_conn, dict_mod_monitoring, hnfe): self.db = db self.ws = ws self.scanned_ip = [] self.list_mod_conn = list_mod_conn self.dict_mod_monitoring = dict_mod_monitoring + self.HostNotFoundException = hnfe # function for splitting the different ranges of the IP adress # launch the nmap detection of each ip under this range @@ -96,6 +97,22 @@ class nmap_detection: except pexpect.ExceptionPexpect: self.ws.send(json.dumps({"40": "nmap command not avaliable on server"})) + def launch_detection_with_hostname(self, hostname): + self.ws.send(json.dumps({"30": "Scanning host : " + hostname})) + try: + child = pexpect.spawn('nmap', ['-A', '-Pn', hostname, '-oX', 'res.xml']) + while child.isalive(): + child.expect('Completed', timeout=None) + except pexpect.EOF: + #try: + self.parse_res(hostname) + return json.dumps(self.scanned_ip) + #except: + # self.ws.send(json.dumps({"40": "Database error"})) + except pexpect.TIMEOUT: + self.ws.send(json.dumps({"40": "Timeout on nmap execution"})) + except pexpect.ExceptionPexpect: + self.ws.send(json.dumps({"40": "nmap command not avaliable on server"})) # parse the xml result to keep only interesting values # save directly it on the database @@ -107,9 +124,10 @@ class nmap_detection: # get every <host> of the collection hosts = collection.getElementsByTagName("host") - # if host cannot have been detected, adds it empty + # if host cannot have been detected, throws an exception if hosts == []: - self.db.add_host(ip, {}) + exception_inst = getattr(self.HostNotFoundException, "HostNotFoundException")(ip) + raise exception_inst # Get the nodes of each <host> and recuperaton of their attributes # JSON = dictionary list @@ -147,5 +165,5 @@ class nmap_detection: dict_host['openports'] = list_dict_port # the host have its IP for ID on the db self.db.add_host(dict_host['addr'], json.dumps(dict_host), self.list_mod_conn, self.dict_mod_monitoring) - pexpect.run("rm -f res.xml") - self.scanned_ip.append(ip) \ No newline at end of file + self.scanned_ip.append(dict_host['addr']) + pexpect.run("rm -f res.xml") \ No newline at end of file diff --git a/views/scan.html b/views/scan.html index 0618a35..4965ce4 100644 --- a/views/scan.html +++ b/views/scan.html @@ -3,7 +3,7 @@ <h1 class="page-header">Scan for new machines</h1> <div ng-show="validated == false" class="ng-hide"> <form class="form-inline" ng_submit="post_val()"> - <label for="input_ip_range">IP range to scan (example : 198.116.0.1-10)</label> + <label for="input_ip_range">Enter a hostname, a single IP or an IP range to scan (example : 198.116.0.1-10)</label> <input type="ip_range" class="form-control" id="input_ip_range" ng-model="ip_range"/> <button type="submit" class="btn btn-primary" ng-click="validated = true">Scan now</button> </form> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository mum. See http://git.chorem.org/mum.git commit 7fe4e89a17f134660bcb69a2c1e9fe2f78abee8b Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Wed Feb 25 15:28:05 2015 +0100 first part of ProcessMonitoring --- app/modules/storage_modules/shelve_db.py | 58 ++++++++++++++++++-------------- app/process_monitoring.py | 58 ++++++++++++++++++++++++++++++++ static/js/controllers/mainCtrl.js | 2 +- views/scan.html | 4 +-- 4 files changed, 94 insertions(+), 28 deletions(-) diff --git a/app/modules/storage_modules/shelve_db.py b/app/modules/storage_modules/shelve_db.py index 5c78984..ef26d36 100644 --- a/app/modules/storage_modules/shelve_db.py +++ b/app/modules/storage_modules/shelve_db.py @@ -64,8 +64,13 @@ class shelve_db: self.db["hosts"][addr_host]["detected"]["nmap"] = nmap_res # Preconfiguration self.db["hosts"][addr_host]["conf"] = {} - self.db["hosts"][addr_host]["conf"]["monitoring"] = self.generate_global_conf(dict_mod_info, - json.loads(nmap_res)['os']) + os_host = json.loads(nmap_res)['os'] + if os_host == 'unknown': + # TODO : may throw exception here + print "OS of " + addr_host + " cannot have been detected. Monitoring cannot be autoconfigurated." + self.db["hosts"][addr_host]["conf"]["monitoring"] = {} + else: + self.db["hosts"][addr_host]["conf"]["monitoring"] = self.generate_global_conf(dict_mod_info, os_host) self.db["hosts"][addr_host]["conf"]["groups"] = ["all"] # Every host is in group "all" self.db["hosts"][addr_host]["conf"]["connections"] = self.init_conn(json.loads(nmap_res), list_mod_conn) self.db["hosts"][addr_host]["conf"]["subscribers"] = {} # Add current user automatically ? @@ -89,29 +94,32 @@ class shelve_db: :return a list containing the default parameters for each monitoring module """ res = {} - for mod in dict_mod_info[os]: - mod_conf = {} - mod_conf['block'] = dict_mod_info[os][mod]['block'] - mod_conf['activated'] = True - mod_conf['check_frequency'] = 60 - mod_conf['nb_minute'] = 30 - mod_conf['nb_hour'] = 12 - mod_conf['nb_day'] = 15 - mod_conf['nb_week'] = 2 - mod_conf['nb_month'] = 6 - mod_conf['nb_year'] = None - unit = dict_mod_info[os][mod]['unit'] - mod_conf['unit'] = unit - if unit == '%': - mod_conf['minor_limit'] = 95 - mod_conf['major_limit'] = 100 - elif unit == 'bool': - mod_conf['minor_limit'] = True - mod_conf['major_limit'] = False - else: - mod_conf['minor_limit'] = 8 - mod_conf['major_limit'] = 10 - res[mod] = mod_conf + if os not in dict_mod_info: + print "OS " + os + " is not supported by the monitoring modules currently loaded." + else: + for mod in dict_mod_info[os]: + mod_conf = {} + mod_conf['block'] = dict_mod_info[os][mod]['block'] + mod_conf['activated'] = True + mod_conf['check_frequency'] = 60 + mod_conf['nb_minute'] = 30 + mod_conf['nb_hour'] = 12 + mod_conf['nb_day'] = 15 + mod_conf['nb_week'] = 2 + mod_conf['nb_month'] = 6 + mod_conf['nb_year'] = None + unit = dict_mod_info[os][mod]['unit'] + mod_conf['unit'] = unit + if unit == '%': + mod_conf['minor_limit'] = 95 + mod_conf['major_limit'] = 100 + elif unit == 'bool': + mod_conf['minor_limit'] = True + mod_conf['major_limit'] = False + else: + mod_conf['minor_limit'] = 8 + mod_conf['major_limit'] = 10 + res[mod] = mod_conf return res def init_conn(self, dict_nmap_res, conn_list): diff --git a/app/process_monitoring.py b/app/process_monitoring.py new file mode 100644 index 0000000..7c76a41 --- /dev/null +++ b/app/process_monitoring.py @@ -0,0 +1,58 @@ +__author__ = 'aguilbaud' + +import threading +from datetime import datetime +from datetime import timedelta +import time + + +class ProcessMonitoring(threading.Thread): + """ + Runs the monitoring modules at the specified time. + Attributes : - waiting_queue : a list containing structured data concerning the monitring modules to launch + in the form + { + 'addr' : val, => the IP address of the host + 'os', val, => the operating system of the host + 'mod_name', val, => the name of the monitoring module + 'time', val, => the time at when to launch the monitoring module + 'freq', val => the frequency check (in seconds) + } + The data are ordored by crescent time. This is for optimize the complexity when poping the most recent time. + We could use here the deque structure from Python in order to use optimized poping left, but this structure + don't have implemented the insert() function, which is used for adding new data and keep the queue ordored. + - buffer_launcher : a list containing structured data of the same type than waiting_queue, + but elements here have to be executed for check. + """ + def __init__(self): + threading.Thread.__init__(self) + self.waiting_queue = [] + self.buffer_launcher = [] + + def run(self): + while True: + if not self.waiting_queue == []: + while self.waiting_queue[len(self.waiting_queue) - 1]['time'] <= datetime.now(): + dict_mod = self.waiting_queue.pop(len(self.waiting_queue) - 1) + self.buffer_launcher.append(dict_mod) + dict_mod['time'] = dict_mod['time'] + timedelta(seconds=dict_mod['freq']) + self.add_to_waiting_queue(dict_mod) + time.sleep(1) + + def add_to_waiting_queue(self, dict_mod): + if self.waiting_queue == []: + self.waiting_queue.append(dict_mod) + else: + pos_queue = 0 + while pos_queue < len(self.waiting_queue) and dict_mod['time'] <= self.waiting_queue[pos_queue]['time']: + pos_queue += 1 + self.waiting_queue.insert(pos_queue, dict_mod) + +""" +class RunMonitoring(threading.Thread): + def __init__(self, list_of_dict_mod): + threading.Thread.__init__(self) + self.list_of_dict_mod = list_of_dict_mod + + def run(self): + """ \ No newline at end of file diff --git a/static/js/controllers/mainCtrl.js b/static/js/controllers/mainCtrl.js index 5a29c00..c71643f 100644 --- a/static/js/controllers/mainCtrl.js +++ b/static/js/controllers/mainCtrl.js @@ -129,7 +129,7 @@ mumApp.controller('mainController', ['$scope', 'toastr', '$interval', '$filter', break; case 30: $scope.$apply(function(){ - $scope.status = value; + $scope.state = value; }); toastr.info(value, "Current status is :"); /* diff --git a/views/scan.html b/views/scan.html index 4965ce4..d99fc8e 100644 --- a/views/scan.html +++ b/views/scan.html @@ -9,8 +9,8 @@ </form> </div> <div ng-show="validated == true"> - {{state}} - {{ip_scanned}} + <p>{{state}}</p> + <p>Scanned IP : {{ip_scanned}}</p> </div> </div> </div> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository mum. See http://git.chorem.org/mum.git commit 440088c864dcce0638ac1e0801a8b087781aca7b Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Thu Feb 26 11:06:38 2015 +0100 monitoring automatique fonctionnel --- app/app.py | 15 +++++-- app/module_loader.py | 6 ++- app/modules/storage_modules/shelve_db.py | 69 ++++++++++++++++++++++++++++++++ app/process_monitoring.py | 63 +++++++++++++++++++---------- static/js/controllers/mainCtrl.js | 10 +++++ views/dashboard.html | 2 +- views/hostpage.html | 1 + 7 files changed, 139 insertions(+), 27 deletions(-) diff --git a/app/app.py b/app/app.py index 8fcddfe..9c22377 100755 --- a/app/app.py +++ b/app/app.py @@ -8,6 +8,7 @@ from bottle_websocket import websocket import json import threading import module_loader +import process_monitoring NMAP_SCAN_DEMAND = "10" DETECTION_DEMAND = "11" @@ -45,9 +46,11 @@ class ThreadDetect(threading.Thread): for ip in json.loads(scanned_ip): conn = module_loader.load_conn("ssh", ip, "aguilbaud", "/home/aguilbaud/.ssh/id_rsa") module_loader.run_all_detection_modules(db.get_host_os(ip), conn, db, self.ws) - module_loader.run_all_monitoring_modules("unix", conn, db, self.ws) - print "first monitoring done" - + monitoring_intructions = db.get_monitoring_instructions(ip) + for instr in monitoring_intructions: + process_monitoring.add_to_waiting_list(instr) + #module_loader.run_all_monitoring_modules("unix", conn, db, self.ws) + # adding entries on process monitoring @route('/') def index(section='home'): @@ -132,6 +135,9 @@ def receive(ws): db = module_loader.load_db() ws.send(json.dumps({GET_HOSTS_RESPONSE: db.get_hosts()})) del db + elif code == HOST_INFO_DEMAND: + db = module_loader.load_db() + ws.send({INFO_HOST: db.get_host_inoformations(msg[HOST_INFO_DEMAND])}) else: break except: # Should be WebSocketError when closing the connection @@ -140,5 +146,6 @@ def receive(ws): # Lancement du serveur a l'adresse 0.0.0.0:1337 if __name__ == '__main__': + process_monitoring.init() port = int(os.environ.get('PORT', 1337)) - run(host='0.0.0.0', port=port, debug=True, reloader=True, server=GeventWebSocketServer) + run(host='0.0.0.0', port=port, debug=True, reloader=True, server=GeventWebSocketServer) \ No newline at end of file diff --git a/app/module_loader.py b/app/module_loader.py index d79199f..f1ded30 100644 --- a/app/module_loader.py +++ b/app/module_loader.py @@ -110,7 +110,7 @@ def run_all_monitoring_modules(os, conn, db, ws): ws.send(json.dumps({"40": cnfe.__str__()})) -def run_one_monitoring_module(mod_name, os, conn, db, ws): +def run_one_monitoring_module(mod_name, addr_host, os, conn, db, ws): """ Instanciates and runs one monitoring_module of the package corresponding to the operating system entered in parameters. @@ -120,6 +120,10 @@ def run_one_monitoring_module(mod_name, os, conn, db, ws): :param db: an instance of a storage module :param ws: a websocket connection if the function have been called from a client. Is None otherwise """ + if conn is None: + conn = load_conn("ssh", addr_host, "aguilbaud", "/home/aguilbaud/.ssh/id_rsa") + if db is None: + db = load_db() __import__("modules.monitoring_modules." + os) mod = __import__("modules.monitoring_modules." + os + "." + mod_name, fromlist=modules.monitoring_modules.unix.__all__) mod_instance = getattr(mod, mod_name)(conn, db, modules.ModuleNotCompatibleException) # on appelle le constructeur diff --git a/app/modules/storage_modules/shelve_db.py b/app/modules/storage_modules/shelve_db.py index ef26d36..aab9e92 100644 --- a/app/modules/storage_modules/shelve_db.py +++ b/app/modules/storage_modules/shelve_db.py @@ -140,6 +140,35 @@ class shelve_db: cpt += 1 return dict_conn + def get_monitoring_instructions(self, addr_host): + """ + Necessary to launch for the first time all activated monitoring modules for a given host + :param addr_host: the address IP of the host + :return: structured informations about monitoring in form : + { + 'addr' : val, => the IP address of the host + 'os', val, => the operating system of the host + 'mod_name', val, => the name of the monitoring module + 'time', val, => the time at when to launch the monitoring module + 'freq', val => the frequency check (in seconds) + } + """ + self.open_db() + res = [] + try: + for mod in self.db['hosts'][addr_host]['conf']['monitoring']: + if self.db['hosts'][addr_host]['conf']['monitoring'][mod]['activated']: + dict = {} + dict['addr'] = addr_host + dict['os'] = json.loads(self.db['hosts'][addr_host]['detected']['nmap'])['os'] + dict['mod_name'] = mod + dict['time'] = datetime.now() + dict['freq'] = self.db['hosts'][addr_host]['conf']['monitoring'][mod]['check_frequency'] + res.append(dict) + finally: + self.close_db() + return res + def get_hosts(self): """ Returns the essential data about all hosts under monitoring @@ -194,6 +223,46 @@ class shelve_db: self.close_db() return json.dumps(res) + def get_host_inoformations(self, addr_host): + """ + Get every informations necessary for the hostpage summary page. + :param addr_host: the IP address of the host + :return: informations concerning this host on the form : + { + addr_host:{ + 'monitoring':{ + mod_name:{ + 'state':val, + 'value':val, + 'unit':val, + 'last_check':date + } + } + 'detection':{ + mod_name:res + } + 'custom_info';val + 'interventions':list + } + } + """ + self.open_db() + res = {} + try: + res['monitoring'] = {} + for mod in self.db['hosts'][addr_host]['monitoring']: + print mod + res['monitoring'][mod] = self.db['hosts'][addr_host]['monitoring'][mod] + res['detected'] = {} + for mod in self.db['hosts'][addr_host]['detected']: + res['detected'][mod] = json.loads(self.db['hosts'][addr_host]['detected'][mod]) + res['custom_info'] = self.db['hosts'][addr_host]['conf']['custom_info'] + res['interventions'] = self.db['hosts'][addr_host]['conf']['interventions'] + finally: + self.close_db() + return json.dumps({addr_host: res}) + + def remove_host(self, addr_host): """ Removes from the database the host at the adress on parameter. If the host is part of a group, it will be diff --git a/app/process_monitoring.py b/app/process_monitoring.py index 7c76a41..c9f03b8 100644 --- a/app/process_monitoring.py +++ b/app/process_monitoring.py @@ -3,7 +3,15 @@ __author__ = 'aguilbaud' import threading from datetime import datetime from datetime import timedelta +from module_loader import run_one_monitoring_module import time +import sys + +waiting_list = [] + +def init(): + pm = ProcessMonitoring() + pm.start() class ProcessMonitoring(threading.Thread): @@ -21,38 +29,51 @@ class ProcessMonitoring(threading.Thread): The data are ordored by crescent time. This is for optimize the complexity when poping the most recent time. We could use here the deque structure from Python in order to use optimized poping left, but this structure don't have implemented the insert() function, which is used for adding new data and keep the queue ordored. - - buffer_launcher : a list containing structured data of the same type than waiting_queue, - but elements here have to be executed for check. """ def __init__(self): threading.Thread.__init__(self) - self.waiting_queue = [] - self.buffer_launcher = [] def run(self): + """ + Each second, the process will check if the last element of the list have to be lauch. + If it is the case, it will add this element to the launching list, as well with the previous elements + having the same launching date. + """ + global waiting_list while True: - if not self.waiting_queue == []: - while self.waiting_queue[len(self.waiting_queue) - 1]['time'] <= datetime.now(): - dict_mod = self.waiting_queue.pop(len(self.waiting_queue) - 1) - self.buffer_launcher.append(dict_mod) + if not waiting_list == []: + modules_to_run = [] + while waiting_list[len(waiting_list) - 1]['time'] <= datetime.now(): + dict_mod = waiting_list.pop(len(waiting_list) - 1) + modules_to_run.append(dict_mod) dict_mod['time'] = dict_mod['time'] + timedelta(seconds=dict_mod['freq']) - self.add_to_waiting_queue(dict_mod) + add_to_waiting_list(dict_mod) + rm = RunMonitoring(modules_to_run) + rm.start() time.sleep(1) - def add_to_waiting_queue(self, dict_mod): - if self.waiting_queue == []: - self.waiting_queue.append(dict_mod) - else: - pos_queue = 0 - while pos_queue < len(self.waiting_queue) and dict_mod['time'] <= self.waiting_queue[pos_queue]['time']: - pos_queue += 1 - self.waiting_queue.insert(pos_queue, dict_mod) -""" +def add_to_waiting_list(dict_mod): + """ + Adds an element to the waiting queue and keep it ordered by crescent launching times. + """ + global waiting_list + if waiting_list == []: + waiting_list.append(dict_mod) + else: + pos_queue = 0 + while pos_queue < len(waiting_list) and dict_mod['time'] <= waiting_list[pos_queue]['time']: + pos_queue += 1 + waiting_list.insert(pos_queue, dict_mod) + + class RunMonitoring(threading.Thread): - def __init__(self, list_of_dict_mod): + def __init__(self, list_dict_mod): threading.Thread.__init__(self) - self.list_of_dict_mod = list_of_dict_mod + self.list_dict_mod = list_dict_mod def run(self): - """ \ No newline at end of file + for dict_mod in self.list_dict_mod: + print "Launching " + str(dict_mod['os']) + "." + str(dict_mod['mod_name']) + " on " + str(dict_mod['addr']) + sys.stdout.flush() + run_one_monitoring_module(dict_mod['mod_name'], dict_mod['addr'], dict_mod['os'], None, None, None) \ No newline at end of file diff --git a/static/js/controllers/mainCtrl.js b/static/js/controllers/mainCtrl.js index c71643f..452e6c3 100644 --- a/static/js/controllers/mainCtrl.js +++ b/static/js/controllers/mainCtrl.js @@ -101,6 +101,13 @@ mumApp.controller('mainController', ['$scope', 'toastr', '$interval', '$filter', $scope.scan_is_over = false; // pour afficher ou non certaines parties de la page $scope.ip_scanned = {}; + /* + // Concerning the hostpage + $scope.host_informations = null; + $scope.get_host_informations = function(addr_host){ + var request = '{"13" : "'+ addr_host + '"}'; + ws.send(request); + }*/ // Concerning WebSocket var ws = new WebSocket("ws://0.0.0.0:1337/websocket"); @@ -121,6 +128,9 @@ mumApp.controller('mainController', ['$scope', 'toastr', '$interval', '$filter', }); toastr.success(value, "Success on module execution"); case 21: // Informations concerning one host + /*$scope.$apply(function(){ + $scope.host_informations = JSON.parse(value); + });*/ break; case 22: // List of hosts under monitoring $scope.$apply(function(){ diff --git a/views/dashboard.html b/views/dashboard.html index d405482..e621f0d 100644 --- a/views/dashboard.html +++ b/views/dashboard.html @@ -68,7 +68,7 @@ orderBy:sort.sortingOrder:sort.reverse | filter:{addr:addr_filter, name:name_filter, status:status_filter, group:{name:group_filter}}" class={{item.status}}> - <td><a href="#/hostpage/{{item.addr}}">{{item.addr}}</a></td> + <td><a href="#/hostpage/{{item.addr}}" ng-click="get_host_informations({{item.addr}})">{{item.addr}}</a></td> <td>{{item.name}}</td> <td>{{item.status}}</td> <td>{{getGroupsByAddr(item.addr)}}</td> diff --git a/views/hostpage.html b/views/hostpage.html index fd9bd28..f25aec8 100644 --- a/views/hostpage.html +++ b/views/hostpage.html @@ -5,6 +5,7 @@ <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_conn">Connection settings</button> <button type="button" class="btn btn-info btn-xs">Launch a new detection</button> <button type="button" class="btn btn-danger btn-xs">Remove this host</button> + {{host_informations}} <table class="table table-condensed table-hover"> <thead> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm