Commit bab510508987041e9f38e8b3a0cc4ec3d1b200d1

Authored by Eduardo Santos
Committed by Eduardo Santos
2 parents f59cced5 0795fe05
Exists in master

Importa as impressoras e melhora a identificação de ativos de rede que ainda não existem

cocar/commands/scan_commands.py
@@ -7,6 +7,7 @@ import os.path @@ -7,6 +7,7 @@ import os.path
7 import lxml.etree 7 import lxml.etree
8 import time 8 import time
9 import pickle 9 import pickle
  10 +import requests
10 from paste.script import command 11 from paste.script import command
11 from .. import Cocar 12 from .. import Cocar
12 from ..model import Base 13 from ..model import Base
@@ -68,6 +69,12 @@ class ScanCommands(command.Command): @@ -68,6 +69,12 @@ class ScanCommands(command.Command):
68 help='Timeout da consulta SNMP' 69 help='Timeout da consulta SNMP'
69 ) 70 )
70 71
  72 + parser.add_option('-n', '--networks',
  73 + action='store',
  74 + dest='networks',
  75 + help='Arquivo individual de rede para ser carregado'
  76 + )
  77 +
71 def __init__(self, name): 78 def __init__(self, name):
72 """ 79 """
73 Constructor method 80 Constructor method
@@ -121,6 +128,12 @@ class ScanCommands(command.Command): @@ -121,6 +128,12 @@ class ScanCommands(command.Command):
121 if cmd == 'get_printer_attribute': 128 if cmd == 'get_printer_attribute':
122 self.get_printer_attribute() 129 self.get_printer_attribute()
123 return 130 return
  131 + if cmd == 'load_file':
  132 + self.load_file()
  133 + return
  134 + if cmd == 'import_printers':
  135 + self.import_printers()
  136 + return
124 else: 137 else:
125 log.error('Command "%s" not recognized' % (cmd,)) 138 log.error('Command "%s" not recognized' % (cmd,))
126 139
@@ -198,64 +211,8 @@ class ScanCommands(command.Command): @@ -198,64 +211,8 @@ class ScanCommands(command.Command):
198 :return: 211 :return:
199 """ 212 """
200 onlyfiles = [ f for f in os.listdir(self.networks_dir) if os.path.isfile(os.path.join(self.networks_dir, f)) ] 213 onlyfiles = [ f for f in os.listdir(self.networks_dir) if os.path.isfile(os.path.join(self.networks_dir, f)) ]
201 - for i in range(len(onlyfiles)):  
202 - network_file = self.networks_dir + "/" + onlyfiles[i]  
203 - log.info("Processando arquivo de rede %s", network_file)  
204 - nmap_xml = NmapXML(network_file)  
205 - try:  
206 - host_dict = nmap_xml.parse_xml()  
207 - except AttributeError, e:  
208 - log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message)  
209 - continue  
210 - except lxml.etree.XMLSyntaxError, e:  
211 - log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message)  
212 - continue  
213 -  
214 - if not host_dict:  
215 - log.error("File %s not found", network_file)  
216 - continue  
217 - session = self.cocar.Session  
218 - for hostname in nmap_xml.hosts.keys():  
219 - host = nmap_xml.identify_host(hostname)  
220 - if isinstance(host, Printer):  
221 - # Vê se a impressora já está na base  
222 - results = session.query(Printer).filter(Printer.network_ip == hostname).first()  
223 - if results is None:  
224 - log.info("Inserindo impressora com o IP %s", hostname)  
225 - try:  
226 - session.add(host)  
227 - session.flush()  
228 - except IntegrityError, e:  
229 - log.error("Erro adicionando impressora com o IP %s. IP Repetido\n%s", hostname, e.message)  
230 - else:  
231 - log.info("Impressora com o IP %s já cadastrada", hostname)  
232 - elif isinstance(host, Computer):  
233 - # Vê se o host já está na base  
234 - results = session.query(Computer).filter(Computer.network_ip == hostname).first()  
235 - if results is None:  
236 - log.info("Inserindo computador com o IP %s", hostname)  
237 - try:  
238 - session.add(host)  
239 - session.flush()  
240 - except IntegrityError, e:  
241 - log.error("Erro adicionando computador com o IP %s. IP Repetido\n%s", hostname, e.message)  
242 - else:  
243 - log.info("Computador com o IP %s já cadastrado", hostname)  
244 - else:  
245 - # Insere host genérico  
246 - results = session.query(Host).filter(Host.network_ip == hostname).first()  
247 - if results is None:  
248 - log.info("Inserindo host genérico com o IP %s", hostname)  
249 - try:  
250 - session.add(host)  
251 - session.flush()  
252 - except IntegrityError, e:  
253 - log.error("Erro adicionando host genérico com o IP %s. IP Repetido\n%s", hostname, e.message)  
254 - else:  
255 - log.info("Host genérico com o IP %s já cadastrado", hostname)  
256 -  
257 - #session.flush()  
258 - session.close() 214 + self.options.networks = onlyfiles
  215 + return self.load_file()
259 216
260 def get_printers(self): 217 def get_printers(self):
261 """ 218 """
@@ -466,6 +423,115 @@ class ScanCommands(command.Command): @@ -466,6 +423,115 @@ class ScanCommands(command.Command):
466 423
467 session.close() 424 session.close()
468 425
  426 + def load_file(self):
  427 + """
  428 + Load printers from networks files
  429 + :return:
  430 + """
  431 + onlyfiles = list()
  432 + if type(self.options.networks) == list:
  433 + for elm in self.options.networks:
  434 + onlyfiles.append(elm)
  435 + else:
  436 + onlyfiles.append(self.options.networks)
  437 +
  438 + for i in range(len(onlyfiles)):
  439 + network_file = self.networks_dir + "/" + onlyfiles[i]
  440 + log.info("Processando arquivo de rede %s", network_file)
  441 + nmap_xml = NmapXML(network_file)
  442 + try:
  443 + host_dict = nmap_xml.parse_xml()
  444 + except AttributeError, e:
  445 + log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message)
  446 + continue
  447 + except lxml.etree.XMLSyntaxError, e:
  448 + log.error("Erro realizando parsing do arquivo %s\n%s", network_file, e.message)
  449 + continue
  450 +
  451 + if not host_dict:
  452 + log.error("File %s not found", network_file)
  453 + continue
  454 + session = self.cocar.Session
  455 + for hostname in nmap_xml.hosts.keys():
  456 + host = nmap_xml.identify_host(hostname, timeout=self.options.timeout)
  457 + if isinstance(host, Printer):
  458 + # Vê se a impressora já está na base
  459 + results = session.query(Printer).filter(Printer.network_ip == hostname).first()
  460 + if results is None:
  461 + log.info("Inserindo impressora com o IP %s", hostname)
  462 + try:
  463 + session.add(host)
  464 + session.flush()
  465 + except IntegrityError, e:
  466 + log.error("Erro adicionando impressora com o IP %s. IP Repetido\n%s", hostname, e.message)
  467 + # Pode haver um host cadastrado que não havia sido identificado como impressora
  468 + teste = session.query(Host).filter(Host.network_ip == hostname).first()
  469 + if teste is not None:
  470 + # Adiciona a impressora
  471 + session.execute(
  472 + Printer.__table__.insert().values(
  473 + network_ip=hostname
  474 + )
  475 + )
  476 + session.flush()
  477 + log.info("Impressora %s adicionada novamente com sucesso", hostname)
  478 + else:
  479 + log.error("ERRO!!! Host não encontrado com o IP!!! %s", hostname)
  480 + else:
  481 + log.info("Impressora com o IP %s já cadastrada", hostname)
  482 + elif isinstance(host, Computer):
  483 + # Vê se o host já está na base
  484 + results = session.query(Computer).filter(Computer.network_ip == hostname).first()
  485 + if results is None:
  486 + log.info("Inserindo computador com o IP %s", hostname)
  487 + try:
  488 + session.add(host)
  489 + session.flush()
  490 + except IntegrityError, e:
  491 + log.error("Erro adicionando computador com o IP %s. IP Repetido\n%s", hostname, e.message)
  492 + else:
  493 + log.info("Computador com o IP %s já cadastrado", hostname)
  494 + else:
  495 + # Insere host genérico
  496 + results = session.query(Host).filter(Host.network_ip == hostname).first()
  497 + if results is None:
  498 + log.info("Inserindo host genérico com o IP %s", hostname)
  499 + try:
  500 + session.add(host)
  501 + session.flush()
  502 + except IntegrityError, e:
  503 + log.error("Erro adicionando host genérico com o IP %s. IP Repetido\n%s", hostname, e.message)
  504 + else:
  505 + log.info("Host genérico com o IP %s já cadastrado", hostname)
  506 +
  507 + #session.flush()
  508 + session.close()
  509 +
  510 + def import_printers(self):
  511 + """
  512 + Importa impressoras já cadastradas e não presentes na base local
  513 + :return:
  514 + """
  515 +
  516 + cocar_url = self.cocar.config.get('cocar', 'server_url')
  517 + printers_url = cocar_url + '/api/printer'
  518 + result = requests.get(printers_url)
  519 + result_json = result.json()
  520 + session = self.cocar.Session
  521 +
  522 + for elm in result_json['printers']:
  523 + printer = Printer(
  524 + ip_address=elm['network_ip']
  525 + )
  526 +
  527 + try:
  528 + session.add(printer)
  529 + session.flush()
  530 + except IntegrityError, e:
  531 + log.info("Impressora %s já cadastrada", elm['network_ip'])
  532 +
  533 + session.close()
  534 +
