Skip to content

Commit

Permalink
some improvement, report saving fails
Browse files Browse the repository at this point in the history
  • Loading branch information
KissPeter committed Oct 2, 2019
1 parent 58ca1d7 commit c581087
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 30 deletions.
30 changes: 21 additions & 9 deletions apifuzzer/fuzzer_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ def __init__(self, name, base_url, report_dir, logger):
self.logger = logger
self.logger.info('Logger initialized')

def try_b64encode(self, data_in):
try:
return b64encode(data_in)
except TypeError:
return data_in

def error_report(self, msg, req):
if hasattr(req, 'request'):
self.report.add('request method', req.request.method)
Expand All @@ -38,9 +44,14 @@ def error_report(self, msg, req):
for k, v in req.items():
if isinstance(v, dict):
for subkey, subvalue in v.items():
self.report.add(subkey, b64encode(subvalue))
try:
self.report.add(subkey, self.try_b64encode(subvalue))
except TypeError:
self.logger.error('Failed to add field ({}) or value ({}) to report because '
'unsupported type ({}), report the issue'.format(subkey, subvalue,
type(subvalue)))
else:
self.report.add(k, b64encode(v))
self.report.add(k, self.try_b64encode(subvalue))
self.report.set_status(Report.ERROR)
self.report.error(msg)

Expand All @@ -52,10 +63,10 @@ def save_report_to_disc(self):
except OSError:
pass
with open('{}/{}_{}.json'.format(self.report_dir, self.test_number, time()), 'wb') as report_dump_file:
report_dump_file.write(json.dumps(self.report.to_dict(), ensure_ascii=False, encoding='utf-8'))
report_dump_file.write(json.dumps(self.report.to_dict()))
except Exception as e:
self.logger.error('Failed to save report "{}" to {} because: {}'
.format(self.report.to_dict(), self.report_dir, e))
.format(self.report, self.report_dir, e))

def transmit(self, **kwargs):
self.logger.debug('Transmit: {}'.format(kwargs))
Expand All @@ -73,8 +84,10 @@ def transmit(self, **kwargs):
_req_url.append(url_part)
self.logger.warn('Request KWARGS:{}, url: {}'.format(kwargs, _req_url))
request_url = '/'.join(_req_url)
request_url = self.expand_path_variables(request_url, kwargs.get('path_variables'))
request_url = self.expand_path_variables(request_url, kwargs.get('params'))
if kwargs.get('path_variables') is not None:
request_url = self.expand_path_variables(request_url, kwargs.get('path_variables'))
if kwargs.get('params') is not None:
request_url = self.expand_path_variables(request_url, kwargs.get('params'))
self.logger.info('Request URL : {}'.format(request_url ))
if kwargs.get('path_variables'):
kwargs.pop('path_variables')
Expand All @@ -85,8 +98,7 @@ def transmit(self, **kwargs):
if isinstance(method , bytes):
method = method .decode()
kwargs.pop('method')
self.logger.warn('>>> Formatted URL: {} <<<'.format(request_url))
_return = requests.request(method=method, url=request_url **kwargs)
_return = requests.request(method=method, url=request_url, **kwargs)
status_code = _return.status_code
if status_code:
if status_code not in self.accepted_status_codes:
Expand All @@ -99,7 +111,7 @@ def transmit(self, **kwargs):
else:
self.error_report('Failed to parse http response code', _return.headers)
return _return
except (RequestException, UnicodeDecodeError) as e: # request failure such as InvalidHeader
except (RequestException, UnicodeDecodeError, UnicodeEncodeError) as e: # request failure such as InvalidHeader
self.error_report('Failed to parse http response code, exception: {}'.format(e), kwargs)

def post_test(self, test_num):
Expand Down
28 changes: 16 additions & 12 deletions apifuzzer/server_fuzzer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import print_function

import json

