Commit 6b7ffc655b74983648fd01515b0d00800891d1d9

Authored by Eduardo Santos
2 parents 2c229ccf 81be0a05
Exists in master

Adição dos comandos para ver como se comportam

cocar/commands/__init__.py 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +__author__ = 'eduardo'
  2 +from .scan_commands import ScanCommands
0 \ No newline at end of file 3 \ No newline at end of file
cocar/commands/scan_commands.py 0 → 100644
@@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
  1 +#!/bin/env python
  2 +# -*- coding: utf-8 -*-
  3 +__author__ = 'eduardo'
  4 +import logging
  5 +import os
  6 +import os.path
  7 +from paste.script import command
  8 +from .. import Cocar
  9 +from ..model import Base
  10 +from ..model.network import Network
  11 +from ..csv_utils import NetworkCSV
  12 +from ..session import NmapSession
  13 +from multiprocessing import Process, Queue
  14 +
  15 +log = logging.getLogger()
  16 +
  17 +
  18 +class ScanCommands(command.Command):
  19 + """
  20 + Comandos para realizar o scan da rede
  21 + Usage::
  22 + paster scan create_db -c <path to config file>
  23 + - Cria banco de dados
  24 + paster scan drop_db -c <path to config file>
  25 + - Remove banco de dados
  26 + paster scan networks -c <path to config file>
  27 + - Faz a busca das redes
  28 +
  29 + Os comandos devem ser executados a partir da raiz do módulo Cocar
  30 + """
  31 + max_args = 1
  32 + min_args = 1
  33 + summary = __doc__.split('\n')[0]
  34 + usage = __doc__
  35 + group_name = "Scan Commands"
  36 +
  37 + parser = command.Command.standard_parser(verbose=True)
  38 +
  39 + parser.add_option('-f', '--full',
  40 + action='store',
  41 + dest='full',
  42 + help='Full scan or regular scan'
  43 + )
  44 +
  45 + def __init__(self, name):
  46 + """
  47 + Constructor method
  48 +
  49 + """
  50 + super(ScanCommands, self).__init__(name)
  51 + self.cocar = Cocar(environment='production')
  52 + self.networks_dir = self.cocar.cocar_data_dir + "/networks"
  53 + self.networks_csv = self.cocar.config.get('cocar', 'networks_csv')
  54 + if not os.path.isdir(self.networks_dir):
  55 + os.mkdir(self.networks_dir)
  56 +
  57 + def command(self):
  58 + """
  59 + Parse command line arguments and call appropriate method.
  60 + """
  61 +
  62 + if not self.args or self.args[0] in ['--help', '-h', 'help']:
  63 + print(ScanCommands.__doc__)
  64 + return
  65 +
  66 + cmd = self.args[0]
  67 +
  68 + if cmd == 'create_db':
  69 + self.create_db()
  70 + return
  71 + if cmd == 'drop_db':
  72 + self.drop_db()
  73 + return
  74 + if cmd == 'load_networks':
  75 + self.load_networks()
  76 + return
  77 + if cmd == 'scan_networks':
  78 + self.scan_networks()
  79 + return
  80 + else:
  81 + log.error('Command "%s" not recognized' % (cmd,))
  82 +
  83 + def create_db(self):
  84 + """
  85 + Create database
  86 + """
  87 + Base.metadata.create_all(self.cocar.engine)
  88 +
  89 + def drop_db(self):
  90 + """
  91 + Drop database
  92 + """
  93 + Base.metadata.drop_all(self.cocar.engine)
  94 +
  95 + def load_networks(self):
  96 + """
  97 + Load networks from CSV file
  98 + """
  99 + networks_csv = NetworkCSV(csv_file=self.networks_csv)
  100 + session = self.cocar.Session
  101 + for elm in networks_csv.parse_csv():
  102 + results = session.query(Network).filter(Network.ip_network == elm.ip_network).first()
  103 + if results is None:
  104 + log.info("Adicionando a rede: %s", elm.network_ip)
  105 + session.add(elm)
  106 + else:
  107 + log.info("Rede já cadastrada: %s", elm.network_ip)
  108 + session.flush()
  109 + session.close()
  110 +
  111 + def scan_networks(self):
  112 + """
  113 + Scan all networks
  114 + """
  115 + processes = int(self.cocar.config.get('cocar', 'processes'))
  116 + # Create queues
  117 + task_queue = Queue()
  118 + done_queue = Queue()
  119 +
  120 + session = self.cocar.Session
  121 + results = session.query(Network).all()
  122 + for network in results:
  123 + network.network_ip = network.ip_network
  124 + if self.options.full is None:
  125 + nmap_session = NmapSession(
  126 + network.network_ip.cidr,
  127 + outfile=self.networks_dir + "/" + str(network.network_ip.cidr).replace("/", "-") + ".xml",
  128 + full=False
  129 + )
  130 + else:
  131 + nmap_session = NmapSession(
  132 + network.network_ip.cidr,
  133 + outfile=self.networks_dir + "/" + str(network.network_ip.cidr).replace("/", "-") + ".xml",
  134 + full=True
  135 + )
  136 + task_queue.put(nmap_session)
  137 +
  138 + #Start worker processes
  139 + for i in range(processes):
  140 + Process(target=worker, args=(task_queue, done_queue)).start()
  141 +
  142 + # Get and print results
  143 + print 'Unordered results:'
  144 + for i in range(len(results)):
  145 + print '\t', done_queue.get()
  146 +
  147 + # Tell child processes to stop
  148 + for i in range(processes):
  149 + task_queue.put('STOP')
  150 +
  151 +
  152 +def make_query(host):
  153 + """This does the actual snmp query
  154 +
  155 + This is a bit fancy as it accepts both instances
  156 + of SnmpSession and host/ip addresses. This
  157 + allows a user to customize mass queries with
  158 + subsets of different hostnames and community strings
  159 + """
  160 + return host.scan()
  161 +
  162 +
  163 +# Function run by worker processes
  164 +def worker(inp, output):
  165 + for func in iter(inp.get, 'STOP'):
  166 + result = make_query(func)
  167 + output.put(result)
