using pynetbox, logging improved

This commit is contained in:
José Lopes 2018-09-25 17:25:48 -03:00
parent 5d3e6972ac
commit f1327f2102
5 changed files with 70 additions and 50 deletions

View File

@ -3,13 +3,12 @@
NETBOX = { NETBOX = {
'ADDRESS': '', 'ADDRESS': '',
'TOKEN': '', 'TOKEN': '',
'TLS': True, 'TLS_VERIFY': True
'PORT': 443,
} }
TAG = 'auto' TAG = 'auto'
UNKNOWN_HOSTNAME = 'UNKNOWN HOST' UNKNOWN = 'UNKNOWN HOST'
DISABLE_TLS_WARNINGS = True # stop displaying TLS/SSL warnings? LOG = '.' # path to logfile
# These are the networks to be scanned. # These are the networks to be scanned.
# Example: ['192.168.40.0/20', '10.2.50.0/24'] # Example: ['192.168.40.0/20', '10.2.50.0/24']

View File

@ -1,22 +1,17 @@
import logging import logging
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
from ipaddress import IPv4Network from ipaddress import IPv4Network
from nmap import PortScanner from nmap import PortScanner
from cpe import CPE from cpe import CPE
from netbox import NetBox from pynetbox import api
class NetBoxScanner(object): class NetBoxScanner(object):
def __init__(self, host, tls, token, port, tag, unknown, warnings=True): def __init__(self, address, token, tls_verify, tag, unknown):
self.netbox = NetBox(host=host, use_ssl=tls, auth_token=token, self.netbox = api(address, token=token, ssl_verify=tls_verify)
port=port)
self.tag = tag self.tag = tag
self.unknown = unknown self.unknown = unknown
if warnings:
disable_warnings(InsecureRequestWarning)
def get_description(self, name, cpe): def get_description(self, name, cpe):
if name: if name:
@ -25,6 +20,21 @@ class NetBoxScanner(object):
c = CPE(cpe[0], CPE.VERSION_2_3) c = CPE(cpe[0], CPE.VERSION_2_3)
return '{}.{}.{}'.format(c.get_vendor()[0], return '{}.{}.{}'.format(c.get_vendor()[0],
c.get_product()[0], c.get_version()[0]) c.get_product()[0], c.get_version()[0])
def nbhandler(self, command, **kwargs):
if command == 'get':
return self.netbox.ipam.ip_addresses.get(
address=kwargs['address'])
elif command == 'create':
self.netbox.ipam.ip_addresses.create(address=kwargs['address'],
tags=kwargs['tag'], description=kwargs['description'])
elif command == 'update':
kwargs['nbhost'].description = kwargs['description']
kwargs['nbhost'].save()
elif command == 'delete':
kwargs['nbhost'].delete()
else:
raise AttributeError
def scan(self, network): def scan(self, network):
'''Scan a network. '''Scan a network.
@ -54,40 +64,48 @@ class NetBoxScanner(object):
:param networks: a list of valid networks, like ['10.0.0.0/8'] :param networks: a list of valid networks, like ['10.0.0.0/8']
:return: nothing will be returned :return: nothing will be returned
''' '''
create = update = delete = undiscovered = duplicate = 0
for net in networks: for net in networks:
logging.info('scan: {}'.format(net)) logging.info('scan: {}'.format(net))
hosts = self.scan(net) hosts = self.scan(net)
for host in hosts: for host in hosts:
nbhost = self.netbox.ipam.get_ip_addresses( try:
address=host['address']) nbhost = self.nbhandler('get', address=host['address'])
except ValueError:
logging.error('duplicate: {}/32'.format(host['address']))
duplicate += 1
continue
if nbhost: if nbhost:
if (self.tag in nbhost[0]['tags']) and ( if (self.tag in nbhost.tags) and (
host['description'] != nbhost[0]['description']): host['description'] != nbhost.description):
logging.warning('update: {} "{}" -> "{}"'.format( logging.warning('update: {} "{}" -> "{}"'.format(
host['address'], nbhost[0]['description'], str(nbhost.address), nbhost.description,
host['description'])) host['description']))
self.netbox.ipam.update_ip('{}/32'.format( self.nbhandler('update', nbhost=nbhost,
host['address']), description=host['description']) description=host['description'])
update += 1
else: else:
logging.info('create: {} "{}"'.format(host['address'], logging.info('create: {}/32 "{}"'.format(host['address'],
host['description'])) host['description']))
self.netbox.ipam.create_ip_address( self.netbox.ipam.ip_addresses.create(
'{}/32'.format(host['address']), address=host['address'], tags=[self.tag],
tags=[self.tag], description=host['description']) description=host['description'])
create += 1
for ipv4 in IPv4Network(net): for ipv4 in IPv4Network(net):
address = str(ipv4) address = str(ipv4)
if not any(h['address'] == address for h in hosts): if not any(h['address'] == address for h in hosts):
nbhost = self.netbox.ipam.get_ip_addresses( nbhost = self.nbhandler('get', address=address)
address=address)
try: try:
if self.tag in nbhost[0]['tags']: if self.tag in nbhost.tags:
logging.warning('delete: {} "{}"'.format( logging.warning('delete: {} "{}"'.format(
nbhost[0]['address'], nbhost.address, nbhost.description))
nbhost[0]['description'])) self.nbhandler('delete', nbhost=nbhost)
self.netbox.ipam.delete_ip_address(address) delete += 1
else: else:
logging.info('undiscovered: {}'.format( logging.info('undiscovered: {}'.format(
nbhost[0]['address'])) nbhost.address))
except IndexError: undiscovered += 1
except AttributeError:
pass pass
return (create, update, delete, undiscovered, duplicate)

