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,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')) |