0 \ No newline at end of file 168 \ No newline at end of file
cocar/model/network.py
1 #!/bin/env python 1 #!/bin/env python
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 __author__ = 'eduardo' 3 __author__ = 'eduardo'
  4 +from iptools.ipv4 import netmask2prefix
4 from netaddr import IPNetwork, IPSet 5 from netaddr import IPNetwork, IPSet
5 from ..model import Base 6 from ..model import Base
6 from sqlalchemy.schema import Column 7 from sqlalchemy.schema import Column
@@ -31,7 +32,7 @@ class Network(Base): @@ -31,7 +32,7 @@ class Network(Base):
31 :param cidr: CIDR para calcular a máscara da rede 32 :param cidr: CIDR para calcular a máscara da rede
32 :param name: Nome da rede 33 :param name: Nome da rede
33 """ 34 """
34 - self.network_ip = IPNetwork(network_ip) 35 + self.network_ip = network_ip
35 self.netmask = netmask 36 self.netmask = netmask
36 self.prefixlen = prefixlen 37 self.prefixlen = prefixlen
37 self.name = name 38 self.name = name
@@ -44,6 +45,19 @@ class Network(Base): @@ -44,6 +45,19 @@ class Network(Base):
44 # SQLAlchemy attribute 45 # SQLAlchemy attribute
45 self.ip_network = str(self.network_ip.ip) 46 self.ip_network = str(self.network_ip.ip)
46 47
  48 + @property
  49 + def network_ip(self):
  50 + return self._network_ip
  51 +
  52 + @network_ip.setter
  53 + def network_ip(self, value):
  54 + self._network_ip = IPNetwork(value)
  55 + if self._network_ip.prefixlen == 32:
  56 + if self.netmask is not None:
  57 + prefixlen = netmask2prefix(self.netmask)
  58 + self._network_ip = IPNetwork(str(self._network_ip.ip) + "/" + str(prefixlen))
  59 + self.prefixlen = prefixlen
  60 +
