new module: netxms

This commit is contained in:
José Lopes 2020-06-15 20:12:08 -03:00
parent 03a90b6239
commit 9bca20b010
6 changed files with 125 additions and 18 deletions

View File

@ -56,26 +56,24 @@ This script accesses [Prime](https://www.cisco.com/c/en/us/products/cloud-system
It is important to note everything was tested on Cisco Prime v3.4.0, using API v4. It was noticed that when trying to retrieve access points data, Prime requires more privileges, so you must explicitly inform that you wish this by using `Prime().run(access_points=True)`. It is important to note everything was tested on Cisco Prime v3.4.0, using API v4. It was noticed that when trying to retrieve access points data, Prime requires more privileges, so you must explicitly inform that you wish this by using `Prime().run(access_points=True)`.
## NetXMS Module
This module reads the full list of NetXMS' objects and searches for IPv4 addresses discarding loopback addresses. Unfortunately, NetXMS API is not well documented and it is quite different from other APIs, since it doesn't paginate and uses cookies for authentication. This way, querying NetXMS can take a couple of minutes depending on the number of records and it can downgrade the system.
## Tests ## Tests
Some basic tests are implemented under `tests`. This directory comes with a shell script to run all the tests at once, but before running it, remember to setup some environment variables required by them, such as `NETBOX_ADDRESS` and `NMAP_PATH`. Some basic tests are implemented under `tests`. This directory comes with a shell script to run all the tests at once, but before running it, remember to setup some environment variables required by them, such as `NETBOX_ADDRESS` and `NMAP_PATH`.
Here's the list of all variables: The script contains a list of all variables, but if you do not want to hardcode passwords, just make sure to export such variables in your shell and properly comment those lines.
```bash
NETBOX_ADDRESS
NETBOX_TOKEN
NMAP_PATH
PRIME_ADDRESS
PRIME_USER
PRIME_PASS
```
## New Modules ## New Modules
New modules should be implemented as a new file with the name of the module, for instance `nbs/netxms.py`. In this case, a class `NetXMS` should be created in this file with a method `run`. Finally, in `netbox-scanner.py`, a function `cmd_netxms` should be created to execute the just created class, and another option should be created both in the argument parsing section and in the if structure inside the main block. New modules should be implemented as a new file with the name of the module, for instance `nbs/netxms.py`. In this case, a class `NetXMS` should be created in this file with a method `run`. Finally, in `netbox-scanner.py`, a function `cmd_netxms` should be created to execute the just created class, and another option should be created both in the argument parsing section and in the if structure inside the main block.
## Contributors
- [Jarder Gonzalez](https://github.com/jfjunior) for the great NetXMS' API tips.
## License ## License
netbox-scanner is licensed under an MIT license --read `LICENSE` file for more information. netbox-scanner is licensed under an MIT license --read `LICENSE` file for more information.

50
nbs/netxms.py Normal file
View File

@ -0,0 +1,50 @@
from re import compile
from json import loads
from requests import session, post
re_ipv4 = compile(r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)')
class NetXMS(object):
def __init__(self, address, username, password, tls_verify, unknown):
self.netxms = Api(address, username, password, tls_verify)
self.unknown = unknown
self.hosts = list()
def run(self):
objects = self.netxms.all()
for obj in objects['objects']:
address = description = ''
try:
if obj['ipAddressList']:
for ip in obj['ipAddressList']:
if re_ipv4.match(ip) and not ip.startswith('127.'):
address = ip
break
else:
continue
except KeyError:
continue
try:
description = obj['objectName']
except KeyError:
description = self.unknown
if address:
self.hosts.append((address, description))
class Api(object):
def __init__(self, base_url, username, password, tls_verify=False):
self.base_url = base_url
self.session = session()
self.session.post(
f'{self.base_url}/sessions',
json={'login':username, 'password':password}
)
def all(self):
return loads(self.session.get(f'{self.base_url}/objects').text)

View File

@ -10,6 +10,15 @@ unknown = autodiscovered:netbox-scanner
tag = nmap tag = nmap
cleanup = yes cleanup = yes
[NETXMS]
address = https://netxms.domain
username =
password =
tls_verify = no
unknown = autodiscovered:netbox-scanner
tag = netxms
cleanup = yes
[PRIME] [PRIME]
address = https://prime.domain/webacs/api/v4 address = https://prime.domain/webacs/api/v4
username = username =

View File

@ -11,6 +11,7 @@ from urllib3.exceptions import InsecureRequestWarning
from nbs import NetBoxScanner from nbs import NetBoxScanner
from nbs.nmap import Nmap from nbs.nmap import Nmap
from nbs.netxms import NetXMS
from nbs.prime import Prime from nbs.prime import Prime
@ -27,12 +28,14 @@ else:
netbox = config['NETBOX'] netbox = config['NETBOX']
nmap = config['NMAP'] nmap = config['NMAP']
netxms = config['NETXMS']
prime = config['PRIME'] prime = config['PRIME']
parser = ArgumentParser(description='netbox-scanner') parser = ArgumentParser(description='netbox-scanner')
subparsers = parser.add_subparsers(title='Commands', dest='command') subparsers = parser.add_subparsers(title='Commands', dest='command')
subparsers.required = True subparsers.required = True
argsp = subparsers.add_parser('nmap', help='Nmap module') argsp = subparsers.add_parser('nmap', help='Nmap module')
argsp = subparsers.add_parser('netxms', help='NetXMS module')
argsp = subparsers.add_parser('prime', help='Cisco Prime module') argsp = subparsers.add_parser('prime', help='Cisco Prime module')
args = parser.parse_args() args = parser.parse_args()
@ -55,6 +58,17 @@ def cmd_nmap(s): # nmap handler
h.run() h.run()
s.sync(h.hosts) s.sync(h.hosts)
def cmd_netxms(s): # netxms handler
h = NetXMS(
netxms['address'],
netxms['username'],
netxms['password'],
netxms.getboolean('tls_verify'),
netxms['unknown']
)
h.run()
s.sync(h.hosts)
def cmd_prime(s): # prime handler def cmd_prime(s): # prime handler
h = Prime( h = Prime(
prime['address'], prime['address'],
@ -78,6 +92,10 @@ if __name__ == '__main__':
if args.command == 'nmap': if args.command == 'nmap':
cmd_nmap(scanner) cmd_nmap(scanner)
elif args.command == 'netxms':
scanner.tag = 'netxms'
scanner.cleanup = netxms.getboolean('cleanup')
cmd_netxms(scanner)
elif args.command == 'prime': elif args.command == 'prime':
scanner.tag = prime['tag'] scanner.tag = prime['tag']
scanner.cleanup = prime.getboolean('cleanup') scanner.cleanup = prime.getboolean('cleanup')

View File

@ -1,13 +1,26 @@
#!/bin/sh #!/bin/sh
# #
# Before running these tests, you must define some # Before running these tests, fill the environment variables
# environment variables, such as: # below according to your setup. If you don't want to
# # hardcode this data, just be sure to exporting them in
# $ export NETBOX_ADDRESS="https..." # your shell.
# $ export NETBOX_TOKEN="..."
# $ export NMAP_PATH="..."
## ##
export NETBOX_ADDRESS=""
export NETBOX_TOKEN=""
export NMAP_PATH=""
export PRIME_ADDRESS=""
export PRIME_USER=""
export PRIME_PASS=""
export NETXMS_ADDRESS=""
export NETXMS_USER=""
export NETXMS_PASS=""
python -m unittest tests.test_netbox python -m unittest tests.test_netbox
python -m unittest tests.test_nmap python -m unittest tests.test_nmap
python -m unittest tests.test_prime python -m unittest tests.test_prime
python -m unittest tests.test_netxms

19
tests/test_netxms.py Normal file
View File

@ -0,0 +1,19 @@
import unittest
from os import environ
from nbs.netxms import NetXMS
class TestRequest(unittest.TestCase):
def test_api(self):
address = environ.get('NETXMS_ADDRESS')
username = environ.get('NETXMS_USER')
password = environ.get('NETXMS_PASS')
netxms = NetXMS(address, username, password, False, 'unknown')
self.assertIsInstance(netxms, NetXMS)
netxms.run()
self.assertIsInstance(netxms.hosts, list)
if __name__ == '__main__':
unittest.main()