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