469 535
470 def make_query(host): 536 def make_query(host):
471 """This does the actual snmp query 537 """This does the actual snmp query
cocar/tests/test_persistence.py
@@ -4,7 +4,9 @@ __author__ = 'eduardo' @@ -4,7 +4,9 @@ __author__ = 'eduardo'
4 4
5 import unittest 5 import unittest
6 import cocar.tests 6 import cocar.tests
  7 +import requests
7 import time 8 import time
  9 +import json
8 from mock import patch 10 from mock import patch
9 from ..xml_utils import NmapXML 11 from ..xml_utils import NmapXML
10 from ..csv_utils import NetworkCSV 12 from ..csv_utils import NetworkCSV
@@ -244,6 +246,26 @@ class TestPersistence(unittest.TestCase): @@ -244,6 +246,26 @@ class TestPersistence(unittest.TestCase):
244 result = self.session.query(PrinterCounter).all() 246 result = self.session.query(PrinterCounter).all()
245 self.assertEqual(len(result), 0) 247 self.assertEqual(len(result), 0)
246 248
  249 + def test_import_printers(self):
  250 + """
  251 + Testa importação da rede
  252 + """
  253 + cocar_url = cocar.tests.cocar.config.get('cocar', 'server_url')
  254 + printers_url = cocar_url + '/api/printer'
  255 + result = requests.get(printers_url)
  256 + self.assertEqual(result.status_code, 200)
  257 +
  258 + result_json = result.json()
  259 + self.assertGreater(len(result_json), 0)
  260 +
  261 + for elm in result_json['printers']:
  262 + printer = Printer(
  263 + ip_address=elm['network_ip']
  264 + )
  265 +
  266 + self.session.add(printer)
  267 + self.session.flush()
  268 +
247 def tearDown(self): 269 def tearDown(self):
248 """ 270 """
249 Remove dados 271 Remove dados
cocar/xml_utils.py
@@ -6,6 +6,7 @@ from lxml import etree @@ -6,6 +6,7 @@ from lxml import etree
6 import model.computer 6 import model.computer
7 import model.printer 7 import model.printer
8 import model.host 8 import model.host
  9 +from .session import SnmpSession
9 10
10 11
11 class NmapXML(object): 12 class NmapXML(object):
@@ -85,33 +86,16 @@ class NmapXML(object): @@ -85,33 +86,16 @@ class NmapXML(object):
85 86
86 return True 87 return True
87 88
88 - def identify_host(self, hostname): 89 + def identify_host(self,
  90 + hostname,
  91 + timeout=None):
