Commit bab510508987041e9f38e8b3a0cc4ec3d1b200d1
Committed by
Eduardo Santos
Exists in
master
Importa as impressoras e melhora a identificação de ativos de rede que ainda não existem
Showing
3 changed files
with
200 additions
and
79 deletions
Show diff stats
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')) | ... | ... |