239 lines
9.7 KiB
Python
Executable file
239 lines
9.7 KiB
Python
Executable file
#!/bin/bash /usr/scripts/python.sh
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Auteur : Pierre-Elliott Bécue <becue@crans.org>
|
|
# Licence : GPLv3
|
|
# Date : 01/09/2014
|
|
|
|
import sys
|
|
import argparse
|
|
import re
|
|
import time
|
|
from ldap import SIZELIMIT_EXCEEDED
|
|
|
|
from gestion.config import encoding
|
|
from gestion import affichage
|
|
from gestion import annuaires_pg
|
|
import lc_ldap.shortcuts
|
|
import lc_ldap.objets
|
|
import lc_ldap.filter2 as lfilter
|
|
import lc_ldap.crans_utils
|
|
|
|
ENCODING = encoding.in_encoding
|
|
|
|
MACRO_FILTRE_PRISE = re.compile(r'\(prise=(?P<prise>[a-zA-Z][0-9]{3})\)')
|
|
MACRO_FILTRE_ADHESION = re.compile(r'\(adhesion=ok\)')
|
|
MACRO_FILTRE_CONNEXION = re.compile(r'\(connexion=ok\)')
|
|
|
|
def print_data(data, args):
|
|
"""Récupère les données et les affiche"""
|
|
dataLen = sum([len(elem) for elem in data.itervalues()])
|
|
if dataLen:
|
|
for (key, elem) in data.iteritems():
|
|
if len(elem) == 0:
|
|
continue
|
|
|
|
_header = affichage.style(u"Résultats de type %s trouvés dans la base." % (key,), ['cyan'])
|
|
print _header.encode(ENCODING)
|
|
if len(elem) == 1:
|
|
elem[0].display(
|
|
historique=args.historique,
|
|
blacklist=args.blacklist,
|
|
disp_adresse=args.adresse,
|
|
disp_telephone=args.telephone,
|
|
sshfp=args.sshfp,
|
|
ipsec=args.ipsec,
|
|
)
|
|
else:
|
|
print lc_ldap.printing.sprint_list(elem).encode(ENCODING)
|
|
print "%s résultats" % len(elem)
|
|
|
|
def explore_db(args):
|
|
"""Utilise le contenu de args pour décider comment explorer la base de données."""
|
|
data = search_ldap(args)
|
|
data = macro_expand(data, args)
|
|
data = limits(data, args)
|
|
|
|
return data
|
|
|
|
def search_ldap(args):
|
|
"""Cherche et trie"""
|
|
data = {}
|
|
if args.ldap:
|
|
search_filter = args.filtre.decode(ENCODING)
|
|
else:
|
|
search_filter = lfilter.human_to_ldap(args.filtre.decode(ENCODING))
|
|
|
|
if args.macro_filtre:
|
|
search_filter = filter_macro(search_filter)
|
|
elif args.wild:
|
|
search_filter = wild_search_filter(search_filter)
|
|
|
|
try:
|
|
resultats = LDAP.search(search_filter, sizelimit=args.limite)
|
|
except SIZELIMIT_EXCEEDED:
|
|
raise EnvironmentError("La limite de résultats LDAP (%s) a été dépassée. Vous pouvez l'augmenter avec l'option -l" % (args.limite,))
|
|
|
|
for elem in resultats:
|
|
if elem not in data.get(elem.__class__.__name__, []):
|
|
data.setdefault(elem.__class__.__name__, []).append(elem)
|
|
|
|
return data
|
|
|
|
def macro_expand(data, args):
|
|
"""Gère les macros spécifiques à whos_lc.
|
|
Permet de récupérer les propriétaires d'objets cherchés,
|
|
ou les factures ou les machines. De chercher par prise,
|
|
etc etc"""
|
|
|
|
new_data = dict(data)
|
|
|
|
if args.proprietaire:
|
|
for elem_list in data.itervalues():
|
|
for elem in elem_list:
|
|
if hasattr(elem, 'proprio'):
|
|
_proprio = elem.proprio()
|
|
|
|
# On a pas besoin du Crans dans le dico
|
|
if isinstance(_proprio, lc_ldap.objets.AssociationCrans):
|
|
continue
|
|
|
|
if _proprio not in data.get(_proprio.__class__.__name__, []):
|
|
new_data.setdefault(_proprio.__class__.__name__, []).append(_proprio)
|
|
args.adherent = True
|
|
|
|
return new_data
|
|
|
|
def filter_macro(filtre):
|
|
"""Étend les macros du filtre passé en argument"""
|
|
|
|
thetime = lc_ldap.crans_utils.to_generalized_time_format(time.time())
|
|
|
|
prise_match = MACRO_FILTRE_PRISE.match(filtre)
|
|
adhesion_match = MACRO_FILTRE_ADHESION.match(filtre)
|
|
connexion_match = MACRO_FILTRE_CONNEXION.match(filtre)
|
|
|
|
if prise_match:
|
|
prise = prise_match.groupdict()['prise']
|
|
bat = prise[0]
|
|
chbre = bat + annuaires_pg.reverse(bat, prise[1:])[0]
|
|
filtre = filtre.replace(u"(prise=%s)" % (prise,), u"(chbre=%s)" % (chbre,))
|
|
|
|
if adhesion_match:
|
|
args.limite = 0
|
|
filtre = filtre.replace(u"(adhesion=ok)", u"(&(finAdhesion>=%s)(|(aid=*)(cid=*)))" % (thetime,))
|
|
|
|
if connexion_match:
|
|
args.limite = 0
|
|
filtre = filtre.replace(u"(connexion=ok)", u"(&(finConnexion>=%s)(|(aid=*)(cid=*)))" % (thetime,))
|
|
|
|
return filtre
|
|
|
|
def wild_search_filter(filtre):
|
|
"""Recherche sur un gros volume d'attributs dans la base de données"""
|
|
|
|
kw = filtre[1:-1]
|
|
|
|
attr_list = [
|
|
u'nom', u'prenom', u'tel', u'mail', u'chbre', u'mailAlias', u'canonicalAlias', u'mailExt', u'uid',
|
|
u'macAddress', u'host', u'hostAlias', u'ipHostNumber', u'ip6HostNumber',
|
|
]
|
|
|
|
filtre = u"(|"
|
|
for elem in attr_list:
|
|
filtre += u"(%s=%s*)" % (elem, kw)
|
|
filtre += u")"
|
|
|
|
return filtre
|
|
|
|
def limits(data, args):
|
|
"""Applique les limitations dans la recherche.
|
|
Les cas sont a priori conflictuels.
|
|
|
|
"""
|
|
data_restricted = {}
|
|
data_restricted.update(data)
|
|
contentFilter = []
|
|
|
|
if args.adherent:
|
|
contentFilter = ["adherent"]
|
|
elif args.club:
|
|
contentFilter = ["club"]
|
|
elif args.machine:
|
|
contentFilter = ["machineFixe", "machineWifi", "machineCrans", "switchCrans", "borneWifi"]
|
|
elif args.crans:
|
|
contentFilter = ["machineCrans", "switchCrans", "borneWifi"]
|
|
elif args.switch:
|
|
contentFilter = ["switchCrans"]
|
|
elif args.borne:
|
|
contentFilter = ["borneWifi"]
|
|
# Special cases.
|
|
elif args.adm:
|
|
contentFilter = []
|
|
out = []
|
|
for machine in data.get('machineCrans', []):
|
|
if lc_ldap.crans_utils.find_rid_plage(machine['rid'][0].value)[0].startswith('adm'):
|
|
out.append(machine)
|
|
data_restricted = {'machineCrans' : out,}
|
|
elif args.special:
|
|
contentFilter = []
|
|
out = []
|
|
for machine in data.get('machineCrans', []):
|
|
if lc_ldap.crans_utils.find_rid_plage(machine['rid'][0].value)[0].startswith('special'):
|
|
out.append(machine)
|
|
data_restricted = {'machineCrans' : out,}
|
|
elif args.serveur:
|
|
contentFilter = []
|
|
out = []
|
|
for machine in data.get('machineCrans', []):
|
|
if lc_ldap.crans_utils.find_rid_plage(machine['rid'][0].value)[0].startswith('serveur'):
|
|
out.append(machine)
|
|
data_restricted = {'machineCrans' : out,}
|
|
|
|
if contentFilter:
|
|
data_restricted = {a: data.get(a, []) for a in contentFilter}
|
|
|
|
return data_restricted
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Recherche dans la base des adhérents", add_help=False)
|
|
parser.add_argument('-A', '--adresse', help="Affiche l'adresse de l'adhérent.", action="store_true")
|
|
parser.add_argument('-d', '--blacklist', type=int, help="Choix du nombre d'entrées blacklist à afficher pour les entrées détaillées.", action="store", default=10)
|
|
parser.add_argument('-h', '--help', help="Affiche ce message et quitte.", action="store_true")
|
|
parser.add_argument('-i', '--ipsec', help="Affichage de la clef wifi de la machine.", action="store_true")
|
|
parser.add_argument('-l', '--limite', type=int, help="Modifier la taille limite de recherche dans la base LDAP", action="store", default=1000)
|
|
parser.add_argument('-L', '--historique', type=int, help="Choix du nombre d'entrées d'historique à afficher pour les entrées détaillées.", action="store", default=10)
|
|
parser.add_argument('-s', '--sshfp', help="Affiche les fingerprint SSH si elles existent.", action="store_true")
|
|
parser.add_argument('-t', '--ldap', help="Utiliser les filtres tels que définis dans ldap", action="store_true")
|
|
parser.add_argument('-T', '--telephone', help="Afficher le numéro de téléphone de l'adhérent.", action="store_true")
|
|
parser.add_argument('--test', help="Se connecter à la base de test", action="store_true")
|
|
parser.add_argument('-v', '--verbose', help="Rend le script (très) verbeux.", action="store_true")
|
|
parser.add_argument('filtre', type=str, nargs="?", help="Le filtre whos à utiliser")
|
|
|
|
macro_group = parser.add_mutually_exclusive_group(required=False)
|
|
macro_group.add_argument('-f', '--macro-filtre', help="Flag activant la gestion des macros pour le filtre LDAP.", action="store_true")
|
|
macro_group.add_argument('-w', '--wild', help="Cherche de façon agressive dans la base de données à partir du filtre", action="store_true")
|
|
|
|
type_group = parser.add_mutually_exclusive_group(required=False)
|
|
type_group.add_argument('-a', '--adherent', help="Limite l'affichage aux adhérents.", action="store_true")
|
|
type_group.add_argument('--adm', help="Limite l'affichage aux machines adm.", action="store_true")
|
|
type_group.add_argument('-b', '--borne', help="Limite l'affichage aux bornes.", action="store_true")
|
|
type_group.add_argument('-c', '--club', help="Limite l'affichage aux clubs.", action="store_true")
|
|
type_group.add_argument('--crans', help="Limite l'affichage aux machines crans.", action="store_true")
|
|
type_group.add_argument('-m', '--machine', help="Limite l'affichage aux machines.", action="store_true")
|
|
type_group.add_argument('-P', '--proprietaire', help="Récupère le propriétaire de l'objet cherché.", action="store_true")
|
|
type_group.add_argument('--serveur', help="Limite l'affichage aux serveurs.", action="store_true")
|
|
type_group.add_argument('--special', help="Limite l'affichage aux machines spéciales.", action="store_true")
|
|
type_group.add_argument('--switch', help="Limite l'affichage aux switches (pas encore implémenté).", action="store_true")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.help:
|
|
parser.print_help()
|
|
sys.exit(0)
|
|
if args.test:
|
|
LDAP = lc_ldap.shortcuts.lc_ldap_test()
|
|
else:
|
|
LDAP = lc_ldap.shortcuts.lc_ldap_readonly()
|
|
|
|
print_data(explore_db(args), args)
|