89 if not self.hosts: 92 if not self.hosts:
90 raise AttributeError("It is necessary do load XML file first") 93 raise AttributeError("It is necessary do load XML file first")
91 94
92 # Ordena os sistemas operacionais por accuracy 95 # Ordena os sistemas operacionais por accuracy
93 host = self.hosts[hostname] 96 host = self.hosts[hostname]
94 accuracy = int(0) 97 accuracy = int(0)
95 - if host.get('os'):  
96 - # Nesse caso já sei que é computador. Precisa identificar o OS  
97 - for os in host['os'].keys():  
98 - if int(host['os'][os]['accuracy']) > accuracy:  
99 - accuracy = int(host['os'][os]['accuracy'])  
100 - os_final = os  
101 -  
102 - scantime = int(host.get('endtime')) - int(host.get('starttime'))  
103 - computer = model.computer.Computer(  
104 - ip_address=hostname,  
105 - mac_address=host.get('mac'),  
106 - hostname=host.get('hostname'),  
107 - inclusion_date=host.get('endtime'),  
108 - scantime=scantime,  
109 - open_ports=host.get('ports'),  
110 - so=host['os'][os_final]  
111 - )  
112 -  
113 - return computer  
114 - elif host.get('ports'): 98 + if host.get('ports'):
115 scantime = int(host.get('endtime')) - int(host.get('starttime')) 99 scantime = int(host.get('endtime')) - int(host.get('starttime'))
116 #FIXME: Tem que encontrar uma forma melhor de identificar a impressora 100 #FIXME: Tem que encontrar uma forma melhor de identificar a impressora
117 for value in ['9100']: 101 for value in ['9100']:
@@ -127,6 +111,36 @@ class NmapXML(object): @@ -127,6 +111,36 @@ class NmapXML(object):
127 ) 111 )
128 112
129 return printer 113 return printer
  114 + else:
  115 + # Tenta ler o contador para identificar a impressora
  116 + snmp_session = SnmpSession(
  117 + DestHost=hostname,
  118 + Timeout=timeout
  119 + )
  120 + status = snmp_session.printer_counter()
  121 + if status is not None:
  122 + # Se conseguir ler o contador, é impressora
  123 + printer = model.printer.Printer(
  124 + ip_address=hostname,
  125 + mac_address=host.get('mac'),
  126 + hostname=host.get('hostname'),
  127 + inclusion_date=host.get('endtime'),
  128 + scantime=scantime,
  129 + open_ports=host['ports'],
  130 + )
  131 + return printer
  132 + else:
  133 + # Desiste e retorna host genérico
  134 + host = model.host.Host(
  135 + ip_address=hostname,
  136 + mac_address=host.get('mac'),
  137 + hostname=host.get('hostname'),
  138 + inclusion_date=host.get('endtime'),
  139 + scantime=scantime,
  140 + open_ports=host['ports'],
  141 + )
  142 +
  143 + return host
130 else: 144 else:
131 host = model.host.Host( 145 host = model.host.Host(
132 ip_address=hostname, 146 ip_address=hostname,
@@ -138,6 +152,25 @@ class NmapXML(object): @@ -138,6 +152,25 @@ class NmapXML(object):
138 ) 152 )
139 153
140 return host 154 return host
  155 + elif host.get('os'):
  156 + # Nesse caso já sei que é computador. Precisa identificar o OS
  157 + for os in host['os'].keys():
  158 + if int(host['os'][os]['accuracy']) > accuracy:
  159 + accuracy = int(host['os'][os]['accuracy'])
  160 + os_final = os
  161 +
  162 + scantime = int(host.get('endtime')) - int(host.get('starttime'))
  163 + computer = model.computer.Computer(
  164 + ip_address=hostname,
  165 + mac_address=host.get('mac'),
  166 + hostname=host.get('hostname'),
  167 + inclusion_date=host.get('endtime'),
  168 + scantime=scantime,
  169 + open_ports=host.get('ports'),
  170 + so=host['os'][os_final]
  171 + )
  172 +
  173 + return computer
141 else: 174 else:
142 # Não foi possível identificar. Só gera um host genérico 175 # Não foi possível identificar. Só gera um host genérico
143 scantime = int(host.get('endtime')) - int(host.get('starttime')) 176 scantime = int(host.get('endtime')) - int(host.get('starttime'))