[mac_prises] En place, avec script d'analyse.
Je commence à en avoir marre des gens qui spoofent. J'ai donc pris en charge l'écriture de mac_prises cette nuit. Je le mets en test vers la mailing list test@lists.crans.org, avis aux amateurs.
This commit is contained in:
parent
baf4aa3645
commit
df49d0b6dc
6 changed files with 305 additions and 90 deletions
|
@ -5,9 +5,9 @@ import psycopg2
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if __name__ == 'annuaires_pg_test':
|
if __name__ == 'annuaires_pg_test':
|
||||||
conn = psycopg2.connect("user=crans dbname=switchs host=localhost")
|
conn = psycopg2.connect(user='crans', database='switchs', host='localhost')
|
||||||
else:
|
else:
|
||||||
conn = psycopg2.connect("user=crans dbname=switchs host=pgsql.adm.crans.org")
|
conn = psycopg2.connect(user='crans', database='switchs', host='pgsql.adm.crans.org')
|
||||||
|
|
||||||
# Population de la tâble avec les bâtiments
|
# Population de la tâble avec les bâtiments
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
|
|
@ -331,6 +331,42 @@ puissions corriger le problème.
|
||||||
--\u0020
|
--\u0020
|
||||||
Les membres actifs du Crans""" % email.Header.make_header([("Déménagement non déclaré", "utf8")])
|
Les membres actifs du Crans""" % email.Header.make_header([("Déménagement non déclaré", "utf8")])
|
||||||
|
|
||||||
|
class mac_prise:
|
||||||
|
# Pour la recherche dans postgres
|
||||||
|
delay = { 'instant': '2 min',
|
||||||
|
'heuristique': '30 min',
|
||||||
|
'journalier': '1 day',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit suspect"
|
||||||
|
# Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit suspect"
|
||||||
|
suspect = { 'instant':{'mac': 2, 'chambre': 2},
|
||||||
|
'heuristique':{'mac': 3, 'chambre': 2},
|
||||||
|
'journalier':{'mac': 3, 'chambre': 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit suspect"
|
||||||
|
# Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit suspect"
|
||||||
|
tres_suspect = { 'instant':{'mac': 3, 'chambre': 3},
|
||||||
|
'heuristique':{'mac': 4, 'chambre': 3},
|
||||||
|
'journalier':{'mac': 4, 'chambre': 3},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Le point central des analyses.
|
||||||
|
rapport_suspect = { 'instant':{'mac': 0.51, 'chambre': 0.51},
|
||||||
|
'heuristique':{'mac': 0.57, 'chambre': 0.55},
|
||||||
|
'journalier':{'mac': 0.61, 'chambre': 0.58},
|
||||||
|
}
|
||||||
|
|
||||||
|
titre_suspect = { 'instant':{'mac': u"Macs se baladant un peu trop entre les chambres (instantanné)", 'chambre': u"Chambres avec un peu trop de macs (instantanné)"},
|
||||||
|
'heuristique':{'mac': u"Macs se baladant un peu trop entre les chambres (délai moyen)", 'chambre': u"Chambres avec un peu trop de macs (délai moyen)"},
|
||||||
|
'journalier':{'mac': u"Macs s'étant peut-être un peu trop baladées aujourd'hui", 'chambre': u"Chambres avec un peu trop de macs sur un jour"},
|
||||||
|
}
|
||||||
|
|
||||||
|
titre_tres_suspect = { 'instant':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (instantanné)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (instantanné)"},
|
||||||
|
'heuristique':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (délai moyen)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (délai moyen)"},
|
||||||
|
'journalier':{'mac': u"/!\ Spoof probable des macs suivantes dans les chambres ci-après aujourd'hui !!", 'chambre': u"/!\ Les chambres suivantes contiennent trop de macs inconnues (sur un jour)"},
|
||||||
|
}
|
||||||
|
|
||||||
# Classe pour les paramètres du firewall #
|
# Classe pour les paramètres du firewall #
|
||||||
##########################################
|
##########################################
|
||||||
|
@ -645,10 +681,10 @@ debit_max_gratuit = 1000000
|
||||||
## Vlan accueil et isolement ##
|
## Vlan accueil et isolement ##
|
||||||
###############################
|
###############################
|
||||||
accueil_route = {
|
accueil_route = {
|
||||||
'138.231.136.1':{'tcp':['80','443']},
|
'138.231.136.1':{'tcp':['80','443'],'hosts':['intranet.crans.org']},
|
||||||
'138.231.136.67':{'tcp':['80','443']},
|
'138.231.136.67':{'tcp':['80','443'],'hosts':['www.crans.org', 'wiki.crans.org', 'wifi.crans.org']},
|
||||||
'138.231.136.98':{'tcp':['20','21','80','111','1024:65535'],'udp':['69','1024:65535']},
|
'138.231.136.98':{'tcp':['20','21','80','111','1024:65535'],'udp':['69','1024:65535'], 'hosts':['ftp.crans.org']},
|
||||||
'138.231.136.130':{'tcp':['80','443']}
|
'138.231.136.130':{'tcp':['80','443'],'hosts':['intranet2.crans.org']}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,8 @@ from commands import getstatusoutput
|
||||||
|
|
||||||
sys.path.append('/usr/scripts/gestion')
|
sys.path.append('/usr/scripts/gestion')
|
||||||
import annuaires_pg
|
import annuaires_pg
|
||||||
import psycopg2
|
import time
|
||||||
|
|
||||||
|
|
||||||
# nécessite apparemment que l'objet conn soit bien créé lors de l'exec
|
# nécessite apparemment que l'objet conn soit bien créé lors de l'exec
|
||||||
# de annuaires_pg, il faut être root (ou dans je ne sais quel groupe)
|
# de annuaires_pg, il faut être root (ou dans je ne sais quel groupe)
|
||||||
|
@ -18,7 +19,7 @@ import psycopg2
|
||||||
# (plante lamentablement quand j'essaye avec mon compte sur vo, sous
|
# (plante lamentablement quand j'essaye avec mon compte sur vo, sous
|
||||||
# ipython. Mais si je sudo ipython, ça marche...
|
# ipython. Mais si je sudo ipython, ça marche...
|
||||||
|
|
||||||
def liste_prises_macs(switch):
|
def liste_chambres_macs(switch):
|
||||||
u'''
|
u'''
|
||||||
Fonction générant un dictionnaire (macs) contenant pour chaque prise une
|
Fonction générant un dictionnaire (macs) contenant pour chaque prise une
|
||||||
liste des macs qui y sont actives.
|
liste des macs qui y sont actives.
|
||||||
|
@ -33,28 +34,32 @@ def liste_prises_macs(switch):
|
||||||
|
|
||||||
liste_chbres = []
|
liste_chbres = []
|
||||||
macs = {}
|
macs = {}
|
||||||
for i in data:
|
if data:
|
||||||
if i == '':
|
for port in data:
|
||||||
continue
|
if port == '':
|
||||||
else:
|
|
||||||
port = int(i.replace('STATISTICS-MIB::hpSwitchPortFdbAddress.', '').split('.')[0])
|
|
||||||
mac = data[i].replace(' ', '').lower().replace('"', '')
|
|
||||||
if not re.match('([0-9a-f]{2}){6}', mac):
|
|
||||||
mac = mac.encode('hex').lower()
|
|
||||||
mac = "%s:%s:%s:%s:%s:%s" % (mac[0:2], mac[2:4], mac[4:6], mac[6:8], mac[8:10], mac[10:12])
|
|
||||||
uplink = annuaires_pg.uplink_prises[bat]
|
|
||||||
prise = num_switch*100+port
|
|
||||||
if prise in uplink:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
chbre = chbre_prises(bat, prise)
|
|
||||||
|
|
||||||
if chbre in liste_chbres:
|
|
||||||
macs[chbre].append(mac+'\n')
|
|
||||||
else:
|
else:
|
||||||
macs[chbre] = []
|
mac = data[port]
|
||||||
macs[chbre].append(mac+'\n')
|
uplink = annuaires_pg.uplink_prises[bat]
|
||||||
liste_chbres.append(chbre)
|
prise = num_switch*100+port
|
||||||
|
if prise in uplink:
|
||||||
|
continue
|
||||||
|
|
||||||
|
result = annuaires_pg.reverse(bat, prise)
|
||||||
|
if result:
|
||||||
|
chbre = bat+result[0]
|
||||||
|
if chbre in liste_chbres:
|
||||||
|
macs[chbre].extend(mac)
|
||||||
|
else:
|
||||||
|
macs[chbre] = []
|
||||||
|
macs[chbre].extend(mac)
|
||||||
|
liste_chbres.append(chbre)
|
||||||
|
del chbre
|
||||||
|
else:
|
||||||
|
# On droppe, c'est des bornes wifi ou autres.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print "Pas de données pour %s" % (switch)
|
||||||
return macs
|
return macs
|
||||||
|
|
||||||
def walk(host, oid):
|
def walk(host, oid):
|
||||||
|
@ -67,8 +72,21 @@ def walk(host, oid):
|
||||||
received = __exec('snmpwalk -Ox -v 1 -c public %s %s' % (host, oid)).split('\n')
|
received = __exec('snmpwalk -Ox -v 1 -c public %s %s' % (host, oid)).split('\n')
|
||||||
result = {}
|
result = {}
|
||||||
for ligne in received:
|
for ligne in received:
|
||||||
pport, pmac = ligne.split('Hex-STRING: ')
|
try:
|
||||||
result[pport] = pmac
|
pport, pmac = ligne.split('Hex-STRING: ')
|
||||||
|
|
||||||
|
port = int(pport.replace('STATISTICS-MIB::hpSwitchPortFdbAddress.', '').split('.')[0])
|
||||||
|
mac = pmac.replace(' ', '').lower().replace('"', '')
|
||||||
|
if not re.match('([0-9a-f]{2}){6}', mac):
|
||||||
|
mac = mac.encode('hex').lower()
|
||||||
|
mac = "%s:%s:%s:%s:%s:%s" % (mac[0:2], mac[2:4], mac[4:6], mac[6:8], mac[8:10], mac[10:12])
|
||||||
|
|
||||||
|
if not result.has_key(port):
|
||||||
|
result[port] = [mac]
|
||||||
|
else:
|
||||||
|
result[port].append(mac)
|
||||||
|
except:
|
||||||
|
print "Ligne moisie : %s de l'hôte : %s" % (ligne, host)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,18 +103,14 @@ def __exec(cmd):
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
switchs = sys.argv[1:]
|
switchs = sys.argv[1:]
|
||||||
|
date = time.strftime('%F %T')
|
||||||
for switch in switchs:
|
for switch in switchs:
|
||||||
macs = liste_prises_macs(switch)
|
macs = liste_chambres_macs(switch)
|
||||||
|
|
||||||
split = switch.replace('.adm.crans.org', '').split('-')
|
|
||||||
bat, num_switch = split[0][-1], int(split[1][0])
|
|
||||||
|
|
||||||
pgsql = psycopg2.connect(database="mac_prises", user="crans")
|
|
||||||
curseur = pgsql.cursor()
|
|
||||||
|
|
||||||
# if not os.path.isdir("bat%s/%d"%(bat, num_switch)):
|
print macs
|
||||||
# os.makedirs("bat%s/%d"%(bat, num_switch))
|
|
||||||
|
# fichier =
|
||||||
|
# for chambre in macs.keys():
|
||||||
|
# for mac in macs[chambre]:
|
||||||
#
|
#
|
||||||
# for chbre in macs:
|
# curseur.execute(requete, (date, chambre, mac))
|
||||||
# with open('bat%s/%d/%s%03d.macs'%(bat, num_switch, bat, prise), 'w') as f:
|
|
||||||
# f.writelines(sorted(macs[prise]))
|
|
||||||
|
|
156
surveillance/mac_prises/mac_prise_analyzer.py
Executable file
156
surveillance/mac_prises/mac_prise_analyzer.py
Executable file
|
@ -0,0 +1,156 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
|
import psycopg2
|
||||||
|
import psycopg2.extras
|
||||||
|
import sys
|
||||||
|
import smtplib
|
||||||
|
|
||||||
|
sys.path.append('/usr/scripts/gestion')
|
||||||
|
from config import mac_prise
|
||||||
|
from affich_tools import tableau
|
||||||
|
sys.path.append('/usr/scripts/lc_ldap')
|
||||||
|
import lc_ldap
|
||||||
|
|
||||||
|
ldap = lc_ldap.lc_ldap_admin()
|
||||||
|
|
||||||
|
membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))')
|
||||||
|
chambres_ma = []
|
||||||
|
for membre_actif in membres_actifs:
|
||||||
|
try:
|
||||||
|
chambres_ma.append(str(membre_actif['chbre'][0]).lower())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
clubs = ldap.search('cid=*')
|
||||||
|
chambres_clubs = []
|
||||||
|
for club in clubs:
|
||||||
|
try:
|
||||||
|
chambres_clubs.append(str(club['chbre'][0]).lower())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
conn = psycopg2.connect(user='crans', database='mac_prises')
|
||||||
|
cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)
|
||||||
|
|
||||||
|
longueur = { 'mac': (24, 3),
|
||||||
|
'chambre': (10, 7),
|
||||||
|
}
|
||||||
|
titres = { 'mac':(u'mac', u'chambres'),
|
||||||
|
'chambre': (u'chambre', u'macs'),
|
||||||
|
}
|
||||||
|
alignements = ('c', 'c')
|
||||||
|
|
||||||
|
def lin(x, y, z):
|
||||||
|
"""
|
||||||
|
Calcul linéaire d'un rapport
|
||||||
|
"""
|
||||||
|
return (float(x)/float(y)-1.0)/(float(z)-1.0)*100
|
||||||
|
|
||||||
|
def genere_comptage(duree, groupe, associes):
|
||||||
|
"""
|
||||||
|
Grosse fonction de hack pour ne pas écrire six fois le même formatage de sortie bidon.
|
||||||
|
Prend en argument :
|
||||||
|
|
||||||
|
* duree, qui peut valoir 'instant', 'heuristique', ou 'journalier', permet d'importer
|
||||||
|
les variables de config qui vont bien
|
||||||
|
* groupe, qui précise selon quoi on groupe (mac ou chambre)
|
||||||
|
* associes, qui contient l'autre champ
|
||||||
|
"""
|
||||||
|
pb_comptage_suspect = {}
|
||||||
|
pb_comptage_tres_suspect = {}
|
||||||
|
output = ""
|
||||||
|
requete = "SELECT array_to_string(array_agg(DISTINCT date), ',') AS dates , %(groupe)s, array_to_string(array_agg(DISTINCT %(associes)s), ',') AS %(associes)ss, COUNT(DISTINCT %(associes)s) AS nb_%(associes)ss_distinctes, COUNT(%(associes)s) AS nb_%(associes)ss, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT %(groupe)s) as nb_%(groupe)ss_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY %(groupe)s;" % { 'groupe': groupe, 'associes': associes, 'delay': mac_prise.delay[duree] }
|
||||||
|
cur.execute(requete)
|
||||||
|
fetched = cur.fetchall()
|
||||||
|
|
||||||
|
for entry in fetched:
|
||||||
|
# Si c'est la chambre d'un membre actif ou d'un club, on droppe.
|
||||||
|
if groupe == 'chambre':
|
||||||
|
if entry[groupe] in chambres_ma + chambres_clubs:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Sinon, on vérifie si le local est bien rempli.
|
||||||
|
if entry['nb_'+associes+'s_distinctes'] >= mac_prise.tres_suspect[duree][groupe]:
|
||||||
|
liste_associes = entry[associes+'s'].split(',')
|
||||||
|
|
||||||
|
# On retire les machines associées à l'adhérent possédant la chambre
|
||||||
|
if groupe == 'chambre':
|
||||||
|
for i in liste_associes:
|
||||||
|
proprio_associe = ldap.search('macAddress=%s' % i)[0].proprio()
|
||||||
|
if str(proprio_associe['chbre']).lower() == entry[groupe]:
|
||||||
|
liste_associes.remove(i)
|
||||||
|
if len(liste_associes) < mac_prise.tres_suspect[duree][groupe]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Toujours un problème ? On ajoute au dico
|
||||||
|
pb_comptage_tres_suspect[entry[groupe]] = liste_associes
|
||||||
|
|
||||||
|
# Même chose avec un seuil plus faible
|
||||||
|
elif entry['nb_'+associes+'s_distinctes'] >= mac_prise.suspect[duree][groupe]:
|
||||||
|
liste_associes = entry[associes+'s'].split(',')
|
||||||
|
|
||||||
|
if groupe == 'chambre':
|
||||||
|
for i in liste_associes:
|
||||||
|
try:
|
||||||
|
proprio_associe = ldap.search('macAddress=%s' % i)[0].proprio()
|
||||||
|
if str(proprio_associe['chbre'][0]).lower() == entry[groupe]:
|
||||||
|
liste_associes.remove(i)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if len(liste_associes) < mac_prise.suspect[duree][groupe]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# On calcul la "probabilité" qu'un truc ne soit pas clair concernant la chambre/mac
|
||||||
|
rapport = lin(entry['nb_'+associes+'s'], entry['nb_dates_distinctes'], float(entry['nb_'+associes+'s_distinctes']))
|
||||||
|
if rapport >= mac_prise.rapport_suspect[duree][groupe]:
|
||||||
|
pb_comptage_suspect[entry[groupe]] = liste_associes
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if len(pb_comptage_suspect) > 0:
|
||||||
|
output += mac_prise.titre_suspect[duree][groupe]+"\n"
|
||||||
|
|
||||||
|
# On prend la longueur de la plus longue valeur, on s'assure que cette longueur fait celle de la légende, plus un entier de marge
|
||||||
|
longueur_max = max([len(", ".join(a)) for a in pb_comptage_suspect.values()] + [longueur[associes][1]]) + 4
|
||||||
|
largeurs = (longueur[groupe][0], longueur_max)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for clef, valeurs in pb_comptage_suspect.items():
|
||||||
|
data.append([clef, ", ".join(valeurs)])
|
||||||
|
|
||||||
|
output += tableau(data, titres[groupe], largeurs, alignements)
|
||||||
|
output += "\n\n\n"
|
||||||
|
|
||||||
|
if len(pb_comptage_tres_suspect) > 0:
|
||||||
|
output += mac_prise.titre_tres_suspect[duree][groupe]+"\n"
|
||||||
|
|
||||||
|
longueur_max = max([len(", ".join(a)) for a in pb_comptage_tres_suspect.values()] + [longueur[associes][1]]) + 4
|
||||||
|
largeurs = (longueur[groupe][0], longueur_max)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for clef, valeurs in pb_comptage_tres_suspect.items():
|
||||||
|
data.append([clef, ", ".join(valeurs)])
|
||||||
|
|
||||||
|
output += tableau(data, titres[groupe], largeurs, alignements)
|
||||||
|
output += "\n\n\n"
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
output = u"Détection de spoof potentiel\n\n\n"
|
||||||
|
coupure = len(output)
|
||||||
|
|
||||||
|
output += genere_comptage('instant', 'mac', 'chambre')
|
||||||
|
output += genere_comptage('heuristique', 'mac', 'chambre')
|
||||||
|
output += genere_comptage('journalier', 'mac', 'chambre')
|
||||||
|
output += genere_comptage('instant', 'chambre', 'mac')
|
||||||
|
output += genere_comptage('heuristique', 'chambre', 'mac')
|
||||||
|
output += genere_comptage('journalier', 'chambre', 'mac')
|
||||||
|
|
||||||
|
if len(output) == coupure:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
print output
|
54
surveillance/mac_prises/mac_prise_holder.py
Executable file
54
surveillance/mac_prises/mac_prise_holder.py
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import psycopg2
|
||||||
|
import mac_prise
|
||||||
|
from threading import Thread
|
||||||
|
import time
|
||||||
|
|
||||||
|
class ThreadWithReturnValue(Thread):
|
||||||
|
"""
|
||||||
|
Classe de threading qui récupère le "return" d'une fonction, et le renvoie avec
|
||||||
|
output()
|
||||||
|
"""
|
||||||
|
def __init__(self, group=None, target=None, name=None,
|
||||||
|
args=(), kwargs={}, Verbose=None):
|
||||||
|
Thread.__init__(self, group, target, name, args, kwargs, Verbose)
|
||||||
|
self._return = None
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if self._Thread__target is not None:
|
||||||
|
self._return = self._Thread__target(*self._Thread__args,
|
||||||
|
**self._Thread__kwargs)
|
||||||
|
def output(self):
|
||||||
|
Thread.join(self)
|
||||||
|
return self._return
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
"""
|
||||||
|
On envoie sur n threads les n arguments, puis on récupère les sorties
|
||||||
|
et on les enregistre dans une base postgresql
|
||||||
|
"""
|
||||||
|
switches = sys.argv[1:]
|
||||||
|
date = time.strftime('%F %T')
|
||||||
|
threads = {}
|
||||||
|
output = {}
|
||||||
|
for switch in switches:
|
||||||
|
threads[switch] = ThreadWithReturnValue(target=mac_prise.liste_chambres_macs, args=(switch,))
|
||||||
|
threads[switch].start()
|
||||||
|
|
||||||
|
# On change de boucle, car il faut absolument que tous les threads aient démarré, histoire qu'on
|
||||||
|
# parallélise vraiment !
|
||||||
|
for switch in switches:
|
||||||
|
output[switch] = threads[switch].output()
|
||||||
|
connecteur = psycopg2.connect(database="mac_prises", user="crans")
|
||||||
|
connecteur.set_session(autocommit=True)
|
||||||
|
curseur = connecteur.cursor()
|
||||||
|
|
||||||
|
requete = "INSERT INTO correspondance (date, chambre, mac) VALUES (%s, %s, %s);"
|
||||||
|
|
||||||
|
for switch in output:
|
||||||
|
for chambre in output[switch]:
|
||||||
|
for mac in output[switch][chambre]:
|
||||||
|
curseur.execute(requete, (date, chambre, mac))
|
|
@ -1,54 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
set -ex
|
SCRIPT=/usr/scripts/surveillance/mac_prises/mac_prise_holder.py
|
||||||
|
|
||||||
GIT_DIR=/usr/scripts/surveillance/mac_prises/output/
|
|
||||||
SCRIPT=/usr/scripts/surveillance/mac_prises/mac_prise.py
|
|
||||||
|
|
||||||
# Nombre de changements de mac sur une prise avant mail
|
|
||||||
WARNING=2
|
|
||||||
|
|
||||||
MAILTO=nobody@crans.org
|
|
||||||
|
|
||||||
if ! [ -d $GIT_DIR ]; then
|
|
||||||
echo -n "Création du répertoire \`$GIT_DIR'..."
|
|
||||||
mkdir $GIT_DIR
|
|
||||||
echo " Fait."
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd $GIT_DIR
|
|
||||||
|
|
||||||
if ! [ -d $GIT_DIR/.git ]; then
|
|
||||||
git init
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Récupération de la liste des switchs
|
# Récupération de la liste des switchs
|
||||||
SWITCHS=$(/usr/bin/host -l adm.crans.org | /usr/bin/awk '/^bat[abcghijpm]-/{print $1}')
|
SWITCHS=$(/usr/bin/host -l adm.crans.org sable.adm.crans.org | /usr/bin/awk '/^bat[abcghijpm]-/{print $1}')
|
||||||
|
|
||||||
# Nettoyage du contenu du répertoire, avec ignore-unmatch pour éviter le plantage en
|
|
||||||
# cas de répertoire vide.
|
|
||||||
/usr/bin/git rm -r -q --ignore-unmatch ./*
|
|
||||||
|
|
||||||
# Lancement du listage des macs en parallèle
|
# Lancement du listage des macs en parallèle
|
||||||
/usr/bin/parallel -j 1000 python $SCRIPT -- $SWITCHS
|
python $SCRIPT $SWITCHS
|
||||||
|
|
||||||
# Ajout de tous les fichiers (à faire avant le diff, pour que les nouveaux fichiers soient pris en compte)
|
|
||||||
/usr/bin/git add *
|
|
||||||
|
|
||||||
# Récupération de statistiques
|
|
||||||
# numstat renvoie le nombre de lignes ajoutées, le nombre de lignes supprimées et le nom du fichier
|
|
||||||
# on ajoute les deux premières variables et on classe par nombre de modifs
|
|
||||||
/usr/bin/git diff --cached --numstat | /usr/bin/awk '{print $1+$2 " " $3}' | sort -rn | ( while read num file; do
|
|
||||||
if [ $num -ge $WARNING ]; then
|
|
||||||
echo $file
|
|
||||||
else
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done ) | xargs /usr/bin/git diff --cached | mail -a 'From: "Eye in the sky" <root@crans.org>' -s "Surveillance macs/prises" $MAILTO
|
|
||||||
|
|
||||||
/usr/bin/git commit -m "Updated mac list" > /dev/null
|
|
||||||
|
|
||||||
# Garbage collection toutes les 10 minutes
|
|
||||||
if [ $(expr $(date +%M) % 10) -eq 0 ]; then
|
|
||||||
/usr/bin/git gc --aggressive -q
|
|
||||||
fi
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue