Skip to content

Commit cc5586b

Browse files
committed
merged
2 parents 1048e88 + feff0a2 commit cc5586b

File tree

10 files changed

+247
-55
lines changed

10 files changed

+247
-55
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ script:
2121
- python test/report_test.py
2222
- python test/report_diff_test.py
2323
- python test/service_test.py
24+
- python test/test_backend_plugin_factory.py

libnmap/__init__.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,3 @@
77
__all__ = ["NmapHost", "NmapService", "NmapParser", "NmapParserException",
88
"NmapReport", "NmapProcess", "DictDiffer", "NmapDiff",
99
"NmapDiffException", "ReportDecoder", "ReportEncoder"]
10-
11-
#from diff import NmapDiff, DictDiffer, NmapDiffException
12-
#from common import NmapHost, NmapService
13-
#from process import NmapProcess
14-
#from parser import NmapParser, NmapParserException
15-
#from report import NmapReport, ReportDecoder, ReportEncoder

libnmap/plugins/backendplugin.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python
2+
3+
4+
class NmapBackendPlugin(object):
5+
def __init__(self):
6+
self.dbname = 'nmapdb'
7+
self.store = 'reports'
8+
9+
def insert(self, dict_data):
10+
raise NotImplementedError
11+
12+
def update(self, id):
13+
raise NotImplementedError
14+
15+
def delete(self, id):
16+
raise NotImplementedError
17+
18+
def get(self, id):
19+
raise NotImplementedError
20+
21+
def getall(self):
22+
"""return a list of all NmapReport saved in the backend
23+
TODO : add a filter capability
24+
"""
25+
raise NotImplementedError
26+
27+
def find(self, key):
28+
raise NotImplementedError
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env python
2+
import sys
3+
import inspect
4+
5+
6+
class BackendPluginFactory(object):
7+
8+
def create(self, plugin_name="mongodb", **kwargs):
9+
"""Import the needed lib and return an object NmapBackendPlugin
10+
representing the backend of your desire.
11+
NmapBackendPlugin is an abstract class, to know what argument
12+
need to be given, review the code of the subclass you need
13+
"""
14+
backendplugin = None
15+
plugin_path = "libnmap.plugins.%s" % (plugin_name)
16+
__import__(plugin_path)
17+
pluginobj = sys.modules[plugin_path]
18+
pluginclasses = inspect.getmembers(pluginobj, inspect.isclass)
19+
for classname, classobj in pluginclasses:
20+
if inspect.getmodule(classobj).__name__.find(plugin_path) == 0:
21+
backendplugin = classobj(**kwargs)
22+
return backendplugin

libnmap/plugins/dbplugin.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

libnmap/plugins/mongodb.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
11
#!/usr/bin/env python
2-
from libnmap.plugins.dbplugin import NmapDBPlugin
2+
import json
33
from pymongo import MongoClient
44
from bson.objectid import ObjectId
55

6+
from libnmap import ReportDecoder, ReportEncoder
7+
from libnmap.plugins.backendplugin import NmapBackendPlugin
68

7-
class NmapMongoPlugin(NmapDBPlugin):
9+
10+
class NmapMongoPlugin(NmapBackendPlugin):
811
def __init__(self, dbname=None, store=None, **kwargs):
9-
NmapDBPlugin.__init__(self)
12+
NmapBackendPlugin.__init__(self)
1013
if dbname is not None:
1114
self.dbname = dbname
1215
if store is not None:
1316
self.store = store
1417
self.dbclient = MongoClient(**kwargs)
1518
self.collection = self.dbclient[self.dbname][self.store]
1619

17-
def db_insert(self, dict_data):
18-
self.collection.insert(dict_data)
20+
def insert(self, report):
21+
# create a json object from an NmapReport instance
22+
j = json.dumps(report, cls=ReportEncoder)
23+
try:
24+
id = self.collection.insert(json.loads(j))
25+
except:
26+
print "MONGODB cannot insert"
27+
raise
28+
return id
1929

20-
def db_get(self, report_id=None):
30+
def get(self, report_id=None):
2131
rid = report_id
2232
if report_id is not None and isinstance(report_id, str):
2333
rid = ObjectId(report_id)
2434

2535
if isinstance(rid, ObjectId):
2636
r = self.collection.find({'_id': rid})
37+
nmapreport = json.loads(r, cls=ReportDecoder)
2738
else:
2839
r = self.collection.find()
2940
return r
3041

31-
def db_delete(self, report_id=None):
42+
def delete(self, report_id=None):
3243
if report_id is not None and isinstance(report_id, str):
3344
self.collection.remove({'_id': ObjectId(report_id)})
3445
else:

libnmap/plugins/sqlite.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env python
2+
import sqlite3
3+
4+
from libnmap import NmapReport
5+
from libnmap.plugins.backendplugin import NmapBackendPlugin
6+
7+
8+
class NmapSqlitePlugin(NmapBackendPlugin):
9+
def __init__(self, dbname=None):
10+
NmapBackendPlugin.__init__(self)
11+
conn = sqlite3.connect(dbname)
12+
curs = conn.cursor()
13+
# Create table if not exist
14+
curs.execute('''CREATE TABLE f not exists reports
15+
(date text, trans text, symbol text, qty real, price real)''')
16+
17+
def db_insert(self, nmap_report):
18+
nr = NmapReport()
19+
20+
pass
21+
22+
def db_get(self, report_id=None):
23+
pass
24+
25+
def db_delete(self, report_id=None):
26+
pass

libnmap/report.py

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#!/usr/bin/env python
2-
import json
32
import sys
43
import inspect
5-
from libnmap import NmapDiff, NmapHost, NmapService
4+
from libnmap import NmapDiff
5+
from libnmap.plugins.backendplugin import NmapBackendPlugin
66

77

88
class NmapReport(object):
@@ -36,6 +36,16 @@ def db(self, plugin_name="mongodb", **kwargs):
3636
r = classobj(**kwargs)
3737
return r
3838

39+
def save(self, backend):
40+
"""this fct get an NmapBackendPlugin representing the backend
41+
"""
42+
if backend is not None:
43+
#do stuff
44+
id = backend.insert(self)
45+
else:
46+
raise RuntimeError
47+
return id
48+
3949
def diff(self, other):
4050
if self._is_consistent() and other._is_consistent():
4151
r = NmapDiff(self, other)
@@ -119,21 +129,3 @@ def get_dict(self):
119129
@property
120130
def id(self):
121131
return hash(1)
122-
123-
124-
#class ReportEncoder(json.JSONEncoder):
125-
# def default(self, obj):
126-
# otype = {'NmapHost': NmapHost,
127-
# 'NmapService': NmapService,
128-
# 'NmapReport': NmapReport}
129-
# if isinstance(obj, tuple(otype.values())):
130-
# key = '__%s__' % obj.__class__.__name__
131-
# return {key: obj.__dict__}
132-
# return json.JSONEncoder.default(self, obj)
133-
#
134-
#
135-
#class ReportDecoder(json.JSONDecoder):
136-
# def decode(self, json_str):
137-
# raw_data = NmapParser.parse_fromdict(json.loads(json_str))
138-
# r = NmapReport(name=raw_data['_name'], raw_data=raw_data)
139-
# return r

libnmap/reportjson.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python
2+
import json
3+
from libnmap import NmapHost, NmapService, NmapReport, NmapParser
4+
5+
6+
class ReportEncoder(json.JSONEncoder):
7+
def default(self, obj):
8+
otype = {'NmapHost': NmapHost,
9+
'NmapService': NmapService,
10+
'NmapReport': NmapReport}
11+
if isinstance(obj, tuple(otype.values())):
12+
key = '__%s__' % obj.__class__.__name__
13+
return {key: obj.__dict__}
14+
return json.JSONEncoder.default(self, obj)
15+
16+
17+
class ReportDecoder(json.JSONDecoder):
18+
def decode(self, json_str):
19+
raw_data = NmapParser.parse_fromdict(json.loads(json_str))
20+
r = NmapReport(name=raw_data['_name'], raw_data=raw_data)
21+
return r
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python
2+
3+
import unittest
4+
import os
5+
from libnmap import NmapParser, NmapReport
6+
from libnmap.plugins.backendplugin import NmapBackendPlugin
7+
from libnmap.plugins.backendpluginFactory import BackendPluginFactory
8+
9+
#define all plugin that need test
10+
from libnmap.plugins.mongodb import NmapMongoPlugin
11+
from libnmap.plugins.sqlite import NmapSqlitePlugin
12+
13+
14+
class TestNmapBackendPlugin(unittest.TestCase):
15+
"""
16+
This testing class will create a testsuite for each plugins
17+
The following test need to be done :
18+
- test the factory
19+
- test all the method of the class NmapBackendPlugin:
20+
- Verify implmented/notImplemented
21+
- Verify the behaviour (ie insert must insert)
22+
Sample of code to implement for a new plugin:
23+
24+
def %plugintest_factory(self):
25+
pass
26+
27+
def %plugintest_insert(self):
28+
pass
29+
30+
def %plugintest_update(self):
31+
pass
32+
33+
def %plugintest_delete(self):
34+
pass
35+
36+
def %plugintest_get(self):
37+
pass
38+
39+
def %plugintest_getall(self):
40+
pass
41+
42+
def %plugintest_find(self):
43+
pass
44+
"""
45+
def setUp(self):
46+
fdir = os.path.dirname(os.path.realpath(__file__))
47+
self.flist_full = [{'file': "%s/%s" % (fdir, 'files/2_hosts.xml'),
48+
'hosts': 2},
49+
{'file': "%s/%s" % (fdir, 'files/1_hosts.xml'),
50+
'hosts': 1},
51+
{'file': "%s/%s" % (fdir,
52+
'files/1_hosts_banner_ports_notsyn.xml'),
53+
'hosts': 1},
54+
{'file': "%s/%s" % (fdir,
55+
'files/1_hosts_banner_ports.xml'),
56+
'hosts': 1},
57+
{'file': "%s/%s" % (fdir,
58+
'files/1_hosts_banner.xml'),
59+
'hosts': 1},
60+
{'file': "%s/%s" % (fdir,
61+
'files/2_hosts_version.xml'),
62+
'hosts': 2},
63+
{'file': "%s/%s" % (fdir,
64+
'files/2_tcp_hosts.xml'),
65+
'hosts': 2},
66+
{'file': "%s/%s" % (fdir,
67+
'files/1_hosts_nohostname.xml'),
68+
'hosts': 1}]
69+
self.flist = self.flist_full
70+
71+
def mongo_test_factory(self):
72+
"""Invoke factory and test that the object is of the right classes"""
73+
#create the backend factory object
74+
factory = BackendPluginFactory()
75+
mongodb = factory.create(plugin_name="mongodb")
76+
self.assertEqual(isinstance(mongodb, NmapBackendPlugin), True)
77+
self.assertEqual(isinstance(mongodb, NmapMongoPlugin), True)
78+
self.assertEqual(isinstance(mongodb, NmapSqlitePlugin), False)
79+
80+
def mongo_test_insert(self):
81+
""""best way to insert is to call save() of nmapreport"""
82+
for testfile in self.flist:
83+
fd = open(testfile['file'], 'r')
84+
s = fd.read()
85+
fd.close()
86+
87+
nr = NmapReport(NmapParser.parse(s))
88+
#create the backend factory object
89+
factory = BackendPluginFactory()
90+
mongodb = factory.create(plugin_name="mongodb")
91+
self.assertNotEqual(nr.save(mongodb),None)
92+
93+
def mongo_test_update(self):
94+
pass
95+
96+
def mongo_test_delete(self):
97+
pass
98+
99+
def mongo_test_get(self):
100+
pass
101+
102+
def mongo_test_getall(self):
103+
pass
104+
105+
def mongo_test_find(self):
106+
pass
107+
108+
if __name__ == '__main__':
109+
template_test_suite = ['test_factory',
110+
'test_insert',
111+
'test_update',
112+
'test_delete',
113+
'test_get',
114+
'test_getall',
115+
'test_find']
116+
117+
test_suite = ['mongo_test_factory', 'mongo_test_insert']
118+
suite = unittest.TestSuite(map(TestNmapBackendPlugin, test_suite))
119+
test_result = unittest.TextTestRunner(verbosity=5).run(suite)

0 commit comments

Comments
 (0)