View File

@ -4,38 +4,40 @@ import logging
from sys import stdout, stderr from sys import stdout, stderr
from argparse import ArgumentParser from argparse import ArgumentParser
from datetime import datetime from datetime import datetime
from urllib3 import disable_warnings
from urllib3.exceptions import InsecureRequestWarning
import config import config
from nbscan import NetBoxScanner from nbscan import NetBoxScanner
logging.basicConfig(filename='netbox-scanner-{}.log'.format(
datetime.now().strftime('%Y%m%dT%H%M%SZ')),
level=logging.INFO,
format='%(asctime)s\tnetbox-scanner\t%(levelname)s\t%(message)s')
argp = ArgumentParser() argp = ArgumentParser()
argp.add_argument('-l', '--log', help='logfile path', default=config.LOG)
argp.add_argument('-a', '--address', help='netbox address', argp.add_argument('-a', '--address', help='netbox address',
default=config.NETBOX['ADDRESS']) default=config.NETBOX['ADDRESS'])
argp.add_argument('-s', '--tls', help='netbox use tls',
action='store_true', default=config.NETBOX['TLS'])
argp.add_argument('-t', '--token', help='netbox access token', argp.add_argument('-t', '--token', help='netbox access token',
default=config.NETBOX['TOKEN']) default=config.NETBOX['TOKEN'])
argp.add_argument('-p', '--port', help='netbox access port', argp.add_argument('-v', '--verify', help='tls verify',
default=config.NETBOX['PORT']) action='store_true', default=config.NETBOX['TLS_VERIFY'])
argp.add_argument('-g', '--tag', help='netbox-scanner tag', argp.add_argument('-g', '--tag', help='netbox-scanner tag',
default=config.TAG) default=config.TAG)
argp.add_argument('-u', '--unknown', help='netbox-scanner unknown host', argp.add_argument('-u', '--unknown', help='netbox-scanner unknown host',
default=config.UNKNOWN_HOSTNAME) default=config.UNKNOWN)
argp.add_argument('-w', '--warnings', help='disable tls warnings',
action='store_true', default=config.DISABLE_TLS_WARNINGS)
argp.add_argument('-n', '--networks', nargs='+', help='networks to be scanned', argp.add_argument('-n', '--networks', nargs='+', help='networks to be scanned',
default=config.NETWORKS) default=config.NETWORKS)
args = argp.parse_args() args = argp.parse_args()
nbs = NetBoxScanner(args.address, args.tls, args.token, args.port, logging.basicConfig(filename='{}/netbox-scanner-{}.log'.format(args.log,
args.tag, args.unknown, args.warnings) datetime.now().strftime('%Y%m%dT%H%M%SZ')),
nbs.sync(args.networks) level=logging.INFO,
logging.info('finished') format='%(asctime)s\tnetbox-scanner\t%(levelname)s\t%(message)s')
disable_warnings(InsecureRequestWarning)
nbs = NetBoxScanner(args.address, args.token, args.verify, args.tag, args.unknown)
logging.info('started: {} networks'.format(len(args.networks)))
stats = nbs.sync(args.networks)
logging.info('finished: +{} ~{} -{} ?{} !{}'.format(stats[0], stats[1],
stats[2], stats[3], stats[4]))
exit(0) exit(0)

View File

@ -2,8 +2,9 @@ certifi==2018.8.24
chardet==3.0.4 chardet==3.0.4
cpe==1.2.1 cpe==1.2.1
idna==2.7 idna==2.7
ipaddress==1.0.22 netaddr==0.7.19
python-netbox==0.0.12 pynetbox==3.4.6
python-nmap==0.6.1 python-nmap==0.6.1
requests==2.19.1 requests==2.19.1
six==1.11.0
urllib3==1.23 urllib3==1.23

View File

@ -7,7 +7,7 @@ with open('README.md', 'r') as fh:
setuptools.setup( setuptools.setup(
name='netbox-scanner', name='netbox-scanner',
version='0.2.1', version='0.3.0',
author='José Lopes de Oliveira Jr.', author='José Lopes de Oliveira Jr.',
author_email='jlojunior@gmail.com', author_email='jlojunior@gmail.com',
description='A scanner util for NetBox', description='A scanner util for NetBox',