from binascii import hexlify
from kitty.data.report import Report
from kitty.fuzzers import ServerFuzzer
from kitty.model import Container, KittyException
Expand Down Expand Up @@ -50,14 +50,15 @@ def _transmit(self, node):
payload[key] = transform_data_to_bytes(node.get_field_by_name(key).render())
fuzz_places = ['params', 'headers', 'data', 'path_variables']
for place in fuzz_places:
self.logger.info('Transmit place: {}'.format(place))
# self.logger.info('Transmit place: {}'.format(place))
try:
param = node.get_field_by_name(place)
if isinstance(param, Container):
self.logger.info('Process param recursively: {}'.format(param))
payload[place] = self._recurse_params(param)
elif hasattr(param, 'render'):
payload[place] = param.render()
# if isinstance(param, Container):
_result = self._recurse_params(param)
self.logger.info('Process param recursively: {} gives: {}'.format(param, _result))
payload[place] = _result
# elif hasattr(param, 'render'):
# payload[place] = param.render()
except KittyException as e:
self.logger.warn('Exception occurred while processing {}: {}'.format(place, e.__str__()))
self.logger.info('Payload: {}'.format(payload))
Expand All @@ -74,6 +75,8 @@ def _recurse_params(param):
if isinstance(param, Container):
for field in param._fields:
_return[field.get_name()] = OpenApiServerFuzzer._recurse_params(field)
elif hasattr(param, 'render'):
_return = transform_data_to_bytes(param.render()).decode(errors='ignore')
return _return

def _store_report(self, report):
Expand All @@ -92,16 +95,17 @@ def _store_report(self, report):
data_report = Report('payload')
data_report.add('raw', payload)
try:
data_report.add('hex', json.dumps(str(payload)).encode('hex'))
except UnicodeDecodeError:
print('cant serialize payload: %', payload)
if isinstance(payload, dict):
data_report.add('hex', hexlify(json.dumps(str(payload), ensure_ascii=False)))
except (UnicodeDecodeError, TypeError):
print('Can not serialize payload: %', payload)
data_report.add('length', len(payload))
report.add('payload', data_report)
else:
report.add('payload', None)

self.dataman.store_report(report, self.model.current_index())
self.dataman.get_report_by_id(self.model.current_index())
# self.dataman.store_report(report, self.model.current_index())
# self.dataman.get_report_by_id(self.model.current_index())

def _test_environment(self):
sequence = self.model.get_sequence()
Expand Down
13 changes: 6 additions & 7 deletions apifuzzer/swagger_template_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from apifuzzer.utils import \
get_sample_data_by_type,\
get_fuzz_type_by_param_type, \
set_class_logger, \
transform_data_to_bytes


Expand All @@ -16,18 +15,18 @@ class ParamTypes(object):
FORM_DATA = 'formData'


@set_class_logger
class SwaggerTemplateGenerator(TemplateGenerator):

def __init__(self, api_resources):
def __init__(self, api_resources, logger):
self.api_resources = api_resources
self.templates = list()
self.logger = logger
self.logger.info('Logger initialized')

def process_api_resources(self):
self.logger.info('Start preparation')
for resource in self.api_resources['paths'].keys():
normalized_url = resource.lstrip('/').replace('/', '_')
normalized_url = resource.lstrip('/').replace('/', '_') #.replace('{','').replace('}','')
for method in self.api_resources['paths'][resource].keys():
self.logger.info('Resource: {} Method: {}'.format(resource, method))
for param in self.api_resources['paths'][resource][method].get('parameters', {}):
Expand All @@ -43,10 +42,10 @@ def process_api_resources(self):
# get parameter type: integer, string
# get format if present
param_type = param.get('in')
self.logger.info('Resource: {} Method: {} Parameter: {}, Parameter type: {}, Sample data: {}'
.format(resource, method, param, param_type, sample_data))

param_name = template_container_name
self.logger.debug('Resource: {} Method: {} Parameter: {}, Parameter type: {}, Sample data: {},'
'Param name: {}'
.format(resource, method, param, param_type, sample_data, param_name))
if param_type == ParamTypes.PATH:
template.path_variables.append(fuzz_type(name=param_name, value=str(sample_data)))
elif param_type == ParamTypes.HEADER:
Expand Down
2 changes: 1 addition & 1 deletion apifuzzer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def transform_data_to_bytes(data_in):
elif isinstance(data_in, Bits):
return data_in.tobytes()
else:
return bytes(data_in).decode()
return bytes(data_in)


def set_class_logger(class_name):
Expand Down
2 changes: 1 addition & 1 deletion fuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, api_resources, report_dir, test_level, log_level, alternate_u

def prepare(self):
# here we will be able to branch the template generator if we will support other than Swagger
template_generator = SwaggerTemplateGenerator(self.api_resources)
template_generator = SwaggerTemplateGenerator(self.api_resources, logger=self.logger)
template_generator.process_api_resources()
self.templates = template_generator.templates
self.base_url = template_generator.compile_base_url(self.alternate_url)
Expand Down

0 comments on commit c581087

Please sign in to comment.