Skip to content

Commit 9bca20b

Browse files
committed
new module: netxms
1 parent 03a90b6 commit 9bca20b

6 files changed

+124
-17
lines changed

README.md

+9-11
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,23 @@ This script accesses [Prime](https://www.cisco.com/c/en/us/products/cloud-system
5656
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)`.
5757

5858

59+
## NetXMS Module
60+
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.
61+
62+
5963
## Tests
6064
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`.
6165

62-
Here's the list of all variables:
66+
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.
6367

64-
```bash
65-
NETBOX_ADDRESS
66-
NETBOX_TOKEN
6768

68-
NMAP_PATH
69+
## New Modules
70+
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.
6971

70-
PRIME_ADDRESS
71-
PRIME_USER
72-
PRIME_PASS
73-
```
7472

73+
## Contributors
7574

76-
## New Modules
77-
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.
75+
- [Jarder Gonzalez](https://github.com/jfjunior) for the great NetXMS' API tips.
7876

7977

8078
## License

nbs/netxms.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from re import compile
2+
from json import loads
3+
4+
from requests import session, post
5+
6+
7+
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]?)')
8+
9+
10+
class NetXMS(object):
11+
def __init__(self, address, username, password, tls_verify, unknown):
12+
self.netxms = Api(address, username, password, tls_verify)
13+
self.unknown = unknown
14+
self.hosts = list()
15+
16+
def run(self):
17+
objects = self.netxms.all()
18+
19+
for obj in objects['objects']:
20+
address = description = ''
21+
try:
22+
if obj['ipAddressList']:
23+
for ip in obj['ipAddressList']:
24+
if re_ipv4.match(ip) and not ip.startswith('127.'):
25+
address = ip
26+
break
27+
else:
28+
continue
29+
except KeyError:
30+
continue
31+
try:
32+
description = obj['objectName']
33+
except KeyError:
34+
description = self.unknown
35+
36+
if address:
37+
self.hosts.append((address, description))
38+
39+
40+
class Api(object):
41+
def __init__(self, base_url, username, password, tls_verify=False):
42+
self.base_url = base_url
43+
self.session = session()
44+
self.session.post(
45+
f'{self.base_url}/sessions',
46+
json={'login':username, 'password':password}
47+
)
48+
49+
def all(self):
50+
return loads(self.session.get(f'{self.base_url}/objects').text)

netbox-scanner.conf

+9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ unknown = autodiscovered:netbox-scanner
1010
tag = nmap
1111
cleanup = yes
1212

13+
[NETXMS]
14+
address = https://netxms.domain
15+
username =
16+
password =
17+
tls_verify = no
18+
unknown = autodiscovered:netbox-scanner
19+
tag = netxms
20+
cleanup = yes
21+
1322
[PRIME]
1423
address = https://prime.domain/webacs/api/v4
1524
username =

netbox-scanner.py

+18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from nbs import NetBoxScanner
1313
from nbs.nmap import Nmap
14+
from nbs.netxms import NetXMS
1415
from nbs.prime import Prime
1516

1617

@@ -27,12 +28,14 @@
2728

2829
netbox = config['NETBOX']
2930
nmap = config['NMAP']
31+
netxms = config['NETXMS']
3032
prime = config['PRIME']
3133

3234
parser = ArgumentParser(description='netbox-scanner')
3335
subparsers = parser.add_subparsers(title='Commands', dest='command')
3436
subparsers.required = True
3537
argsp = subparsers.add_parser('nmap', help='Nmap module')
38+
argsp = subparsers.add_parser('netxms', help='NetXMS module')
3639
argsp = subparsers.add_parser('prime', help='Cisco Prime module')
3740
args = parser.parse_args()
3841

@@ -55,6 +58,17 @@ def cmd_nmap(s): # nmap handler
5558
h.run()
5659
s.sync(h.hosts)
5760

61+
def cmd_netxms(s): # netxms handler
62+
h = NetXMS(
63+
netxms['address'],
64+
netxms['username'],
65+
netxms['password'],
66+
netxms.getboolean('tls_verify'),
67+
netxms['unknown']
68+
)
69+
h.run()
70+
s.sync(h.hosts)
71+
5872
def cmd_prime(s): # prime handler
5973
h = Prime(
6074
prime['address'],
@@ -78,6 +92,10 @@ def cmd_prime(s): # prime handler
7892

7993
if args.command == 'nmap':
8094
cmd_nmap(scanner)
95+
elif args.command == 'netxms':
96+
scanner.tag = 'netxms'
97+
scanner.cleanup = netxms.getboolean('cleanup')
98+
cmd_netxms(scanner)
8199
elif args.command == 'prime':
82100
scanner.tag = prime['tag']
83101
scanner.cleanup = prime.getboolean('cleanup')

tests/run_tests.sh

+19-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
#!/bin/sh
22
#
3-
# Before running these tests, you must define some
4-
# environment variables, such as:
5-
#
6-
# $ export NETBOX_ADDRESS="https..."
7-
# $ export NETBOX_TOKEN="..."
8-
# $ export NMAP_PATH="..."
3+
# Before running these tests, fill the environment variables
4+
# below according to your setup. If you don't want to
5+
# hardcode this data, just be sure to exporting them in
6+
# your shell.
97
##
108

9+
export NETBOX_ADDRESS=""
10+
export NETBOX_TOKEN=""
11+
12+
export NMAP_PATH=""
13+
14+
export PRIME_ADDRESS=""
15+
export PRIME_USER=""
16+
export PRIME_PASS=""
17+
18+
export NETXMS_ADDRESS=""
19+
export NETXMS_USER=""
20+
export NETXMS_PASS=""
21+
22+
1123
python -m unittest tests.test_netbox
1224
python -m unittest tests.test_nmap
1325
python -m unittest tests.test_prime
26+
python -m unittest tests.test_netxms

tests/test_netxms.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import unittest
2+
from os import environ
3+
from nbs.netxms import NetXMS
4+
5+
6+
class TestRequest(unittest.TestCase):
7+
def test_api(self):
8+
address = environ.get('NETXMS_ADDRESS')
9+
username = environ.get('NETXMS_USER')
10+
password = environ.get('NETXMS_PASS')
11+
12+
netxms = NetXMS(address, username, password, False, 'unknown')
13+
self.assertIsInstance(netxms, NetXMS)
14+
netxms.run()
15+
self.assertIsInstance(netxms.hosts, list)
16+
17+
18+
if __name__ == '__main__':
19+
unittest.main()

0 commit comments

Comments
 (0)