branch develop updated (0b5c9d1 -> 7d977ba)
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 0b5c9d1 suppression de res.xml new c865e90 toaster en place sur l'index de base + maquette ajoutée new 6c21b41 scan nmap sauvegardé dans bdd Shelve new 91d6baf scan nmap sauvegardé dans bdd Shelve new 7d977ba function get_hosts() implemented The 4 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 7d977bac276a337cf4cb14876f24ef8428ff2cd1 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 15:22:17 2015 +0100 function get_hosts() implemented commit 91d6baf751607759cf9c762bd21e5373b95b2298 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 11:29:06 2015 +0100 scan nmap sauvegardé dans bdd Shelve commit 6c21b415ad9507b1566b7a7961139806bedd490f Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 11:28:31 2015 +0100 scan nmap sauvegardé dans bdd Shelve commit c865e90a5142080a7c767a737e49d114da57af81 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Mon Feb 16 17:52:35 2015 +0100 toaster en place sur l'index de base + maquette ajoutée Summary of changes: app/app.py | 63 ++- app/{detection_modules => modules}/__init__.py | 0 .../detection_modules}/__init__.py | 0 app/modules/detection_modules/drive_detection.py | 34 ++ .../detection_modules/nagios_detection.py | 0 .../detection_modules/nmap_detection.py | 88 ++-- .../detection_modules/snmp_detection.py | 0 .../detection_modules/ssh_detection.py | 15 +- app/modules/storage.py | 156 ++++++ app/{ => modules/storage_module}/__init__.py | 0 bower.json | 4 +- static/css/dashboard.css | 121 +++++ static/css/signin.css | 40 ++ static/js/controllers/detectCtrl.js | 60 ++- static/js/controllers/settings_ctrl.js | 8 + static/js/controllers/table_ctrl.js | 351 ++++++++++++++ views/angular.html | 20 - views/dashboard.html | 162 +++++++ views/groups.html | 142 ++++++ views/hostpage.html | 524 +++++++++++++++++++++ views/index.html | 24 +- views/notifications.html | 247 ++++++++++ views/profile.html | 187 ++++++++ views/scan.html | 81 ++++ views/settings.html | 216 +++++++++ views/signin.html | 43 ++ views/stats.html | 97 ++++ views/users.html | 94 ++++ 28 files changed, 2685 insertions(+), 92 deletions(-) rename app/{detection_modules => modules}/__init__.py (100%) rename app/{monitoring_modules => modules/detection_modules}/__init__.py (100%) create mode 100644 app/modules/detection_modules/drive_detection.py rename app/{ => modules}/detection_modules/nagios_detection.py (100%) rename app/{ => modules}/detection_modules/nmap_detection.py (60%) rename app/{ => modules}/detection_modules/snmp_detection.py (100%) rename app/{ => modules}/detection_modules/ssh_detection.py (90%) create mode 100644 app/modules/storage.py copy app/{ => modules/storage_module}/__init__.py (100%) create mode 100644 static/css/dashboard.css create mode 100644 static/css/signin.css create mode 100644 static/js/controllers/settings_ctrl.js create mode 100644 static/js/controllers/table_ctrl.js delete mode 100644 views/angular.html create mode 100644 views/dashboard.html create mode 100644 views/groups.html create mode 100644 views/hostpage.html create mode 100644 views/notifications.html create mode 100644 views/profile.html create mode 100644 views/scan.html create mode 100644 views/settings.html create mode 100644 views/signin.html create mode 100644 views/stats.html create mode 100644 views/users.html -- 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 c865e90a5142080a7c767a737e49d114da57af81 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Mon Feb 16 17:52:35 2015 +0100 toaster en place sur l'index de base + maquette ajoutée --- app/app.py | 61 +++- app/detection_modules/nmap_detection.py | 76 +++-- app/detection_modules/ssh_detection.py | 15 +- app/storage.py | 78 +++++ bower.json | 4 +- requirements.txt | 3 +- static/css/dashboard.css | 121 ++++++++ static/css/signin.css | 40 +++ static/js/controllers/detectCtrl.js | 60 +++- static/js/controllers/settings_ctrl.js | 8 + static/js/controllers/table_ctrl.js | 351 +++++++++++++++++++++ views/angular.html | 20 -- views/dashboard.html | 162 ++++++++++ views/groups.html | 142 +++++++++ views/hostpage.html | 524 ++++++++++++++++++++++++++++++++ views/index.html | 20 +- views/notifications.html | 247 +++++++++++++++ views/profile.html | 187 ++++++++++++ views/scan.html | 80 +++++ views/settings.html | 216 +++++++++++++ views/signin.html | 43 +++ views/stats.html | 97 ++++++ views/users.html | 94 ++++++ 23 files changed, 2561 insertions(+), 88 deletions(-) diff --git a/app/app.py b/app/app.py index cedca86..43532f9 100755 --- a/app/app.py +++ b/app/app.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals __author__ = 'aguilbaud' from bottle import * -from detection_modules.nmap_detection import check_ip_range +from detection_modules.nmap_detection import check_ip_range, get_scanned_ip from bottle_websocket import GeventWebSocketServer from bottle_websocket import websocket import json @@ -20,7 +20,9 @@ class ThreadDetect(threading.Thread): def run(self): req = {} check_ip_range(self.ip_range, self.ws) - req["state"] = "Scan terminé" + #print "scanned ip :" + #print get_scanned_ip() + req["20"] = get_scanned_ip() self.ws.send(json.dumps(req)) @@ -29,22 +31,58 @@ def index(section='home'): return template('index') -@route('/angular') +@route('/dashboard.html') def angular(): - return template('angular') + return template('dashboard') + +@route('/groups.html') +def angular(): + return template('groups') + +@route('/hostpage.html') +def angular(): + return template('hostpage') + +@route('/notifications.html') +def angular(): + return template('notifications') + +@route('/profile.html') +def angular(): + return template('profile') + +@route('/scan.html') +def angular(): + return template('scan') + +@route('/settings.html') +def angular(): + return template('settings') + +@route('/signin.html') +def angular(): + return template('signin') + +@route('/stats.html') +def angular(): + return template('stats') + +@route('/users.html') +def angular(): + return template('users') # Lancement de la detection apres reception d'une plage d'ip def start_first_detection(ip_range, ws): req = {} - # Verification que l'ip est bien formatee + # 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 - req["error"] = "La plage d'IP est mal formatée" + req["40"] = "La plage d'IP est mal formatée" ws.send(json.dumps(req)) @error(404) @@ -66,14 +104,17 @@ def bower_files(filepath): # Creation d'une websocket pour permettre la communication avec le client @get('/websocket', apply=[websocket]) -def echo(ws): +def receive(ws): while True: response = ws.receive() if response is not None: msg = json.loads(response) - for title in msg: - if title == "Sending_ip_range": - start_first_detection(msg["Sending_ip_range"], ws) + for code in msg: + if code == "10": + start_first_detection(msg["10"], ws) + else: + return + # Lancement du serveur a l'adresse 0.0.0.0:1337 diff --git a/app/detection_modules/nmap_detection.py b/app/detection_modules/nmap_detection.py index 7d59fd1..e8adecf 100644 --- a/app/detection_modules/nmap_detection.py +++ b/app/detection_modules/nmap_detection.py @@ -9,57 +9,65 @@ import json scanned_ip = {} +def get_scanned_ip(): + global scanned_ip + return json.dumps(scanned_ip) + + # fonction qui permet de decomposer les differentes plages d'ip # lance la detection nmap pour chacune des ip comprises dans cette plage +# NB : il est possible de lancer nmap directement sur la plage, mais il est alors difficile de determiner l'état +# du scan. De plus, si la plage d'ip est grande, l'exécution sera bien plus longue et tous les résultats +# seront obtenus d'un coup à la fin. def check_ip_range(ip_range, ws): # separation des 4 octets - byte1 = ip_range.split('.')[0] - byte2 = ip_range.split('.')[1] - byte3 = ip_range.split('.')[2] - byte4 = ip_range.split('.')[3] + range_byte_1 = ip_range.split('.')[0] + range_byte_2 = ip_range.split('.')[1] + range_byte_3 = ip_range.split('.')[2] + range_byte_4 = ip_range.split('.')[3] # separation des plages eventuelles - split_byte1 = byte1.split('-') - split_byte2 = byte2.split('-') - split_byte3 = byte3.split('-') - split_byte4 = byte4.split('-') + split_byte_1 = range_byte_1.split('-') + split_byte_2 = range_byte_2.split('-') + split_byte_3 = range_byte_3.split('-') + split_byte_4 = range_byte_4.split('-') # si aucune plage n'est indiquee, on cree une plage de meme valeur - if len(split_byte1) == 1: - split_byte1.append(split_byte1[0]) + if len(split_byte_1) == 1: + split_byte_1.append(split_byte_1[0]) # verification que les nombres sont ordonnes correctement # et que les valeurs entrees sont inferieures a 255 - split_byte1 = check_order_and_under_255(split_byte1) + split_byte_1 = check_order_and_under_255(split_byte_1) # idem pour le deuxieme octet - if len(split_byte2) == 1: - split_byte2.append(split_byte2[0]) - split_byte2 = check_order_and_under_255(split_byte2) + if len(split_byte_2) == 1: + split_byte_2.append(split_byte_2[0]) + split_byte_2 = check_order_and_under_255(split_byte_2) # idem pour le troisieme octet - if len(split_byte3) == 1: - split_byte3.append(split_byte3[0]) - split_byte3 = check_order_and_under_255(split_byte3) + if len(split_byte_3) == 1: + split_byte_3.append(split_byte_3[0]) + split_byte_3 = check_order_and_under_255(split_byte_3) # idem pour le quatrieme octet - if len(split_byte4) == 1: - split_byte4.append(split_byte4[0]) - split_byte4 = check_order_and_under_255(split_byte4) + if len(split_byte_4) == 1: + split_byte_4.append(split_byte_4[0]) + split_byte_4 = check_order_and_under_255(split_byte_4) # il est possible d'ajouter ici une condition pour verifier que l'utilisateur # n'ait pas entre une plage d'IP trop grande # pour toutes les plages dans l'ordre croissant, en partant du dernier octet - for i in range(int(split_byte1[0]), int(split_byte1[1]) + 1): - for j in range(int(split_byte2[0]), int(split_byte2[1]) + 1): - for k in range(int(split_byte3[0]), int(split_byte3[1]) + 1): - for l in range(int(split_byte4[0]), int(split_byte4[1]) + 1): - launch_detection(i, j, k, l, ws) + for byte_1 in range(int(split_byte_1[0]), int(split_byte_1[1]) + 1): + for byte_2 in range(int(split_byte_2[0]), int(split_byte_2[1]) + 1): + for byte_3 in range(int(split_byte_3[0]), int(split_byte_3[1]) + 1): + for byte_4 in range(int(split_byte_4[0]), int(split_byte_4[1]) + 1): + launch_detection(byte_1, byte_2, byte_3, byte_4, ws) -# verifie que la plage de donnee entree est dans l'ordre croissant -# et que ses valeurs sont inferieures a 255 -# si ce n'est pas le cas, retourne le tableau trie et/ou avec les valeurs capees a 255 +# vérifie que la plage de données entrée est dans l'ordre croissant +# et que ses valeurs sont inferieures à 255 +# si ce n'est pas le cas, retourne le tableau trié et/ou avec les valeurs capées à 255 def check_order_and_under_255(tab_val): if int(tab_val[0]) > 255 : tab_val[0] = '255' @@ -73,10 +81,10 @@ def check_order_and_under_255(tab_val): # lance la detection a l'aide de nmap sur l'ip representee par les 4 octets passes en parametres -def launch_detection(b1, b2, b3, b4, ws): +def launch_detection(byte_1, byte_2, byte_3, byte_4, ws): req = {} - ip = str(b1) + '.' + str(b2) + '.' + str(b3) + '.' + str(b4) - req["state"] = "Scan de l'IP " + ip + " en cours..." + ip = str(byte_1) + '.' + str(byte_2) + '.' + str(byte_3) + '.' + str(byte_4) + req["30"] = "Scan de l'IP " + ip + " en cours..." ws.send(json.dumps(req)) child = pexpect.spawn('nmap', ['-A', ip, '-oX', 'res.xml']) res = '' @@ -137,6 +145,8 @@ def parse_res(ip): list_dict_port.append(dict_port) dict_host['openports'] = list_dict_port # sauvegarde de l'host dans la base elasticsearch avec pour ID son IP - pexpect.run('curl -XPUT \'localhost:9200/host/external/' + dict_host['addr'] + '?pretty\' -d \'' + - json.dumps(dict_host) + '\'') + pexpect.run("curl -XPUT 'localhost:9200/host/external/" + dict_host['addr'] + "' -d '" + + json.dumps(dict_host) + "'") + pexpect.run("rm -f res.xml") + #pexpect.run('curl -XPUT \'localhost:9200/saved_hosts' scanned_ip[ip] = "localhost:9200/host/external/" + ip \ No newline at end of file diff --git a/app/detection_modules/ssh_detection.py b/app/detection_modules/ssh_detection.py index 76f133c..c2d1c52 100644 --- a/app/detection_modules/ssh_detection.py +++ b/app/detection_modules/ssh_detection.py @@ -1,6 +1,7 @@ import paramiko import json + # il faudrait p-e separer le traitement du resultat des commandes avec le lancement en lui mm # si independant des protocoles utilises @@ -12,6 +13,8 @@ def connect(): ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('127.0.0.1', username='aguilbaud', pkey=key) + run_detection(ssh) + disconnect(ssh) @@ -20,10 +23,10 @@ def disconnect(ssh): def run_detection(ssh): - detect_hardware(ssh) - detect_drives(ssh) - detect_os_version(ssh) - detect_non_updated_packages(ssh) + print detect_hardware(ssh) + print detect_drives(ssh) + print detect_os_version(ssh) + print detect_non_updated_packages(ssh) # Informations materielles globales @@ -34,7 +37,7 @@ def detect_hardware(ssh): for line in stdout.read().splitlines(): res += line res_json = json.loads(res) - # TODO Traitement du resultat pour garder l'essentiel ? + # TODO Traitement du resultat pour garder l'essentiel... return res_json @@ -73,7 +76,7 @@ def detect_os_version(ssh): dict_total = {} dict_total["kernel"] = res.split('#')[0] - # os + # os cmd = "cat /etc/os-release" stdin, stdout, stderr = ssh.exec_command(cmd) for line in stdout.read().splitlines(): diff --git a/app/storage.py b/app/storage.py new file mode 100644 index 0000000..dc5173e --- /dev/null +++ b/app/storage.py @@ -0,0 +1,78 @@ +# -*- coding: utf8 -*- +from __future__ import unicode_literals +__author__ = 'aguilbaud' + +import shelve +from datetime import datetime +from math import sqrt + + +def add_check(addr_host, name_part, val): + new_val = {"date": datetime.now()} + db = shelve.open('mum.db', writeback=True) + try: + if val >= db['hosts']['conf']['monitorig'][name_part]['minor_limit']: + new_val['state'] = 'warning' + elif val >= db['hosts']['conf']['monitorig'][name_part]['major_limit']: + new_val['state'] = 'danger' + else: + new_val['state'] = 'success' + previous_val = db['hosts'][addr_host]["monitoring"][name_part] + db['hosts'][addr_host]['monitoring'][name_part] = new_val + # now performing archiving + if db['hosts'][addr_host]['archive'].has_key(name_part): + db['hosts'][addr_host]['archive'][name_part] = update_stats(db['hosts'][addr_host]['archive'][name_part], val) + finally: + db.close() + + +# Updates calulated statistics once a new value is received +def update_stats(stats, val): + stats['nb_check'] += 1 + stats['total'] += val + if stats['min'] > val: + stats['min'] = val + if stats['max'] < val: + stats['max'] = val + # Compute linear regression + stats['lr'] += val * stats['nb_check'] + # Compute variance + stats['delta'] = val - stats['mean'] + stats['mean'] += stats['delta'] / stats['nb_check'] + stats['M2'] += stats['delta'] * (val - stats['mean']) + return stats + + +def get_mean(stats): + res = float('nan') + try: + res = stats['total'] / stats['nb_check'] + except ZeroDivisionError: + print "Division by 0 on get_mean(stats)" + return res + + +def get_standard_derivation(stats): + variance = stats['M2'] / max(1, stats['nb_check'] + 1) + res = sqrt(variance) + return res + + +def get_slope_of_linear_regression(stats): + res = float('nan') + try: + mX = (stats['nb_check'] + 1) / 2 + mY = stats['total'] / stats['nb_check'] + mX2 = (stats['nb_check'] + 1) * (2 * stats['nb_check'] + 1) / 6 + mXY = stats['lr'] / stats['nb_check'] + res = (mXY - mX * mY) / (mX2 - mX * mX) + except ZeroDivisionError: + print "Division by 0 on get_slope_of_linear_regression(stats)" + return res + +def save_detection(name_part, json_res): + db = shelve.open('mum.db', writeback=True) + try: + return + finally: + db.close() \ No newline at end of file diff --git a/bower.json b/bower.json index 8b8ed45..477f28e 100644 --- a/bower.json +++ b/bower.json @@ -3,6 +3,8 @@ "version": "0.0.1", "dependencies": { "bootstrap": "~3.2.0", - "angular-latest": "~1.3.9" + "angular-latest": "~1.3.9", + "angular": "~1.3.13", + "angular-toastr": "~0.5.2" } } diff --git a/requirements.txt b/requirements.txt index b689fc6..1545e2e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ bottle==0.12.7 pysnmp pexpect paramiko -bottle-websocket \ No newline at end of file +bottle-websocket +elasticsearch \ No newline at end of file diff --git a/static/css/dashboard.css b/static/css/dashboard.css new file mode 100644 index 0000000..c958c18 --- /dev/null +++ b/static/css/dashboard.css @@ -0,0 +1,121 @@ +/* + * Base structure + */ + +/* Move down content because we have a fixed navbar that is 50px tall */ +body { + padding-top: 50px; +} + + +/* + * Global add-ons + */ + +.sub-header { + padding-bottom: 10px; + border-bottom: 1px solid #eee; +} + +/* + * Top navigation + * Hide default border to remove 1px line. + */ +.navbar-fixed-top { + border: 0; +} + +/* + * Sidebar + */ + +/* Hide for mobile, show later */ +.sidebar { + display: none; +} +@media (min-width: 768px) { + .sidebar { + position: fixed; + top: 51px; + bottom: 0; + left: 0; + z-index: 1000; + display: block; + padding: 20px; + overflow-x: hidden; + overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */ + background-color: #f5f5f5; + border-right: 1px solid #eee; + } +} + +/* Sidebar navigation */ +.nav-sidebar { + margin-right: -21px; /* 20px padding + 1px border */ + margin-bottom: 20px; + margin-left: -20px; +} +.nav-sidebar > li > a { + padding-right: 20px; + padding-left: 20px; +} +.nav-sidebar > .active > a, +.nav-sidebar > .active > a:hover, +.nav-sidebar > .active > a:focus { + color: #fff; + background-color: #428bca; +} + + +/* + * Main content + */ + +.main { + padding: 20px; +} +@media (min-width: 768px) { + .main { + padding-right: 40px; + padding-left: 40px; + } +} +.main .page-header { + margin-top: 0; +} + + +/* + * Placeholder dashboard ideas + */ + +.placeholders { + margin-bottom: 30px; + text-align: center; +} +.placeholders h4 { + margin-bottom: 0; +} +.placeholder { + margin-bottom: 20px; +} +.placeholder img { + display: inline-block; + border-radius: 50%; +} + + +/* + * For multi-level select in notification menu + */ +.optionGroup +{ + font-weight:bold; + font-style:italic; +} + +.optionChild +{ + padding-left:15px; +} + diff --git a/static/css/signin.css b/static/css/signin.css new file mode 100644 index 0000000..995df48 --- /dev/null +++ b/static/css/signin.css @@ -0,0 +1,40 @@ +body { + padding-top: 40px; + padding-bottom: 40px; + background-color: #eee; +} + +.form-signin { + max-width: 330px; + padding: 15px; + margin: 0 auto; +} +.form-signin .form-signin-heading, +.form-signin .checkbox { + margin-bottom: 10px; +} +.form-signin .checkbox { + font-weight: normal; +} +.form-signin .form-control { + position: relative; + height: auto; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 10px; + font-size: 16px; +} +.form-signin .form-control:focus { + z-index: 2; +} +.form-signin input[type="email"] { + margin-bottom: -1px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.form-signin input[type="password"] { + margin-bottom: 10px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} diff --git a/static/js/controllers/detectCtrl.js b/static/js/controllers/detectCtrl.js index 6bd55aa..254e9c6 100644 --- a/static/js/controllers/detectCtrl.js +++ b/static/js/controllers/detectCtrl.js @@ -1,10 +1,12 @@ -var formExample = angular.module('formExample', []); +var formExample = angular.module('formExample', ['toastr']); -formExample.controller('ExampleController', ['$scope', '$http', '$interval', function($scope, $http, $interval) { +formExample.controller('ExampleController', ['$scope', 'toastr', '$http', '$interval', function($scope, toastr, $http, $interval) { $scope.master = {}; $scope.ip_range = "198.116.0.1-10" // la plage d'ip entree dans le champ $scope.state = ""; // l'etat general du scan en cours $scope.validated = false; // pour afficher ou non certaines parties de la page + $scope.scan_is_over = false; // pour afficher ou non certaines parties de la page + $scope.ip_scanned = {}; var ws = new WebSocket("ws://0.0.0.0:1337/websocket"); /*ws.onopen = function() { @@ -14,23 +16,57 @@ formExample.controller('ExampleController', ['$scope', '$http', '$interval', fun // actions effectuees lors de la reception d'un message via la websocket ws.onmessage = function (evt) { JSON.parse(evt.data, function (key, value) { - if(key == "state"){ - $scope.$apply(function(){ - $scope.state = value - }); - } - if(key == "error"){ - $scope.$apply(function(){ - $scope.state = "Erreur : " + value - }); + switch(parseInt(key)){ + case 20: // Success of a module execution + toastr.success(value, "Success on module execution"); + case 21: // Informations concerning one host + break; + case 22: // List of hosts under monitoring + break; + case 30: + toastr.info(value, "Current status is :"); + /* + $scope.$apply(function(){ + $scope.state = value + });*/ + break; + case 31: + params = value.split(','); + if(params[0]=='success'){ + $scope.pop_success("Success on " + params[1], params[2]); + } + else if(params[0] == 'warning'){ + $scope.pop_warning("Warning on " + params[1], params[2]); + } + else if(params[0] == 'danger'){ + $scope.pop_danger("Danger on "+ params[1], params[2]); + } + break; + case 40: + toastr.error(value, "Server error"); + break; + default: + break; } }); }; + $scope.pop_success = function(title, msg){ + toastr.success(msg, title); + }; + + $scope.pop_warning = function(title, msg){ + toastr.success(msg, title); + }; + + $scope.pop_danger = function(title, msg){ + toastr.error(msg, title); + }; + //lace la detection apres remplissage du champ et validation du formulaire $scope.post_val = function(){ - var request = '{"Sending_ip_range" : "' + $scope.ip_range + '"}'; + var request = '{"10" : "' + $scope.ip_range + '"}'; ws.send(request); } }]); diff --git a/static/js/controllers/settings_ctrl.js b/static/js/controllers/settings_ctrl.js new file mode 100644 index 0000000..3b9b5f0 --- /dev/null +++ b/static/js/controllers/settings_ctrl.js @@ -0,0 +1,8 @@ +var settingsModule = angular.module('appSettings', []); + +settingsModule.controller('ctrlSettings', function ($scope) { + $scope.cpu_warn=90; + $scope.cpu_danger=100; + $scope.drive_warn=90; + $scope.drive_danger=100; +}); \ No newline at end of file diff --git a/static/js/controllers/table_ctrl.js b/static/js/controllers/table_ctrl.js new file mode 100644 index 0000000..b515a37 --- /dev/null +++ b/static/js/controllers/table_ctrl.js @@ -0,0 +1,351 @@ +var tablemodule = angular.module('myModule', []); + + +tablemodule.controller('ctrlRead', function ($scope, $filter) { + + // init + $scope.sort = { + sortingOrder : 'id', + reverse : false + }; + + $scope.gap = 5; + + $scope.filteredItems = []; + $scope.groupedItems = []; + $scope.itemsPerPage = 25; + $scope.pagedItems = []; + $scope.currentPage = 0; + + $scope.addr_filter = ''; + $scope.name_filter = ''; + $scope.status_filter = ''; + $scope.group_filter = ''; + + $scope.items = [ + { + "addr":"192.168.74.1", + "name":"www.example.com", + "status":"success", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup1" + } + ], + "last_check":"14:51" + }, + { + "addr":"192.168.74.2", + "name":"www.example.com", + "status":"success", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup1" + } + ], + "last_check":"14:48" + }, + { + "addr":"192.168.74.3", + "name":"www.example.com", + "status":"success", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup1" + } + ], + "last_check":"14:51" + }, + { + "addr":"142.42.13.37", + "name":"www.nerd.org", + "status":"warning", + "group":[ + { + "name":"all" + } + ], + "last_check":"08:24" + }, + { + "addr":"135.47.86.11", + "name":"www.blabla.fr", + "status":"danger", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup2" + } + ], + "last_check":"12:18" + }, + { + "addr":"135.47.86.12", + "name":"www.blabla.fr", + "status":"success", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup2" + } + ], + "last_check":"12:20" + }, + { + "addr":"192.147.0.0", + "name":"", + "status":"warning", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup3" + } + ], + "last_check":"11:11" + }, + { + "addr":"192.147.0.1", + "name":"", + "status":"danger", + "group":[ + { + "name":"all" + }, + { + "name":"mygroup3" + } + ], + "last_check":"11:14" + } + +]; + $scope.grp = "all"; + + var searchMatch = function (haystack, needle) { + if (!needle) { + return true; + } + return haystack.toLowerCase().indexOf(needle.toLowerCase()) !== -1; + }; + + // init the filtered items + $scope.search = function () { + $scope.filteredItems = $filter('filter')($scope.items, function (item) { + for(var attr in item) { + if (searchMatch(item[attr], $scope.query)) + return true; + } + return false; + }); + // take care of the sorting order + if ($scope.sort.sortingOrder !== '') { + $scope.filteredItems = $filter('orderBy')($scope.filteredItems, $scope.sort.sortingOrder, $scope.sort.reverse); + } + $scope.currentPage = 0; + // now group by pages + $scope.groupToPages(); + }; + + + // calculate page in place + $scope.groupToPages = function () { + $scope.pagedItems = []; + + for (var i = 0; i < $scope.filteredItems.length; i++) { + if (i % $scope.itemsPerPage === 0) { + $scope.pagedItems[Math.floor(i / $scope.itemsPerPage)] = [ $scope.filteredItems[i] ]; + } else { + $scope.pagedItems[Math.floor(i / $scope.itemsPerPage)].push($scope.filteredItems[i]); + } + } + }; + + $scope.range = function (size,start, end) { + var ret = []; + console.log(size,start, end); + + if (size < end) { + end = size; + start = size-$scope.gap; + } + for (var i = start; i < end; i++) { + ret.push(i); + } + console.log(ret); + return ret; + }; + + $scope.prevPage = function () { + if ($scope.currentPage > 0) { + $scope.currentPage--; + } + }; + + $scope.nextPage = function () { + if ($scope.currentPage < $scope.pagedItems.length - 1) { + $scope.currentPage++; + } + }; + + $scope.setPage = function () { + $scope.currentPage = this.n; + }; + + // functions have been describe process the data for display + $scope.search(); + + // $scope.groupsByAddr = {} + + $scope.getGroupsByAddr = function(addr) { + res = "" + for(var i = 0; i<$scope.items.length; i++){ + if($scope.items[i].addr === addr){ + for(var j = 0; j<$scope.items[i].group.length; j++){ + res += $scope.items[i].group[j].name + " "; + } + } + } + return res; + }; + + $scope.allGroups = function(){ + var res = [] + for(var i = 0; i<$scope.items.length; i++){ + for(var j = 0; j<$scope.items[i].group.length; j++){ + res.push($scope.items[i].group[j].name); + } + } + return res; + }; + + /* + * Return a vector with the number of hosts with a status of : success, warning, danger + */ + $scope.stateNumber = function(){ + var res = [0,0,0]; + for(var i = 0; i<$scope.items.length; i++){ + if($scope.items[i].status === "success"){ + res[0]++; + } + if($scope.items[i].status === "warning"){ + res[1]++; + } + if($scope.items[i].status === "danger"){ + res[2]++; + } + } + return res; + }; + + $scope.checkAll = function(){ + if($scope.selectedAll){ + $scope.selectedAll = true; + } + else{ + $scope.selectedAll = false; + } + angular.forEach($scope.items, function(item){ + item.Selected = $scope.selectedAll; + }); + }; + +}); + + +tablemodule.$inject = ['$scope', '$filter']; + +tablemodule.directive("customSort", function() { +return { + restrict: 'A', + transclude: true, + scope: { + order: '=', + sort: '=' + }, + template : + ' <a ng-click="sort_by(order)" style="color: #555555;">'+ + ' <span ng-transclude></span>'+ + ' <i ng-class="selectedCls(order)"></i>'+ + '</a>', + link: function(scope) { + + // change sorting order + scope.sort_by = function(newSortingOrder) { + var sort = scope.sort; + + if (sort.sortingOrder == newSortingOrder){ + sort.reverse = !sort.reverse; + } + + sort.sortingOrder = newSortingOrder; + }; + + + scope.selectedCls = function(column) { + if(column == scope.sort.sortingOrder){ + return ('icon-chevron-' + ((scope.sort.reverse) ? 'down' : 'up')); + } + else{ + return'icon-sort' + } + }; + }// end link +} + + +}); + +// https://github.com/angular-ui/angular-ui-OLDREPO/blob/master/modules/filters... (MIT licence) +tablemodule.filter('unique', function () { + + return function (items, filterOn) { + + if (filterOn === false) { + return items; + } + + if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) { + var hashCheck = {}, newItems = []; + + var extractValueToCompare = function (item) { + if (angular.isObject(item) && angular.isString(filterOn)) { + return item[filterOn]; + } else { + return item; + } + }; + + angular.forEach(items, function (item) { + var valueToCheck, isDuplicate = false; + + for (var i = 0; i < newItems.length; i++) { + if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) { + isDuplicate = true; + break; + } + } + if (!isDuplicate) { + newItems.push(item); + } + + }); + items = newItems; + } + return items; + }; +}); \ No newline at end of file diff --git a/views/angular.html b/views/angular.html deleted file mode 100644 index 449a7dd..0000000 --- a/views/angular.html +++ /dev/null @@ -1,20 +0,0 @@ -<html lang="en" ng-app="myAppName"> -<head> - <meta charset="utf-8"> - <title>My HTML File</title> - <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"> - <script src="bower_components/angular/angular.js"></script> - <script src="static/js/controllers/app.js"></script> -</head> -<body> - <!-- Un premier contrôleur --> - <div ng-controller="MainCtrl"> - <ul> - - {{ text }} - - </ul> - </div> - -</body> -</html> diff --git a/views/dashboard.html b/views/dashboard.html new file mode 100644 index 0000000..8c6f056 --- /dev/null +++ b/views/dashboard.html @@ -0,0 +1,162 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=2"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Dashboard</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> + + <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> + <!--[if lt IE 9]><!-- + <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> + <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> + <![endif]--> + </head> + + <body ng-app="myModule" ng-controller="ctrlRead"> + + <nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : {{stateNumber()[0]}}</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : {{stateNumber()[1]}}</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : {{stateNumber()[2]}}</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> + </nav> + + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar sidebar-fixed-left"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Dashboard</h1> + <h2 class="sub-header">Hosts currently on monitoring</h2> + + <div class="row"> + <div class="col-xs-3"> + <label for="addr_f">Address filter</label> + <input class="form-control" type="text" id="addr_f" ng-model="addr_filter"> + </div> + <div class="col-xs-3"> + <label for="name_f">Name filter</label> + <input class="form-control" type="text" id="name_f" ng-model="name_filter"> + </div> + <div class="col-xs-2"> + <label for="status_f">Status filter</label> + <select class="form-control input-sm" id="status_f" ng-model="status_filter"> + <option></option> + <option>success</option> + <option>warning</option> + <option>danger</option> + </select> + </div> + <div class="col-xs-2"> + <label for="group_f">Group filter</label> + <select class="form-control input-sm" id="group_f" ng-model="group_filter"> + <option>all</option> + <option>mygroup1</option> + <option>mygroup2</option> + <option>mygroup3</option> + </select> + </div> + <table class="table table-condensed table-hover"> + <thead> + + <tr> + <th class="id" custom-sort order="'addr'" sort="sort">Address </th> + <th class="name" custom-sort order="'name'" sort="sort">Name </th> + <th class="description" custom-sort order="'status'" sort="sort">Status </th> + <th class="field3" custom-sort order="'group'" sort="sort">Group </th> + <th class="field4" custom-sort order="'last_check'" sort="sort">Last check </th> + </tr> + </thead> + + <!--<tfoot> === pour l'affichage du tableau par pages + <td colspan="6"> + <div class="pagination pull-right"> + <ul> + <li ng-class="{disabled: currentPage == 0}"> + <a href ng-click="prevPage()">« Prev</a> + </li> + + <li ng-repeat="n in range(pagedItems.length, currentPage, currentPage + gap) " + ng-class="{active: n == currentPage}" + ng-click="setPage()"> + <a href ng-bind="n + 1">1</a> + </li> + + <li ng-class="{disabled: (currentPage) == pagedItems.length - 1}"> + <a href ng-click="nextPage()">Next »</a> + </li> + </ul> + </div> + </td> + </tfoot> + + <pre>pagedItems.length: {{pagedItems.length|json}}</pre> + <pre>currentPage: {{currentPage|json}}</pre> + <pre>currentPage: {{sort|json}}</pre>--> + <tbody> + <tr ng-repeat="item in filteredItems | + 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.html">{{item.addr}}</a></td> + <td>{{item.name}}</td> + <td>{{item.status}}</td> + <td>{{getGroupsByAddr(item.addr)}}</td> + <td>{{item.last_check}}</td> + </tr> + </tbody> + </table> + </div> + + </div> + </div> + </div> + + <!-- Bootstrap core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> + </body> +</html> + diff --git a/views/groups.html b/views/groups.html new file mode 100644 index 0000000..62be2a4 --- /dev/null +++ b/views/groups.html @@ -0,0 +1,142 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Group manager</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> +</head> + +<body ng-app="myModule" ng-controller="ctrlRead"> + +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> +</nav> + +<div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Group manager</h1> + <div class="row"> + <div class="col-xs-3"> + <label for="grpoption">Your existing groups</label> + <form class="form-inline" id="grpoption"> + <select class="form-control" ng-model="grp" ng-options="item for item in allGroups() | unique:'group'"> + </select> + </form> + </div> + <div class="col-xs-3"> + <label for="addr_f">Address filter</label> + <input class="form-control" type="text" id="addr_f" ng-model="addr_filter"> + </div> + <div class="col-xs-3"> + <label for="name_f">Name filter</label> + <input class="form-control" type="text" id="name_f" ng-model="name_filter"> + </div> + <table class="table table-striped table-hover"> + <thead> + <tr> + <th>Address</th> + <th>Name</th> + <th>Groups</th> + <th><input type="checkbox" ng-model="selectedAll" ng-click="checkAll()"></th> + </tr> + </thead> + <tbody> + <tr ng-repeat="item in items | filter:{group:{name:grp}, addr:addr_filter, name:name_filter}"> + <td>{{item.addr}}</td> + <td>{{item.name}}</td> + <td>{{getGroupsByAddr(item.addr)}}</td> + <td> + <input type="checkbox" ng-model="item.Selected"/> + </td> + </tr> + </tbody> + </table> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal_add">Add selected to group...</button> + <button ng-show="grp != 'all' || ''" type="button" class="btn btn-danger">Remove selected from {{grp}}</button> + </div> + </div> +</div> + +<div class="modal fade" id="modal_add" tabindex="-1" role="dialog" aria-labelledby="modal_add_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_add_label">Add to group</h4> + </div> + + <div class="modal-body"> + <form> + <div class="form-group"> + <label for="list_grp">From an existing group</label> + <select class="form-control" id="list_grp" ng-model="selected_grp" ng-options= + "item for item in allGroups() | unique:'group'"> + </select> + <label for="grp_name">Or create a new group</label> + <input type="text" class="form-control" id="grp_name" placeholder="Group name"> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> +</div> +</div> + + <!-- Bootstrap core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> +</body> +</html> + diff --git a/views/hostpage.html b/views/hostpage.html new file mode 100644 index 0000000..b08b2fe --- /dev/null +++ b/views/hostpage.html @@ -0,0 +1,524 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Host details</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> + </head> + + <body> + + <nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> + </nav> + + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Current state of 192.168.74.1 <small>www.example.com</small></h1> + <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_block">Activate/Deactivate</button> + <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> + <table class="table table-condensed table-hover"> + <thead> + + <tr> + <th class="id" custom-sort order="'addr'" sort="sort">Part </th> + <th class="name" custom-sort order="'name'" sort="sort">Value </th> + <th class="description" custom-sort order="'status'" sort="sort">State </th> + <th class="field3" custom-sort order="'group'" sort="sort">Last check </th> + </tr> + </thead> + <tbody> + <tr class=success> + <td>HTTP</td> + <td>up</td> + <td>success</td> + <td>12:00</td> + <td><button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_conf"> + Configure + </button> + </td> + <td><button type="button" class="btn btn-info btn-xs"> + Check now + </button> + </td> + </tr> + <tr class=success> + <td>SMTP</td> + <td>up</td> + <td>success</td> + <td>12:04</td> + <td><button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_conf"> + Configure + </button> + </td> + <td><button type="button" class="btn btn-info btn-xs"> + Check now + </button> + </td> + </tr> + <tr class=success> + <td>CPU</td> + <td>28%</td> + <td>success</td> + <td>14:51</td> + <td><button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_conf"> + Configure + </button> + </td> + <td><button type="button" class="btn btn-info btn-xs"> + Check now + </button> + </td> + </tr> + <tr class=success> + <td>Drive</td> + <td>37% used</td> + <td>success</td> + <td>14:51</td> + <td><button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_conf"> + Configure + </button> + </td> + <td><button type="button" class="btn btn-info btn-xs"> + Check now + </button> + </td> + </tr> + </tbody> + </table> + <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingOne"> + <h4 class="panel-title"> + <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> + Detected configuration + </a> + </h4> + </div> + <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne"> + <div class="panel-body"> + <p>Date of this detection : Sat, 07 Feb 2015 12:00:00 </p> + <h2>Global informations</h2> + <table class="table table-bordered table-hover"> + <tr> + <td>addr</td> + <td>192.168.74.1</td> + </tr> + <tr> + <td>hostname</td> + <td>www.example.com</td> + </tr> + </table> + <h2>Open ports</h2> + <table class="table table-bordered table-hover"> + <tr> + <th>portid </th> + <th>portname </th> + </tr> + <tr> + <td>22</td> + <td>ssh</td> + </tr> + <tr> + <td>25</td> + <td>smtp</td> + </tr> + <tr> + <td>111</td> + <td>rpcbind</td> + </tr> + <tr> + <td>631</td> + <td>ipp</td> + </tr> + <tr> + <td>8080</td> + <td>http</td> + </tr> + </table> + <h2>Operating system</h2> + <table class="table table-bordered table-hover"> + <tr> + <td>os-name</td> + <td>Debian GNU/Linux</td> + </tr> + <tr> + <td>version</td> + <td>7 (wheezy)</td> + </tr> + <tr> + <td>kernel</td> + <td>Linux version 3.16.0-0.bpo.4-amd64 (debian-kernel@lists.debian.org) (gcc version 4.6.3 (Debian 4.6.3-14) )</td> + </tr> + </table> + </div> + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingTwo"> + <h4 class="panel-title"> + <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo"> + Custom informations + </a> + </h4> + </div> + <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo"> + <div class="panel-body"> + <label for="custom_info">Add any information here :</label> + <textarea class="form-control" rows="3" id="custom_info"></textarea> + <button type="button" class="btn btn-info btn-xs">Save</button> + </div> + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingThree"> + <h4 class="panel-title"> + <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="false" aria-controls="collapseThree"> + Interventions done + </a> + </h4> + </div> + <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree"> + <div class="panel-body"> + <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_interv">Add a new intervention</button> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Date </th> + <th>Person </th> + <th>Details </th> + </tr> + </thead> + <tbody> + <tr> + <td>Mon, 01 Feb 2015 10:01:57</td> + <td>J.C.</td> + <td>Package update.</td> + </tr> + <tr> + <td>Thu, 11 Dec 2014 16:54:17</td> + <td>G.G.</td> + <td>Database backup.</td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + + </div> + </div> + </div> + + <div class="modal fade" id="modal_conf" tabindex="-1" role="dialog" aria-labelledby="modal_conf_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_conf_label">Configure</h4> + </div> + <div class="modal-body"> + <form> + <div class="form-group"> + <h3>HTTP</h3> + <label for="http_freq">Frequency check</label> + <select type="http_freq" class="form-control" id="http_freq"> + <option>Every minute</option> + <option selected>Every hour (default)</option> + <option>Every day</option> + </select> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="modal_interv" tabindex="-1" role="dialog" aria-labelledby="modal_interv_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_interv_label">Add an intervention</h4> + </div> + <div class="modal-body"> + <form> + <div class="form-group"> + <div class="row"> + <div class="col-xs-4"> + <label for="username">Person</label> + <input type="text" class="form-control" id="username" placeholder="G.G."> + </div> + <div class="col-xs-4"> + <label for="date">Date</label> + <input type="date" class="form-control" id="date" placeholder="2015-02-11"> + </div> + <div class="col-xs-4"> + <label for="date">Time</label> + <input type="time" class="form-control" id="time" placeholder="16:28:00"> + </div> + </div> + <label for="interv_detail">Details of this intervention</label> + <textarea class="form-control" rows="3" id="interv_detail"></textarea> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="modal_conn" tabindex="-1" role="dialog" aria-labelledby="modal_conn_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_conn_label">Connection configuration</h4> + </div> + <div class="modal-body"> + <form> + <div class="form-group"> + <h3>Choose the priority of each avaliable connection</h3> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Protocol </th> + <th>Priority </th> + <th>Options </th> + </tr> + </thead> + <tbody> + <tr> + <td>SSH</td> + <td><input type="number" min="0" placeholder=1></td> + <td> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal_conf_conn">Advanced configuration</button> + <button type="button" class="btn btn-success">Test</button> + </td> + + </tr> + <tr> + <td>SNMP</td> + <td><input type="number" min="0" placeholder=0 disabled></td> + <td> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal_conf_conn">Advanced configuration</button> + <button type="button" class="btn btn-success">Test</button> + </td> + + </tr> + <tr> + <td>Nagios</td> + <td><input type="number" min="0" placeholder=0 disabled></td> + <td> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#modal_conf_conn">Advanced configuration</button> + <button type="button" class="btn btn-success">Test</button> + </td> + </tr> + </tbody> + </table> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> + </div> + + <div class="modal fade bs-example-modal-lg" id="modal_conf_conn" tabindex="-1" role="dialog" aria-labelledby="modal_conf_conn_label" aria-hidden="true"> + <div class="modal-dialog modal-lg"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_conf_conn_label">Advanced settings for SSH</h4> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-xs-2"> + <label for="port">Port used</label> + <input type="number" id="port" min="0" placeholder="22"> + </div> + </div> + <div class="row"> + <div class="col-xs-3"> + <label for="usrname">Login</label> + <input type="text" id="usrname" placeholder="mylogin"> + </div> + </div> + <div class="row"> + <div class="col-xs-3"> + <label for="publickey">Public key</label> + <select class="form-control" id="publickey"> + <option>mykey1</option> + <option>mykey2</option> + </select> + </div> + <button type="button" class="btn btn-primary btn-xs">Add public key</button> + <button type="button" class="btn btn-danger btn-xs">Remove selected</button> + </div> + <div class="row"> + <div class="col-xs-3"> + <label for="privatekey">Private key</label> + <select class="form-control" id="privatekey"> + <option>mypkey1</option> + <option>mypkey2</option> + </select> + </div> + <button type="button" class="btn btn-primary btn-xs">Add private key</button> + <button type="button" class="btn btn-danger btn-xs">Remove selected</button> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="modal_block" tabindex="-1" role="dialog" aria-labelledby="modal_block_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_block_label">Activate/Deactivate monitoring blocks</h4> + </div> + <div class="modal-body"> + <form> + <div class="form-group"> + <h3>Network</h3> + <button type="button" class="btn btn-defaule">Select all</button> + <button type="button" class="btn btn-defaule">Select none</button> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Part </th> + <th>Activated </th> + </tr> + </thead> + <tbody> + <tr> + <td>HTTP</td> + <td><input type="checkbox" value="http" checked></td> + </tr> + <tr> + <td>SMTP</td> + <td><input type="checkbox" value="smtp" checked></td> + </tr> + </tbody> + </table> + <h3>Hardware</h3> + <button type="button" class="btn btn-defaule">Select all</button> + <button type="button" class="btn btn-defaule">Select none</button> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Part </th> + <th>Activated </th> + </tr> + </thead> + <tbody> + <tr> + <td>CPU</td> + <td><input type="checkbox" value="http" checked></td> + </tr> + <tr> + <td>Drive</td> + <td><input type="checkbox" value="smtp" checked></td> + </tr> + </tbody> + </table> + <h3>Software</h3> + <button type="button" class="btn btn-defaule">Select all</button> + <button type="button" class="btn btn-defaule">Select none</button> + <table class="table table-bordered table-hover"> + <thead> + <tr> + <th>Part </th> + <th>Activated </th> + </tr> + </thead> + <tbody> + <tr> + <td>Packages updated</td> + <td><input type="checkbox" value="http"></td> + </tr> + </tbody> + </table> + </div> + </form> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> + </div> + </div> + + <!-- Bootstrap core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> + </body> +</html> + diff --git a/views/index.html b/views/index.html index 0c276a6..adb8536 100644 --- a/views/index.html +++ b/views/index.html @@ -10,11 +10,14 @@ <title>Mum (Machines under monitoring)</title> <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script> - <script src="bower_components/angular/angular.js"></script> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/angular/angular.min.js"></script> + <script src="bower_components/angular-toastr/dist/angular-toastr.min.js"></script> <script src="static/js/controllers/detectCtrl.js"></script> - <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" media="screen"> - <link href="static/css/main.css" rel="stylesheet" media="screen"> + <link href="bower_components/angular-toastr/dist/angular-toastr.min.css" rel="stylesheet"/> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" media="screen"/> + <link href="static/css/main.css" rel="stylesheet" media="screen"/> </head> <body ng-app="formExample"> @@ -24,9 +27,16 @@ Plage d'IP à scanner (exemple : 198.116.0.1-10) : <input name="ip_range" ng-model="ip_range" /> <input value="Valider" type="submit" ng-click="validated = true"/> </div> - <div ng-show="validated == true"> - <p>{{state}}</p> + <!-- + <div ng-show="scan_is_over == true"> + <p> + Voici les résultats obtenus : + </p> + <ul> + <li ng-repeat="addr_ip in ip_scanned">{{addr_ip.ip}}</li> + </ul> </div> + --> </form> </div> diff --git a/views/notifications.html b/views/notifications.html new file mode 100644 index 0000000..0cc69dd --- /dev/null +++ b/views/notifications.html @@ -0,0 +1,247 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Notifications manager</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> +</head> + +<body> + +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> +</nav> + +<div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Who to notify?</h1> + <!--<h2 class="sub-header">They will be applied on each new host you will add.</h2>--> + <form> + <label for="grp_choice">Select one host or one group :</label> + <select class="form-control" id="grp_choice"> + <option value="142.42.13.37" class="optionChild">142.42.13.37 www.nerd.org</option> + <option value="mygroup1" class="optionGroup">mygroup1</option> + <option value="192.168.74.1" class="optionChild">192.168.74.1 www.example.com</option> + <option value="192.168.74.2" class="optionChild">192.168.74.2 www.example.com</option> + <option value="192.168.74.3" class="optionChild">192.168.74.3 www.example.com</option> + <option value="mygroup2" class="optionGroup">mygroup2</option> + <option value="135.47.86.11" class="optionChild">135.47.86.11 www.blabla.fr</option> + <option value="135.47.86.12" class="optionChild">135.47.86.12 www.blabla.fr</option> + <option value="mygroup3" class="optionGroup">mygroup3</option> + <option value="192.147.0.0" class="optionChild">192.147.0.0</option> + <option value="192.147.0.1" class="optionChild">192.147.0.1</option> + </select> + + </form> + <p>Check the box if you want the user to be notified by the correspondant service.</p> + <p>The value represents the numbers of notifications that should occure since the last login of the user.</p> + <p>The notification will be sent to the user, by this service, once this value is reached.</p> + <table class="table table-bordered"> + <thead> + <tr> + <th>User <button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#modal_add">Add...</button></th> + <th>Notification service </th> + <th>Minor notifications</th> + <th>Major notifications</th> + </tr> + </thead> + <tbody> + <tr> + <td rowspan="3">G.G.</td> + <td>Browser</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcbrowsermincheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcbrowserminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcbrowsermajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcbrowsermajnb" placeholder="1"> + </div> + </td> + </tr> + <tr> + <td>E-mail</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcmailmincheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcmailminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcmailmajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcmailmajnb" placeholder="1"> + </div> + </td> + </tr> + <tr> + <td>SMS</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcsmsmincheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcsmsminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="jcsmsmajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="jcsmsmajnb" placeholder="1"> + </div> + </td> + </tr> + <tr> + <td rowspan="3">J.C.</td> + <td>Browser</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggbrowserminchecj"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggbrowserminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggbrowsermajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggbrowsermajnb" placeholder="1"> + </div> + </td> + </tr> + <tr> + <td>E-mail</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggmailmincheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggmailminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggmailmajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggmailmajnb" placeholder="1"> + </div> + </td> + </tr> + <tr> + <td>SMS</td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggsmsmincheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggsmsminnb" placeholder="1"> + </div> + </td> + <td> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" aria-label="ggsmsmajcheck"> + </span> + <input type="number" min="1" class="form-control" aria-label="ggsmsmajnb" placeholder="1"> + </div> + </td> + </tr> + </tbody> + </table> + <button type="button" class="btn btn-default">Discard changes</button> + <button type="button" class="btn btn-primary">Save changes</button> + </div> + </div> +</div> + +<div class="modal fade" id="modal_add" tabindex="-1" role="dialog" aria-labelledby="modal_add_label" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="modal_add_label">Add users to this group/host</h4> + </div> + <div class="modal-body"> + <select multiple class="form-control"> + <option>D.D.</option> + <option>J.D.</option> + <option>X.R.</option> + </select> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + <button type="button" class="btn btn-primary">Add selected</button> + </div> + </div> + </div> +</div> +<!-- Bootstrap core JavaScript +================================================== --> +<!-- Placed at the end of the document so the pages load faster --> +<script src="bower_components/jquery/dist/jquery.min.js"></script> +<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> +</body> +</html> + diff --git a/views/profile.html b/views/profile.html new file mode 100644 index 0000000..32e370d --- /dev/null +++ b/views/profile.html @@ -0,0 +1,187 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Settings</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> +</head> + +<body> + +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> +</nav> + +<div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Your account</h1> + <!--<h2 class="sub-header">They will be applied on each new host you will add.</h2>--> + <form> + <div class="row"> + <h3>Personal informations</h3> + <div class="col-xs-3"> + <label for="username">Username</label> + <input type="username" class="form-control" id="username" placeholder="Username"> + </div> + <div class="row"></div> + <div class="col-xs-3"> + <label for="pswd">Change password</label> + <input type="password" class="form-control" id="pswd" placeholder="New password"> + </div> + <div class="col-xs-3"> + <label for="pswd2">Repeat new password</label> + <input type="password" class="form-control" id="pswd2" placeholder="Repeat new password"> + </div> + <div class="row"></div> + <div class="col-xs-4"> + <label for="mail">Email address</label> + <input type="email" class="form-control" id="mail" placeholder="Enter email"> + </div> + <div class="row"></div> + <div class="col-xs-4"> + <label for="cellphone">SMS URL</label> + <input type="email" class="form-control" id="cellphone"> + </div> + </div> + <h3>Preferences</h3> + + <div class="checkbox"> + <label for="minornotif">Send minor notifications by :</label> + <label> + <input type="checkbox" value="" id="minornotif"> + Browser notification + </label> + <label> + <input type="checkbox" value=""> + E-mail + </label> + <label> + <input type="checkbox" value=""> + SMS + </label> + </div> + + <div class="checkbox"> + <label for="majornotif">Send major notifications by :</label> + <label> + <input type="checkbox" value="" id="majornotif"> + Browser notification + </label> + <label> + <input type="checkbox" value=""> + E-mail + </label> + <label> + <input type="checkbox" value=""> + SMS + </label> + </div> + + <button type="button" class="btn btn-primary">Save changes</button> + + </form> + <h3>Summary of notification subscriptions</h3> + <p>Number of notifications between your last login</p> + <table class="table table-hover"> + <thead> + <tr> + <th>Host/Group</th> + <th>Notification service</th> + <th>Minor</th> + <th>Major</th> + </tr> + </thead> + <tbody> + <tr> + <td rowspan="2">mygroup2</td> + <td>Browser</td> + <td class="success">1</td> + <td class="success">1</td> + </tr> + <tr> + <td>E-mail</td> + <td></td> + <td class="success">3</td> + </tr> + <tr> + <td>142.42.13.37</td> + <td>E-mail</td> + <td class="success">3</td> + <td class="success">1</td> + </tr> + <tr> + <td rowspan="3">192.168.74.1</td> + <td>Browser</td> + <td class="success">1</td> + <td class="success">1</td> + </tr> + <tr> + <td>E-mail</td> + <td></td> + <td class="success">3</td> + </tr> + <tr> + <td>SMS</td> + <td></td> + <td class="success">5</td> + </tr> + </tbody> + </table> + </div> + </div> +</div> + +<!-- Bootstrap core JavaScript +================================================== --> +<!-- Placed at the end of the document so the pages load faster --> +<script src="bower_components/jquery/dist/jquery.min.js"></script> +<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> +</body> +</html> + diff --git a/views/scan.html b/views/scan.html new file mode 100644 index 0000000..5c8da50 --- /dev/null +++ b/views/scan.html @@ -0,0 +1,80 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : New scan</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> + </head> + + <body> + + <nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> + </nav> + + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Scan for new machines</h1> + <form class="form-inline"> + <label for="input_ip_range">IP range to scan (example : 198.116.0.1-10)</label> + <input type="ip_range" class="form-control" id="input_ip_range" placeholder="198.116.0.1-10"/> + <button type="submit" class="btn btn-primary">Scan now</button> + </form> + </div> + </div> + </div> + + <!-- Bootstrap core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> + </body> +</html> + diff --git a/views/settings.html b/views/settings.html new file mode 100644 index 0000000..7e86be7 --- /dev/null +++ b/views/settings.html @@ -0,0 +1,216 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Settings</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/settings_ctrl.js"></script> + </head> + + <body ng-app="appSettings" ng-controller="ctrlSettings"> + + <nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> + </nav> + + <div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Configure the default settings</h1> + <!--<h2 class="sub-header">They will be applied on each new host you will add.</h2>--> + <form> + <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true"> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingOne"> + <h4 class="panel-title"> + <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="false" aria-controls="collapseOne"> + Hardware + </a> + </h4> + </div> + <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne"> + <div class="panel-body"> + <h3>CPU</h3> + <div class="row"> + <div class="col-xs-2"> + <label for="cpu_freq">Frequency check</label> + <input type="text" class="form-control" id="cpu_freq" placeholder="d:hh:mm"> + </div> + <div class="col-xs-4"> + <label for="cpu_val1">Minor notification at {{cpu_warn}}% of charge</label> + <input type="range" name="cpu_warn" min="0" max="99" id="cpu_val1" ng-model="cpu_warn"> + </div> + <div class="col-xs-4"> + <label for="cpu_val2">Major notification at {{cpu_danger}}% of charge</label> + <input type="range" name="cpu_danger" min="{{cpu_warn}}" max="100" id="cpu_val2" ng-model="cpu_danger"> + </div> + </div> + <h3>Drive</h3> + <div class="row"> + <div class="col-xs-2"> + <label for="drive_freq">Frequency check</label> + <input type="text" class="form-control" id="drive_freq" placeholder="d:hh:mm"> + </div> + <div class="col-xs-4"> + <label for="drive_val1">Minor notification at {{drive_warn}}% of charge</label> + <input type="range" name="cpu_warn" min="0" max="99" id="drive_val1" ng-model="drive_warn"> + </div> + <div class="col-xs-4"> + <label for="drive_val2">Major notification at {{drive_danger}}% of charge</label> + <input type="range" name="drive_danger" min="{{drive_warn}}" max="100" id="drive_val2" ng-model="drive_danger"> + </div> + </div> + </div> + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingTwo"> + <h4 class="panel-title"> + <a data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="true" aria-controls="collapseTwo"> + Network + </a> + </h4> + </div> + <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo"> + <div class="panel-body"> + <h3>HTTP</h3> + <div class="row"> + <div class="col-xs-2"> + <label for="http_freq">Frequency check</label> + <input type="text" class="form-control" id="http_freq" placeholder="d:hh:mm"> + </div> + <div class="col-xs-3"> + <label for="http_crit_1">If down, send a </label> + <div class="radio"> + <label> + <input type="radio" name="http_crit" id="http_crit_1" value="warning" checked> + minor notification + </label> + </div> + <div class="radio"> + <label> + <input type="radio" name="http_crit" id="http_crit_2" value="danger"> + major notification + </label> + </div> + </div> + </div> + + + <h3>SMTP</h3> + <div class="row"> + <div class="col-xs-2"> + <label for="smtp_freq">Frequency check</label> + <input type="text" class="form-control" id="smtp_freq" placeholder="d:hh:mm"> + </div> + <div class="col-xs-3"> + <label for="smtp_crit_1">If down, send a </label> + <div class="radio"> + <label> + <input type="radio" name="smtp_crit" id="smtp_crit_1" value="warning" checked> + minor notification + </label> + </div> + <div class="radio"> + <label> + <input type="radio" name="smtp_crit" id="smtp_crit_2" value="danger"> + major notification + </label> + </div> + </div> + </div> + </div> + + + </div> + </div> + + <div class="panel panel-default"> + <div class="panel-heading" role="tab" id="headingThree"> + <h4 class="panel-title"> + <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree" aria-expanded="true" aria-controls="collapseThree"> + Software + </a> + </h4> + </div> + <div id="collapseThree" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingThree"> + <div class="panel-body"> + <h3>Packages updated</h3> + <div class="row"> + <div class="col-xs-2"> + <label for="pack_freq">Frequency check</label> + <input type="text" class="form-control" id="pack_freq" placeholder="d:hh:mm"> + </div> + <div class="col-xs-4"> + <label for="min_pack">Minor notif at (non updated)</label> + <input type="number" class="form-control" id="min_pack" min="0" placeholder="5"> + </div> + <div class="col-xs-4"> + <label for="maj_pack">Major notif at (non updated)</label> + <input type="number" class="form-control" id="maj_pack" min="0" placeholder="20"> + </div> + </div> + </div> + </div> + </div> + </div> + <button type="button" class="btn btn-default">Discard changes</button> + <button type="button" class="btn btn-primary">Save changes</button> + </form> + + </div> + </div> + </div> + + <!-- Bootstrap core JavaScript + ================================================== --> + <!-- Placed at the end of the document so the pages load faster --> + <script src="bower_components/jquery/dist/jquery.min.js"></script> + <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> + </body> +</html> + diff --git a/views/signin.html b/views/signin.html new file mode 100644 index 0000000..a86d7b9 --- /dev/null +++ b/views/signin.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="../../favicon.ico"> + + <title>Signin Template for Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/signin.css" rel="stylesheet"> + +</head> + +<body> + +<div class="container"> + + <form class="form-signin" action="dashboard.html"> + <h1>Welcome to Mum!</h1> + <h2 class="form-signin-heading">Please sign in</h2> + <label for="inputEmail" class="sr-only">Email address</label> + <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus> + <label for="inputPassword" class="sr-only">Password</label> + <input type="password" id="inputPassword" class="form-control" placeholder="Password" required> + <div class="checkbox"> + <label> + <input type="checkbox" value="remember-me"> Remember me + </label> + </div> + <button class="btn btn-lg btn-primary btn-block">Sign in</button> + </form> + +</div> <!-- /container --> + +</body> +</html> diff --git a/views/stats.html b/views/stats.html new file mode 100644 index 0000000..c93db8e --- /dev/null +++ b/views/stats.html @@ -0,0 +1,97 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Statistics</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> +</head> + +<body> + +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> +</nav> + +<div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> + <h1 class="page-header">Statistics</h1> + + <div class="row placeholders"> + <div class="col-xs-6 col-sm-3 placeholder"> + <img src="data/index.svg" class="img-responsive" alt="Generic placeholder thumbnail"> + <h4>Label</h4> + <span class="text-muted">Something else</span> + </div> + <div class="col-xs-6 col-sm-3 placeholder"> + <img src="data/index.svg" class="img-responsive" alt="Generic placeholder thumbnail"> + <h4>Label</h4> + <span class="text-muted">Something else</span> + </div> + <div class="col-xs-6 col-sm-3 placeholder"> + <img src="data/index.svg" class="img-responsive" alt="Generic placeholder thumbnail"> + <h4>Label</h4> + <span class="text-muted">Something else</span> + </div> + <div class="col-xs-6 col-sm-3 placeholder"> + <img src="data/index.svg" class="img-responsive" alt="Generic placeholder thumbnail"> + <h4>Label</h4> + <span class="text-muted">Something else</span> + </div> + </div> + </div> + </div> +</div> + +<!-- Bootstrap core JavaScript +================================================== --> +<!-- Placed at the end of the document so the pages load faster --> +<script src="bower_components/jquery/dist/jquery.min.js"></script> +<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> +</body> +</html> diff --git a/views/users.html b/views/users.html new file mode 100644 index 0000000..aa17df7 --- /dev/null +++ b/views/users.html @@ -0,0 +1,94 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="description" content=""> + <meta name="author" content=""> + <link rel="icon" href="favicon.ico"> + + <title>Mum : Users</title> + + <!-- Bootstrap core CSS --> + <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="static/css/dashboard.css" rel="stylesheet"> + + <script src="bower_components/angular/angular.min.js"></script> + + <script src="static/js/controllers/table_ctrl.js"></script> +</head> + +<body> + +<nav class="navbar navbar-inverse navbar-fixed-top"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="dashboard.html">Mum</a> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:green">OK : 4</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:orange">Warning : 2</a></p> + <p class="navbar-text navbar-left"><a href="dashboard.html" style="color:red">KO : 2</a></p> + </div> + <div id="navbar" class="navbar-collapse collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="profile.html">Profile</a></li> + <li><a href="signin.html">Logout</a></li> + </ul> + </div> + </div> +</nav> + +<div class="container-fluid"> + <div class="row"> + <div class="col-sm-3 col-md-2 sidebar"> + <ul class="nav nav-sidebar"> + <li><a href="dashboard.html">Dashboard</a></li> + <li><a href="scan.html">Scan for new machines</a></li> + <li><a href="groups.html">Manage your groups</a></li> + <li><a href="settings.html">Check the default settings</a></li> + <li><a href="users.html">Users</a></li> + <li><a href="notifications.html">Notification parameters</a></li> + <li><a href="stats.html">See the statistics</a></li> + </ul> + </div> + <div class="col-md-offset-2 main"> + <h1 class="page-header">Users</h1> + <div class="row"> + <div class="col-xs-4"> + <label for="usrlist">Registered users</label> + <select class="form-control" id="usrlist"> + <option>D.D.</option> + <option>G.G.</option> + <option>J.C.</option> + <option>J.D.</option> + <option>X.R.</option> + </select> + </div> + </div> + <div class="row"> + <div class="col-xs-4"> + <button type="button" class="btn btn-primary btn-xs" data-toggle="popover" + data-placement="bottom" title="Add user..." data-content="ger">Add user</button> + <button type="button" class="btn btn-danger btn-xs">Remove selected</button> + </div> + </div> + </div> + </div> +</div> + +<!-- Bootstrap core JavaScript +================================================== --> +<!-- Placed at the end of the document so the pages load faster --> +<script src="bower_components/jquery/dist/jquery.min.js"></script> +<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> +</body> +</html> + -- 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 6c21b415ad9507b1566b7a7961139806bedd490f Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 11:28:31 2015 +0100 scan nmap sauvegardé dans bdd Shelve --- app/app.py | 6 +- app/detection_modules/nagios_detection.py | 1 - app/detection_modules/nmap_detection.py | 152 --------------------- app/detection_modules/snmp_detection.py | 1 - app/detection_modules/ssh_detection.py | 103 -------------- app/{detection_modules => modules}/__init__.py | 0 app/{ => modules}/storage.py | 28 ++++ .../storage_module}/__init__.py | 0 requirements.txt | 3 +- static/js/controllers/detectCtrl.js | 4 +- views/index.html | 4 +- views/scan.html | 11 +- 12 files changed, 42 insertions(+), 271 deletions(-) diff --git a/app/app.py b/app/app.py index 43532f9..29196b2 100755 --- a/app/app.py +++ b/app/app.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals __author__ = 'aguilbaud' from bottle import * -from detection_modules.nmap_detection import check_ip_range, get_scanned_ip +from modules.detection_modules import nmap_detection from bottle_websocket import GeventWebSocketServer from bottle_websocket import websocket import json @@ -19,10 +19,10 @@ class ThreadDetect(threading.Thread): def run(self): req = {} - check_ip_range(self.ip_range, self.ws) + nmap_detection.check_ip_range(self.ip_range, self.ws) #print "scanned ip :" #print get_scanned_ip() - req["20"] = get_scanned_ip() + req["20"] = nmap_detection.get_scanned_ip() self.ws.send(json.dumps(req)) diff --git a/app/detection_modules/nagios_detection.py b/app/detection_modules/nagios_detection.py deleted file mode 100644 index fcb43f2..0000000 --- a/app/detection_modules/nagios_detection.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'aguilbaud' diff --git a/app/detection_modules/nmap_detection.py b/app/detection_modules/nmap_detection.py deleted file mode 100644 index e8adecf..0000000 --- a/app/detection_modules/nmap_detection.py +++ /dev/null @@ -1,152 +0,0 @@ -# -*- coding: utf8 -*- -from __future__ import unicode_literals -__author__ = 'aguilbaud' - -from xml.dom import minidom -import pexpect -import json - -scanned_ip = {} - - -def get_scanned_ip(): - global scanned_ip - return json.dumps(scanned_ip) - - -# fonction qui permet de decomposer les differentes plages d'ip -# lance la detection nmap pour chacune des ip comprises dans cette plage -# NB : il est possible de lancer nmap directement sur la plage, mais il est alors difficile de determiner l'état -# du scan. De plus, si la plage d'ip est grande, l'exécution sera bien plus longue et tous les résultats -# seront obtenus d'un coup à la fin. -def check_ip_range(ip_range, ws): - # separation des 4 octets - range_byte_1 = ip_range.split('.')[0] - range_byte_2 = ip_range.split('.')[1] - range_byte_3 = ip_range.split('.')[2] - range_byte_4 = ip_range.split('.')[3] - - # separation des plages eventuelles - split_byte_1 = range_byte_1.split('-') - split_byte_2 = range_byte_2.split('-') - split_byte_3 = range_byte_3.split('-') - split_byte_4 = range_byte_4.split('-') - - # si aucune plage n'est indiquee, on cree une plage de meme valeur - if len(split_byte_1) == 1: - split_byte_1.append(split_byte_1[0]) - # verification que les nombres sont ordonnes correctement - # et que les valeurs entrees sont inferieures a 255 - split_byte_1 = check_order_and_under_255(split_byte_1) - - # idem pour le deuxieme octet - if len(split_byte_2) == 1: - split_byte_2.append(split_byte_2[0]) - split_byte_2 = check_order_and_under_255(split_byte_2) - - # idem pour le troisieme octet - if len(split_byte_3) == 1: - split_byte_3.append(split_byte_3[0]) - split_byte_3 = check_order_and_under_255(split_byte_3) - - # idem pour le quatrieme octet - if len(split_byte_4) == 1: - split_byte_4.append(split_byte_4[0]) - split_byte_4 = check_order_and_under_255(split_byte_4) - - # il est possible d'ajouter ici une condition pour verifier que l'utilisateur - # n'ait pas entre une plage d'IP trop grande - - # pour toutes les plages dans l'ordre croissant, en partant du dernier octet - for byte_1 in range(int(split_byte_1[0]), int(split_byte_1[1]) + 1): - for byte_2 in range(int(split_byte_2[0]), int(split_byte_2[1]) + 1): - for byte_3 in range(int(split_byte_3[0]), int(split_byte_3[1]) + 1): - for byte_4 in range(int(split_byte_4[0]), int(split_byte_4[1]) + 1): - launch_detection(byte_1, byte_2, byte_3, byte_4, ws) - - -# vérifie que la plage de données entrée est dans l'ordre croissant -# et que ses valeurs sont inferieures à 255 -# si ce n'est pas le cas, retourne le tableau trié et/ou avec les valeurs capées à 255 -def check_order_and_under_255(tab_val): - if int(tab_val[0]) > 255 : - tab_val[0] = '255' - if int(tab_val[1]) > 255 : - tab_val[1] = '255' - if int(tab_val[0]) > int(tab_val[1]): - tmp = tab_val[1] - tab_val[1] = tab_val[0] - tab_val[0] = tmp - return tab_val - - -# lance la detection a l'aide de nmap sur l'ip representee par les 4 octets passes en parametres -def launch_detection(byte_1, byte_2, byte_3, byte_4, ws): - req = {} - ip = str(byte_1) + '.' + str(byte_2) + '.' + str(byte_3) + '.' + str(byte_4) - req["30"] = "Scan de l'IP " + ip + " en cours..." - ws.send(json.dumps(req)) - child = pexpect.spawn('nmap', ['-A', ip, '-oX', 'res.xml']) - res = '' - # ici : possibilite de verifier l'avancement du scan, si option verbose (-v3) activee dans la commande nmap - try: - while child.isalive(): - child.expect('Completed', timeout=None) - res += child.before + '<br/>' - except pexpect.EOF: - res += ' A FINI' - parse_res(ip) - except pexpect.TIMEOUT: - res += ' TIMEOUT' - return res - - -# parse le resultat xml de nmap pour ne conserver que les valeurs interssantes -# envoie directement le resultat sur le service ElasticSearch -def parse_res(ip): - global scanned_ip - # Ouverture du fichier xml avec le parseur minidom - root = minidom.parse("res.xml") - collection = root.documentElement - - # Recuperer tous les <host> de la collection - hosts = collection.getElementsByTagName("host") - - # Recuperation des noeuds de chaque <host> et affichage de leur attributss - # JSON = liste de dictionnaires - for host in hosts: - status = host.getElementsByTagName('status')[0] - address = host.getElementsByTagName('address')[0] - - dict_host = {} - dict_host['addr'] = address.getAttribute('addr') - dict_host['date'] = host.getAttribute('endtime') - dict_host['state'] = status.getAttribute('state') - dict_host['os'] = 'unknown' # par defaut - - hostnames_elem = host.getElementsByTagName('hostnames')[0] - hostnames = hostnames_elem.getElementsByTagName('hostname') - for hostname in hostnames: - dict_host['hostname'] = hostname.getAttribute("name") - - ports_elem = host.getElementsByTagName('ports')[0] - ports = ports_elem.getElementsByTagName('port') - list_dict_port = [] - for port in ports: - dict_port = {} - state = port.getElementsByTagName('state')[0] - service = port.getElementsByTagName('service')[0] - if service.hasAttribute("ostype"): - dict_host['os'] = service.getAttribute("ostype") - if state.getAttribute('state') == 'open': - dict_port['portid'] = port.getAttribute('portid') - dict_port['portname'] = service.getAttribute('name') - # Ajouter d'autres infos ? - list_dict_port.append(dict_port) - dict_host['openports'] = list_dict_port - # sauvegarde de l'host dans la base elasticsearch avec pour ID son IP - pexpect.run("curl -XPUT 'localhost:9200/host/external/" + dict_host['addr'] + "' -d '" + - json.dumps(dict_host) + "'") - pexpect.run("rm -f res.xml") - #pexpect.run('curl -XPUT \'localhost:9200/saved_hosts' - scanned_ip[ip] = "localhost:9200/host/external/" + ip \ No newline at end of file diff --git a/app/detection_modules/snmp_detection.py b/app/detection_modules/snmp_detection.py deleted file mode 100644 index fcb43f2..0000000 --- a/app/detection_modules/snmp_detection.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'aguilbaud' diff --git a/app/detection_modules/ssh_detection.py b/app/detection_modules/ssh_detection.py deleted file mode 100644 index c2d1c52..0000000 --- a/app/detection_modules/ssh_detection.py +++ /dev/null @@ -1,103 +0,0 @@ -import paramiko -import json - - -# il faudrait p-e separer le traitement du resultat des commandes avec le lancement en lui mm -# si independant des protocoles utilises - -def connect(): - # TODO rendre la connection dynamique - key = paramiko.RSAKey.from_private_key_file("/home/aguilbaud/.ssh/id_rsa") - - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - ssh.connect('127.0.0.1', username='aguilbaud', pkey=key) - - run_detection(ssh) - - disconnect(ssh) - - -def disconnect(ssh): - ssh.close() - - -def run_detection(ssh): - print detect_hardware(ssh) - print detect_drives(ssh) - print detect_os_version(ssh) - print detect_non_updated_packages(ssh) - - -# Informations materielles globales -def detect_hardware(ssh): - cmd = "lshw -json" - stdin, stdout, stderr = ssh.exec_command(cmd) - res = "" - for line in stdout.read().splitlines(): - res += line - res_json = json.loads(res) - # TODO Traitement du resultat pour garder l'essentiel... - return res_json - - -# Informations sur les partitions -def detect_drives(ssh): - cmd = "lsblk -r --output=NAME,SIZE,TYPE,MOUNTPOINT" - stdin, stdout, stderr = ssh.exec_command(cmd) - dict_total = {} - i = 1 - ignore = True - for line in stdout.read().splitlines(): - # On ignore la premiere ligne qui ne contient pas de valeurs - if ignore: - ignore = False - else: - dict_drive = {} - tab_elem = line.split() - dict_drive["name"] = tab_elem[0] - dict_drive["size"] = tab_elem[1] - dict_drive["type"] = tab_elem[2] - if len(tab_elem) > 3: - dict_drive["mountpoint"] = tab_elem[3] - else: - dict_drive["mountpoint"] = "none" - # meilleur nom pour chaque attribut ? - dict_total[dict_drive["name"]] = dict_drive - i = i + 1 - return json.dumps(dict_total) - - -def detect_os_version(ssh): - # kernel - cmd = "cat /proc/version" - stdin, stdout, stderr = ssh.exec_command(cmd) - res = stdout.read() - dict_total = {} - dict_total["kernel"] = res.split('#')[0] - - # os - cmd = "cat /etc/os-release" - stdin, stdout, stderr = ssh.exec_command(cmd) - for line in stdout.read().splitlines(): - tab_elem = line.split("=") - # pour retirer les "" sur tous les champs qui en possedent - tab_right = tab_elem[1].split('"') - if len(tab_right) == 1: - dict_total[str.lower(tab_elem[0])] = tab_right[0] - else: - dict_total[str.lower(tab_elem[0])] = tab_right[1] - # encore une fois, on recupere tout le contenu de la commande, p-e qu'il est possible d'enlever le superflu - return json.dumps(dict_total, indent=4, separators=(',', ': ')) - - -# dependant de la langue du systeme ? -def detect_non_updated_packages(ssh): - cmd = "apt-get upgrade -s" - stdin, stdout, stderr = ssh.exec_command(cmd) - res = stdout.read() - tab_res = res.split(':') - if len(tab_res) == 2: - return json.dumps({'non_updated_packages': False}) - else: - return json.dumps({'non_updated_packages': True}) \ No newline at end of file diff --git a/app/detection_modules/__init__.py b/app/modules/__init__.py similarity index 100% rename from app/detection_modules/__init__.py rename to app/modules/__init__.py diff --git a/app/storage.py b/app/modules/storage.py similarity index 77% rename from app/storage.py rename to app/modules/storage.py index dc5173e..c898104 100644 --- a/app/storage.py +++ b/app/modules/storage.py @@ -5,6 +5,34 @@ __author__ = 'aguilbaud' import shelve from datetime import datetime from math import sqrt +import os.path + + +def init_db(): + if not os.path.isfile("mum.db"): + db = shelve.open("mum.db", writeback=True) + try: + db[str("hosts")] = {} + db[str("users")] = {} + db[str("groups")] = {} + db[str("global_conf")] = {} + finally: + db.close() + return shelve.open("mum.db" , writeback=True) + + +def close_db(db): + db.close() + + +def add_host(addr_host, nmap_res): + db = init_db() + try: + db[str("hosts")][str(addr_host)] = {} + db[str("hosts")][str(addr_host)][str("detected")] = {} + db[str("hosts")][str(addr_host)][str("detected")][str("nmap")] = nmap_res + finally: + close_db(db) def add_check(addr_host, name_part, val): diff --git a/app/monitoring_modules/__init__.py b/app/modules/storage_module/__init__.py similarity index 100% rename from app/monitoring_modules/__init__.py rename to app/modules/storage_module/__init__.py diff --git a/requirements.txt b/requirements.txt index 1545e2e..b689fc6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,5 +2,4 @@ bottle==0.12.7 pysnmp pexpect paramiko -bottle-websocket -elasticsearch \ No newline at end of file +bottle-websocket \ No newline at end of file diff --git a/static/js/controllers/detectCtrl.js b/static/js/controllers/detectCtrl.js index 254e9c6..69afe93 100644 --- a/static/js/controllers/detectCtrl.js +++ b/static/js/controllers/detectCtrl.js @@ -1,6 +1,6 @@ -var formExample = angular.module('formExample', ['toastr']); +var formExample = angular.module('detectModule', ['toastr']); -formExample.controller('ExampleController', ['$scope', 'toastr', '$http', '$interval', function($scope, toastr, $http, $interval) { +formExample.controller('DetectController', ['$scope', 'toastr', '$http', '$interval', function($scope, toastr, $http, $interval) { $scope.master = {}; $scope.ip_range = "198.116.0.1-10" // la plage d'ip entree dans le champ $scope.state = ""; // l'etat general du scan en cours diff --git a/views/index.html b/views/index.html index adb8536..619e2f9 100644 --- a/views/index.html +++ b/views/index.html @@ -20,8 +20,8 @@ <link href="static/css/main.css" rel="stylesheet" media="screen"/> </head> -<body ng-app="formExample"> -<div ng-controller="ExampleController"> +<body ng-app="detectModule"> +<div ng-controller="DetectController"> <form ng_submit="post_val()"> <div ng-show="validated == false" class="ng-hide"> Plage d'IP à scanner (exemple : 198.116.0.1-10) : <input name="ip_range" ng-model="ip_range" /> diff --git a/views/scan.html b/views/scan.html index 5c8da50..bd2e3c7 100644 --- a/views/scan.html +++ b/views/scan.html @@ -15,13 +15,14 @@ <!-- Custom styles for this template --> <link href="static/css/dashboard.css" rel="stylesheet"> + <link href="bower_components/angular-toastr/dist/angular-toastr.min.css" rel="stylesheet"/> <script src="bower_components/angular/angular.min.js"></script> - - <script src="static/js/controllers/table_ctrl.js"></script> + <script src="bower_components/angular-toastr/dist/angular-toastr.min.js"></script> + <script src="static/js/controllers/detectCtrl.js"></script> </head> - <body> + <body ng-app="detectModule" ng-controller="DetectController"> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container-fluid"> @@ -61,9 +62,9 @@ </div> <div class="col-md-offset-2 main"> <h1 class="page-header">Scan for new machines</h1> - <form class="form-inline"> + <form class="form-inline" ng_submit="post_val()"> <label for="input_ip_range">IP range to scan (example : 198.116.0.1-10)</label> - <input type="ip_range" class="form-control" id="input_ip_range" placeholder="198.116.0.1-10"/> + <input type="ip_range" class="form-control" id="input_ip_range" ng-model="ip_range" placeholder="198.116.0.1-10"/> <button type="submit" class="btn btn-primary">Scan now</button> </form> </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 91d6baf751607759cf9c762bd21e5373b95b2298 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 11:29:06 2015 +0100 scan nmap sauvegardé dans bdd Shelve --- app/modules/detection_modules/__init__.py | 1 + app/modules/detection_modules/drive_detection.py | 34 +++++ app/modules/detection_modules/nagios_detection.py | 1 + app/modules/detection_modules/nmap_detection.py | 160 ++++++++++++++++++++++ app/modules/detection_modules/snmp_detection.py | 1 + app/modules/detection_modules/ssh_detection.py | 103 ++++++++++++++ 6 files changed, 300 insertions(+) diff --git a/app/modules/detection_modules/__init__.py b/app/modules/detection_modules/__init__.py new file mode 100644 index 0000000..fcb43f2 --- /dev/null +++ b/app/modules/detection_modules/__init__.py @@ -0,0 +1 @@ +__author__ = 'aguilbaud' diff --git a/app/modules/detection_modules/drive_detection.py b/app/modules/detection_modules/drive_detection.py new file mode 100644 index 0000000..fb374b3 --- /dev/null +++ b/app/modules/detection_modules/drive_detection.py @@ -0,0 +1,34 @@ +# -*- coding: utf8 -*- +from __future__ import unicode_literals +__author__ = 'aguilbaud' + +''' +Retourne les informations des partitions systeme sous la forme : +{"sr0": {"mountpoint": "none", "type": "rom", "name": "sr0", "size": "1024M"} +''' + +# Informations sur les partitions +def detect_drives(conn, os): + cmd = "lsblk -r --output=NAME,SIZE,TYPE,MOUNTPOINT" + stdin, stdout, stderr = conn.exec_command(cmd) + dict_total = {} + i = 1 + ignore = True + for line in stdout.read().splitlines(): + # On ignore la premiere ligne qui ne contient pas de valeurs + if ignore: + ignore = False + else: + dict_drive = {} + tab_elem = line.split() + dict_drive["name"] = tab_elem[0] + dict_drive["size"] = tab_elem[1] + dict_drive["type"] = tab_elem[2] + if len(tab_elem) > 3: + dict_drive["mountpoint"] = tab_elem[3] + else: + dict_drive["mountpoint"] = "none" + # meilleur nom pour chaque attribut ? + dict_total[dict_drive["name"]] = dict_drive + i = i + 1 + return json.dumps(dict_total) \ No newline at end of file diff --git a/app/modules/detection_modules/nagios_detection.py b/app/modules/detection_modules/nagios_detection.py new file mode 100644 index 0000000..fcb43f2 --- /dev/null +++ b/app/modules/detection_modules/nagios_detection.py @@ -0,0 +1 @@ +__author__ = 'aguilbaud' diff --git a/app/modules/detection_modules/nmap_detection.py b/app/modules/detection_modules/nmap_detection.py new file mode 100644 index 0000000..d5a95c1 --- /dev/null +++ b/app/modules/detection_modules/nmap_detection.py @@ -0,0 +1,160 @@ +# -*- coding: utf8 -*- +from __future__ import unicode_literals +__author__ = 'aguilbaud' + +from xml.dom import minidom +import pexpect +import json +import shelve +import os.path +from .. import storage + +scanned_ip = {} + + +def get_scanned_ip(): + global scanned_ip + return json.dumps(scanned_ip) + + +# fonction qui permet de decomposer les differentes plages d'ip +# lance la detection nmap pour chacune des ip comprises dans cette plage +# NB : il est possible de lancer nmap directement sur la plage, mais il est alors difficile de determiner l'état +# du scan. De plus, si la plage d'ip est grande, l'exécution sera bien plus longue et tous les résultats +# seront obtenus d'un coup à la fin. +def check_ip_range(ip_range, ws): + # separation des 4 octets + range_byte_1 = ip_range.split('.')[0] + range_byte_2 = ip_range.split('.')[1] + range_byte_3 = ip_range.split('.')[2] + range_byte_4 = ip_range.split('.')[3] + + # separation des plages eventuelles + split_byte_1 = range_byte_1.split('-') + split_byte_2 = range_byte_2.split('-') + split_byte_3 = range_byte_3.split('-') + split_byte_4 = range_byte_4.split('-') + + # si aucune plage n'est indiquee, on cree une plage de meme valeur + if len(split_byte_1) == 1: + split_byte_1.append(split_byte_1[0]) + # verification que les nombres sont ordonnes correctement + # et que les valeurs entrees sont inferieures a 255 + split_byte_1 = check_order_and_under_255(split_byte_1) + + # idem pour le deuxieme octet + if len(split_byte_2) == 1: + split_byte_2.append(split_byte_2[0]) + split_byte_2 = check_order_and_under_255(split_byte_2) + + # idem pour le troisieme octet + if len(split_byte_3) == 1: + split_byte_3.append(split_byte_3[0]) + split_byte_3 = check_order_and_under_255(split_byte_3) + + # idem pour le quatrieme octet + if len(split_byte_4) == 1: + split_byte_4.append(split_byte_4[0]) + split_byte_4 = check_order_and_under_255(split_byte_4) + + # il est possible d'ajouter ici une condition pour verifier que l'utilisateur + # n'ait pas entre une plage d'IP trop grande + + # pour toutes les plages dans l'ordre croissant, en partant du dernier octet + for byte_1 in range(int(split_byte_1[0]), int(split_byte_1[1]) + 1): + for byte_2 in range(int(split_byte_2[0]), int(split_byte_2[1]) + 1): + for byte_3 in range(int(split_byte_3[0]), int(split_byte_3[1]) + 1): + for byte_4 in range(int(split_byte_4[0]), int(split_byte_4[1]) + 1): + launch_detection(byte_1, byte_2, byte_3, byte_4, ws) + + +# vérifie que la plage de données entrée est dans l'ordre croissant +# et que ses valeurs sont inferieures à 255 +# si ce n'est pas le cas, retourne le tableau trié et/ou avec les valeurs capées à 255 +def check_order_and_under_255(tab_val): + if int(tab_val[0]) > 255 : + tab_val[0] = '255' + if int(tab_val[1]) > 255 : + tab_val[1] = '255' + if int(tab_val[0]) > int(tab_val[1]): + tmp = tab_val[1] + tab_val[1] = tab_val[0] + tab_val[0] = tmp + return tab_val + + +# lance la detection a l'aide de nmap sur l'ip representee par les 4 octets passes en parametres +def launch_detection(byte_1, byte_2, byte_3, byte_4, ws): + req = {} + ip = str(byte_1) + '.' + str(byte_2) + '.' + str(byte_3) + '.' + str(byte_4) + req["30"] = "Scan de l'IP " + ip + " en cours..." + ws.send(json.dumps(req)) + child = pexpect.spawn('nmap', ['-A', ip, '-oX', 'res.xml']) + res = '' + # ici : possibilite de verifier l'avancement du scan, si option verbose (-v3) activee dans la commande nmap + try: + while child.isalive(): + child.expect('Completed', timeout=None) + res += child.before + '<br/>' + except pexpect.EOF: + res += ' A FINI' + try: + parse_res(ip) + except: + del req["30"] + req["40"] = "Database error" + except pexpect.TIMEOUT: + del req["30"] + req["40"] = "Timeout on nmap execution" + ws.send(json.dumps(req)) + return res + + +# parse le resultat xml de nmap pour ne conserver que les valeurs interssantes +# envoie directement le resultat sur le service ElasticSearch +def parse_res(ip): + global scanned_ip + # Ouverture du fichier xml avec le parseur minidom + root = minidom.parse("res.xml") + collection = root.documentElement + + # Recuperer tous les <host> de la collection + hosts = collection.getElementsByTagName("host") + + # Recuperation des noeuds de chaque <host> et affichage de leur attributss + # JSON = liste de dictionnaires + for host in hosts: + status = host.getElementsByTagName('status')[0] + address = host.getElementsByTagName('address')[0] + + dict_host = {} + dict_host['addr'] = address.getAttribute('addr') + dict_host['date'] = host.getAttribute('endtime') + dict_host['state'] = status.getAttribute('state') + dict_host['os'] = 'unknown' # par defaut + + hostnames_elem = host.getElementsByTagName('hostnames')[0] + hostnames = hostnames_elem.getElementsByTagName('hostname') + for hostname in hostnames: + dict_host['hostname'] = hostname.getAttribute("name") + + ports_elem = host.getElementsByTagName('ports')[0] + ports = ports_elem.getElementsByTagName('port') + list_dict_port = [] + for port in ports: + dict_port = {} + state = port.getElementsByTagName('state')[0] + service = port.getElementsByTagName('service')[0] + if service.hasAttribute("ostype"): + dict_host['os'] = service.getAttribute("ostype") + if state.getAttribute('state') == 'open': + dict_port['portid'] = port.getAttribute('portid') + dict_port['portname'] = service.getAttribute('name') + # Ajouter d'autres infos ? + list_dict_port.append(dict_port) + dict_host['openports'] = list_dict_port + # sauvegarde de l'host dans la base elasticsearch avec pour ID son IP + storage.add_host(dict_host['addr'], json.dumps(dict_host)) + pexpect.run("rm -f res.xml") + #pexpect.run('curl -XPUT \'localhost:9200/saved_hosts' + scanned_ip[ip] = "localhost:9200/host/external/" + ip \ No newline at end of file diff --git a/app/modules/detection_modules/snmp_detection.py b/app/modules/detection_modules/snmp_detection.py new file mode 100644 index 0000000..fcb43f2 --- /dev/null +++ b/app/modules/detection_modules/snmp_detection.py @@ -0,0 +1 @@ +__author__ = 'aguilbaud' diff --git a/app/modules/detection_modules/ssh_detection.py b/app/modules/detection_modules/ssh_detection.py new file mode 100644 index 0000000..c2d1c52 --- /dev/null +++ b/app/modules/detection_modules/ssh_detection.py @@ -0,0 +1,103 @@ +import paramiko +import json + + +# il faudrait p-e separer le traitement du resultat des commandes avec le lancement en lui mm +# si independant des protocoles utilises + +def connect(): + # TODO rendre la connection dynamique + key = paramiko.RSAKey.from_private_key_file("/home/aguilbaud/.ssh/id_rsa") + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect('127.0.0.1', username='aguilbaud', pkey=key) + + run_detection(ssh) + + disconnect(ssh) + + +def disconnect(ssh): + ssh.close() + + +def run_detection(ssh): + print detect_hardware(ssh) + print detect_drives(ssh) + print detect_os_version(ssh) + print detect_non_updated_packages(ssh) + + +# Informations materielles globales +def detect_hardware(ssh): + cmd = "lshw -json" + stdin, stdout, stderr = ssh.exec_command(cmd) + res = "" + for line in stdout.read().splitlines(): + res += line + res_json = json.loads(res) + # TODO Traitement du resultat pour garder l'essentiel... + return res_json + + +# Informations sur les partitions +def detect_drives(ssh): + cmd = "lsblk -r --output=NAME,SIZE,TYPE,MOUNTPOINT" + stdin, stdout, stderr = ssh.exec_command(cmd) + dict_total = {} + i = 1 + ignore = True + for line in stdout.read().splitlines(): + # On ignore la premiere ligne qui ne contient pas de valeurs + if ignore: + ignore = False + else: + dict_drive = {} + tab_elem = line.split() + dict_drive["name"] = tab_elem[0] + dict_drive["size"] = tab_elem[1] + dict_drive["type"] = tab_elem[2] + if len(tab_elem) > 3: + dict_drive["mountpoint"] = tab_elem[3] + else: + dict_drive["mountpoint"] = "none" + # meilleur nom pour chaque attribut ? + dict_total[dict_drive["name"]] = dict_drive + i = i + 1 + return json.dumps(dict_total) + + +def detect_os_version(ssh): + # kernel + cmd = "cat /proc/version" + stdin, stdout, stderr = ssh.exec_command(cmd) + res = stdout.read() + dict_total = {} + dict_total["kernel"] = res.split('#')[0] + + # os + cmd = "cat /etc/os-release" + stdin, stdout, stderr = ssh.exec_command(cmd) + for line in stdout.read().splitlines(): + tab_elem = line.split("=") + # pour retirer les "" sur tous les champs qui en possedent + tab_right = tab_elem[1].split('"') + if len(tab_right) == 1: + dict_total[str.lower(tab_elem[0])] = tab_right[0] + else: + dict_total[str.lower(tab_elem[0])] = tab_right[1] + # encore une fois, on recupere tout le contenu de la commande, p-e qu'il est possible d'enlever le superflu + return json.dumps(dict_total, indent=4, separators=(',', ': ')) + + +# dependant de la langue du systeme ? +def detect_non_updated_packages(ssh): + cmd = "apt-get upgrade -s" + stdin, stdout, stderr = ssh.exec_command(cmd) + res = stdout.read() + tab_res = res.split(':') + if len(tab_res) == 2: + return json.dumps({'non_updated_packages': False}) + else: + return json.dumps({'non_updated_packages': True}) \ No newline at end of file -- 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 7d977bac276a337cf4cb14876f24ef8428ff2cd1 Author: Alexis Guilbaud <guilbaud@codelutin.com> Date: Tue Feb 17 15:22:17 2015 +0100 function get_hosts() implemented --- app/modules/storage.py | 76 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/app/modules/storage.py b/app/modules/storage.py index c898104..d4d7d06 100644 --- a/app/modules/storage.py +++ b/app/modules/storage.py @@ -1,43 +1,92 @@ -# -*- coding: utf8 -*- -from __future__ import unicode_literals __author__ = 'aguilbaud' import shelve from datetime import datetime from math import sqrt import os.path +import json +# Returns an instance of the python database +# If the base doesn't exists, it initialize the first elements def init_db(): if not os.path.isfile("mum.db"): db = shelve.open("mum.db", writeback=True) try: - db[str("hosts")] = {} - db[str("users")] = {} - db[str("groups")] = {} - db[str("global_conf")] = {} + db["hosts"] = {} + db["users"] = {} + db["groups"] = {} + db["global_conf"] = {} finally: - db.close() - return shelve.open("mum.db" , writeback=True) + return db + return shelve.open("mum.db", writeback=True) +# Closes the database def close_db(db): db.close() +# Add and save a new host after its first nmap detection +# It also preconfigure with the default configuration, add the host to the group "all" and +# creates empty structures for the monitoring and archive data. def add_host(addr_host, nmap_res): + addr_host = str(addr_host) # Shelve doesn't support Unicode db = init_db() try: - db[str("hosts")][str(addr_host)] = {} - db[str("hosts")][str(addr_host)][str("detected")] = {} - db[str("hosts")][str(addr_host)][str("detected")][str("nmap")] = nmap_res + # Add the nmap detection + db["hosts"][addr_host] = {} + db["hosts"][addr_host]["detected"] = {} + db["hosts"][addr_host]["detected"]["nmap"] = nmap_res + # Preconfiguration + db["hosts"][addr_host]["conf"] = {} + db["hosts"][addr_host]["conf"]["monitoring"] = db["global_conf"] + db["hosts"][addr_host]["conf"]["groups"] = {"name": "all"} + db["hosts"][addr_host]["conf"]["subscribers"] = {} # Add current user automatically ? + db["hosts"][addr_host]["conf"]["custom_info"] = "" + db["hosts"][addr_host]["conf"]["interventions"] = {} + # Create structure for monitoring data + db["hosts"][addr_host]["monitoring"] = {} + # Create structure for archiving data + db["hosts"][addr_host]["archive"] = {} finally: close_db(db) +# Returns the essential data about all hosts under monitoring +# These are used by the front-end +# If no hosts have been added, the function will return an empty list +def get_hosts(): + res = [] + db = init_db() + try: + if db["hosts"] != {}: + for host in db["hosts"]: + detected = json.loads(db["hosts"][host]["detected"]["nmap"]) + info_host = {} + info_host["addr"] = detected["addr"] + info_host["name"] = detected["hostname"] + if "status" in db["hosts"][host]["monitoring"]: + info_host["status"] = db["hosts"][host]["monitoring"]["status"] + else: + info_host["status"] = "" + info_host["group"] = [] + for group in db["hosts"][host]["conf"]["groups"]: + info_host["group"].append({"name": db["hosts"][host]["conf"]["groups"][group]}) + if "date" in db["hosts"][host]["monitoring"]: + info_host["last_check"] = db["hosts"][host]["monitoring"]["date"] + else: + info_host["last_check"] = 0 + res.append(info_host) + finally: + close_db(db) + return json.dumps(res) + + +# Add a new check of a host from a specific module def add_check(addr_host, name_part, val): new_val = {"date": datetime.now()} - db = shelve.open('mum.db', writeback=True) + db = init_db() try: if val >= db['hosts']['conf']['monitorig'][name_part]['minor_limit']: new_val['state'] = 'warning' @@ -51,7 +100,7 @@ def add_check(addr_host, name_part, val): if db['hosts'][addr_host]['archive'].has_key(name_part): db['hosts'][addr_host]['archive'][name_part] = update_stats(db['hosts'][addr_host]['archive'][name_part], val) finally: - db.close() + close_db(db) # Updates calulated statistics once a new value is received @@ -98,6 +147,7 @@ def get_slope_of_linear_regression(stats): print "Division by 0 on get_slope_of_linear_regression(stats)" return res + def save_detection(name_part, json_res): db = shelve.open('mum.db', writeback=True) try: -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm