Merge branch 'beta-1.8' of https://github.com/HASecuritySolutions/VulnWhisperer into beta-1.8
This commit is contained in:
@ -26,16 +26,16 @@ class vwConfig(object):
|
||||
return self.config.getboolean(section, option)
|
||||
|
||||
def get_sections_with_attribute(self, attribute):
|
||||
sections = []
|
||||
sections = []
|
||||
# TODO: does this not also need the "yes" case?
|
||||
check = ["true", "True", "1"]
|
||||
for section in self.config.sections():
|
||||
check = ["true", "True", "1"]
|
||||
for section in self.config.sections():
|
||||
try:
|
||||
if self.get(section, attribute) in check:
|
||||
sections.append(section)
|
||||
except:
|
||||
self.logger.warn("Section {} has no option '{}'".format(section, attribute))
|
||||
return sections
|
||||
return sections
|
||||
|
||||
def exists_jira_profiles(self, profiles):
|
||||
# get list of profiles source_scanner.scan_name
|
||||
|
@ -63,8 +63,8 @@ class qualysWhisperAPI(object):
|
||||
|
||||
# First two columns are metadata we already have
|
||||
# Last column corresponds to "target_distribution_across_scanner_appliances" element
|
||||
# which doesn't follow the schema and breaks the pandas data manipulation
|
||||
return pd.read_json(scan_json).iloc[2:-1]
|
||||
# which doesn't follow the schema and breaks the pandas data manipulation
|
||||
return pd.read_json(scan_json).iloc[2:-1]
|
||||
|
||||
class qualysUtils:
|
||||
def __init__(self):
|
||||
|
0
vulnwhisp/test/__init__.py
Normal file
0
vulnwhisp/test/__init__.py
Normal file
75
vulnwhisp/test/mock.py
Normal file
75
vulnwhisp/test/mock.py
Normal file
@ -0,0 +1,75 @@
|
||||
import os
|
||||
import logging
|
||||
import httpretty
|
||||
|
||||
class mockAPI(object):
|
||||
def __init__(self, mock_dir=None, debug=False):
|
||||
self.mock_dir = mock_dir
|
||||
if not self.mock_dir:
|
||||
# Try to guess the mock_dir if python setup.py develop was used
|
||||
self.mock_dir = '/'.join(__file__.split('/')[:-3]) + '/test'
|
||||
|
||||
self.logger = logging.getLogger('mockAPI')
|
||||
|
||||
if debug:
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
self.logger.info('mockAPI initialised, API requests will be mocked'.format(self.mock_dir))
|
||||
self.logger.debug('Test path resolved as {}'.format(self.mock_dir))
|
||||
|
||||
def get_directories(self, path):
|
||||
dir, subdirs, files = next(os.walk(path))
|
||||
return subdirs
|
||||
|
||||
def get_files(self, path):
|
||||
dir, subdirs, files = next(os.walk(path))
|
||||
return files
|
||||
|
||||
def qualys_vuln_callback(self, request, uri, response_headers):
|
||||
self.logger.debug('Simulating response for {} ({})'.format(uri, request.body))
|
||||
if 'list' in request.parsed_body['action']:
|
||||
return [ 200,
|
||||
response_headers,
|
||||
open('{}/{}'.format(self.qualys_vuln_path, 'scans')).read()]
|
||||
elif 'fetch' in request.parsed_body['action']:
|
||||
try:
|
||||
response_body = open('{}/{}'.format(
|
||||
self.qualys_vuln_path,
|
||||
request.parsed_body['scan_ref'][0].replace('/', '_'))
|
||||
).read()
|
||||
except:
|
||||
# Can't find the file, just send an empty response
|
||||
response_body = ''
|
||||
return [200, response_headers, response_body]
|
||||
|
||||
def create_nessus_resource(self, framework):
|
||||
for filename in self.get_files('{}/{}'.format(self.mock_dir, framework)):
|
||||
method, resource = filename.split('_',1)
|
||||
resource = resource.replace('_', '/')
|
||||
self.logger.debug('Adding mocked {} endpoint {} {}'.format(framework, method, resource))
|
||||
httpretty.register_uri(
|
||||
getattr(httpretty, method), 'https://{}:443/{}'.format(framework, resource),
|
||||
body=open('{}/{}/{}'.format(self.mock_dir, framework, filename)).read()
|
||||
)
|
||||
|
||||
def create_qualys_vuln_resource(self, framework):
|
||||
# Create health check endpoint
|
||||
self.logger.debug('Adding mocked {} endpoint {} {}'.format(framework, 'GET', 'msp/about.php'))
|
||||
httpretty.register_uri(
|
||||
httpretty.GET,
|
||||
'https://{}:443/{}'.format(framework, 'msp/about.php'),
|
||||
body='')
|
||||
|
||||
self.logger.debug('Adding mocked {} endpoint {} {}'.format(framework, 'POST', 'api/2.0/fo/scan'))
|
||||
httpretty.register_uri(
|
||||
httpretty.POST, 'https://{}:443/{}'.format(framework, 'api/2.0/fo/scan/'),
|
||||
body=self.qualys_vuln_callback)
|
||||
|
||||
def mock_endpoints(self):
|
||||
for framework in self.get_directories(self.mock_dir):
|
||||
if framework in ['nessus', 'tenable']:
|
||||
self.create_nessus_resource(framework)
|
||||
elif framework == 'qualys_vuln':
|
||||
self.qualys_vuln_path = self.mock_dir + '/' + framework
|
||||
self.create_qualys_vuln_resource(framework)
|
||||
httpretty.enable()
|
@ -478,8 +478,9 @@ class vulnWhispererNessus(vulnWhispererBase):
|
||||
self.conn.close()
|
||||
self.logger.info('Scan aggregation complete! Connection to database closed.')
|
||||
else:
|
||||
|
||||
self.logger.error('Failed to use scanner at {host}:{port}'.format(host=self.hostname, port=self.nessus_port))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
class vulnWhispererQualys(vulnWhispererBase):
|
||||
@ -1244,6 +1245,7 @@ class vulnWhisperer(object):
|
||||
self.verbose = verbose
|
||||
self.source = source
|
||||
self.scanname = scanname
|
||||
self.exit_code = 0
|
||||
|
||||
|
||||
def whisper_vulnerabilities(self):
|
||||
@ -1254,15 +1256,15 @@ class vulnWhisperer(object):
|
||||
password=self.password,
|
||||
verbose=self.verbose,
|
||||
profile=self.profile)
|
||||
vw.whisper_nessus()
|
||||
self.exit_code += vw.whisper_nessus()
|
||||
|
||||
elif self.profile == 'qualys_web':
|
||||
vw = vulnWhispererQualys(config=self.config)
|
||||
vw.process_web_assets()
|
||||
self.exit_code += vw.process_web_assets()
|
||||
|
||||
elif self.profile == 'openvas':
|
||||
vw_openvas = vulnWhispererOpenVAS(config=self.config)
|
||||
vw_openvas.process_openvas_scans()
|
||||
self.exit_code += vw_openvas.process_openvas_scans()
|
||||
|
||||
elif self.profile == 'tenable':
|
||||
vw = vulnWhispererNessus(config=self.config,
|
||||
@ -1270,11 +1272,11 @@ class vulnWhisperer(object):
|
||||
password=self.password,
|
||||
verbose=self.verbose,
|
||||
profile=self.profile)
|
||||
vw.whisper_nessus()
|
||||
self.exit_code += vw.whisper_nessus()
|
||||
|
||||
elif self.profile == 'qualys_vuln':
|
||||
vw = vulnWhispererQualysVuln(config=self.config)
|
||||
vw.process_vuln_scans()
|
||||
self.exit_code += vw.process_vuln_scans()
|
||||
|
||||
elif self.profile == 'jira':
|
||||
#first we check config fields are created, otherwise we create them
|
||||
@ -1288,3 +1290,5 @@ class vulnWhisperer(object):
|
||||
return 0
|
||||
else:
|
||||
vw.jira_sync(self.source, self.scanname)
|
||||
|
||||
return self.exit_code
|
||||
|
Reference in New Issue
Block a user