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 7 import lxml.etree
8 8 import time
9 9 import pickle
  10 +import requests
10 11 from paste.script import command
11 12 from .. import Cocar
12 13 from ..model import Base
... ... @@ -68,6 +69,12 @@ class ScanCommands(command.Command):
68 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 78 def __init__(self, name):
72 79 """
73 80 Constructor method
... ... @@ -121,6 +128,12 @@ class ScanCommands(command.Command):
121 128 if cmd == 'get_printer_attribute':
122 129 self.get_printer_attribute()
123 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 137 else:
125 138 log.error('Command "%s" not recognized' % (cmd,))
126 139  
... ... @@ -198,64 +211,8 @@ class ScanCommands(command.Command):
198 211 :return:
199 212 """
200 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 217 def get_printers(self):
261 218 """
... ... @@ -466,6 +423,115 @@ class ScanCommands(command.Command):
466 423  
467 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 536 def make_query(host):
471 537 """This does the actual snmp query
... ...
cocar/tests/test_persistence.py
... ... @@ -4,7 +4,9 @@ __author__ = 'eduardo'
4 4  
5 5 import unittest
6 6 import cocar.tests
  7 +import requests
7 8 import time
  9 +import json
8 10 from mock import patch
9 11 from ..xml_utils import NmapXML
10 12 from ..csv_utils import NetworkCSV
... ... @@ -244,6 +246,26 @@ class TestPersistence(unittest.TestCase):
244 246 result = self.session.query(PrinterCounter).all()
245 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 269 def tearDown(self):
248 270 """
249 271 Remove dados
... ...
cocar/xml_utils.py
... ... @@ -6,6 +6,7 @@ from lxml import etree
6 6 import model.computer
7 7 import model.printer
8 8 import model.host
  9 +from .session import SnmpSession
9 10  
10 11  
11 12 class NmapXML(object):
... ... @@ -85,33 +86,16 @@ class NmapXML(object):
85 86  
86 87 return True
87 88  
88   - def identify_host(self, hostname):
  89 + def identify_host(self,
  90 + hostname,
  91 + timeout=None):
89 92 if not self.hosts:
90 93 raise AttributeError("It is necessary do load XML file first")
91 94  
92 95 # Ordena os sistemas operacionais por accuracy
93 96 host = self.hosts[hostname]
94 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 99 scantime = int(host.get('endtime')) - int(host.get('starttime'))
116 100 #FIXME: Tem que encontrar uma forma melhor de identificar a impressora
117 101 for value in ['9100']:
... ... @@ -127,6 +111,36 @@ class NmapXML(object):
127 111 )
128 112  
129 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 144 else:
131 145 host = model.host.Host(
132 146 ip_address=hostname,
... ... @@ -138,6 +152,25 @@ class NmapXML(object):
138 152 )
139 153  
140 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 174 else:
142 175 # Não foi possível identificar. Só gera um host genérico
143 176 scantime = int(host.get('endtime')) - int(host.get('starttime'))
... ...