47 def ip_list(self): 61 def ip_list(self):
48 """ 62 """
49 Método que encontra a lista de IP's da subrede 63 Método que encontra a lista de IP's da subrede
cocar/query.py
@@ -50,7 +50,7 @@ def main(): @@ -50,7 +50,7 @@ def main():
50 for i in range(NUMBER_OF_PROCESSES): 50 for i in range(NUMBER_OF_PROCESSES):
51 Process(target=worker, args=(task_queue, done_queue)).start() 51 Process(target=worker, args=(task_queue, done_queue)).start()
52 52
53 - # Get and print results 53 + # Get and print results
54 print 'Unordered results:' 54 print 'Unordered results:'
55 for i in range(len(hosts)): 55 for i in range(len(hosts)):
56 print '\t', done_queue.get().query 56 print '\t', done_queue.get().query
cocar/session.py
@@ -62,7 +62,7 @@ class SnmpSession(Cocar): @@ -62,7 +62,7 @@ class SnmpSession(Cocar):
62 return self.hostrec 62 return self.hostrec
63 63
64 64
65 -class NmapSession(Cocar): 65 +class NmapSession(object):
66 """ 66 """
67 Realiza busca Nmap num ativo de rede 67 Realiza busca Nmap num ativo de rede
68 Inspirado em https://github.com/c0r3dump3d/pylanos 68 Inspirado em https://github.com/c0r3dump3d/pylanos
@@ -75,13 +75,12 @@ class NmapSession(Cocar): @@ -75,13 +75,12 @@ class NmapSession(Cocar):
75 """ 75 """
76 Parâmetros obrigatórios 76 Parâmetros obrigatórios
77 """ 77 """
78 - Cocar.__init__(self)  
79 self.host = host 78 self.host = host
80 self.full = full 79 self.full = full
81 if outfile is not None: 80 if outfile is not None:
82 self.outfile = outfile 81 self.outfile = outfile
83 else: 82 else:
84 - self.outfile = self.cocar_data_dir + "/" + str(self.host).replace("/", "-") + ".xml" 83 + self.outfile = str(self.host).replace("/", "-") + ".xml"
85 84
86 def scan(self): 85 def scan(self):
87 """ 86 """
development.ini-dist
1 [cocar] 1 [cocar]
2 data_dir = /srv/cocar-agente/cocar_data 2 data_dir = /srv/cocar-agente/cocar_data
  3 +netorks_csv = /srv/cocar-agente/cocar_data/networks.csv
  4 +processes = 4
3 5
4 [sqlalchemy] 6 [sqlalchemy]
5 url = sqlite:////srv/cocar-agente/cocar-data/tests/cocar-test.db 7 url = sqlite:////srv/cocar-agente/cocar-data/tests/cocar-test.db
@@ -7,7 +7,9 @@ requires = [ @@ -7,7 +7,9 @@ requires = [
7 'netaddr', 7 'netaddr',
8 'netifaces', 8 'netifaces',
9 'lxml', 9 'lxml',
10 - 'sqlalchemy' 10 + 'sqlalchemy',
  11 + 'PasteScript',
  12 + 'iptools'
11 ] 13 ]
12 14
13 15
@@ -23,4 +25,9 @@ setup( @@ -23,4 +25,9 @@ setup(
23 description='Agente coletor do software Cocar', 25 description='Agente coletor do software Cocar',
24 test_suite='cocar', 26 test_suite='cocar',
25 install_requires=requires, 27 install_requires=requires,
  28 + entry_points="""\
  29 + [paste.paster_command]
  30 + scan = cocar.commands:ScanCommands
  31 + """,
  32 +
26 ) 33 )