Skip to content

Commit

Permalink
Merge pull request #31 from rmaskell/master
Browse files Browse the repository at this point in the history
Jenkins logging fix, array to bytes fix, req body keys fix
  • Loading branch information
KissPeter committed Feb 7, 2020
2 parents d424a78 + dc72743 commit 217ac1d
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 13 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ if you application can cope with the fuzzed parameters. Does not require coding.
### Work in progress
- [API Blueprint][]

## Pre-requirements
1. Python3
2. libcurl4-openssl-dev libssl-dev (for pycurl)

## Installation

Fetch the most recent code from GitHub
Expand Down
18 changes: 16 additions & 2 deletions apifuzzer/fuzzer_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,21 @@ def transmit(self, **kwargs):
url_part = url_part.decode()
_req_url.append(url_part.strip('/'))
kwargs.pop('url')
request_url = '/'.join(_req_url)
# Replace back the placeholder for '/'
# (this happens in expand_path_variables,
# but if we don't have any path_variables, it won't)
request_url = '/'.join(_req_url).replace('+', '/')
query_params = None
if kwargs.get('params') is not None:
query_params = self.format_pycurl_query_param(request_url, kwargs.get('params', {}))
kwargs.pop('params')
if kwargs.get('path_variables') is not None:
request_url = self.expand_path_variables(request_url, kwargs.get('path_variables'))
kwargs.pop('path_variables')
request_url = '{}{}'.format(request_url, query_params)
if kwargs.get('data') is not None:
kwargs['data'] = self.fix_data(kwargs.get('data'))
if query_params is not None:
request_url = '{}{}'.format(request_url, query_params)
self.logger.info('Request URL : {}'.format(request_url))
method = kwargs['method']
if isinstance(method, Bits):
Expand Down Expand Up @@ -316,6 +322,14 @@ def transmit(self, **kwargs):
except (UnicodeDecodeError, UnicodeEncodeError) as e: # request failure such as InvalidHeader
self.report_add_basic_msg(('Failed to parse http response code, exception occurred: %s', e))

@staticmethod
def fix_data(data):
new_data = {}
for data_key, data_value in data.items():
new_key = data_key.split('|')[-1]
new_data[new_key] = data_value
return new_data

def post_test(self, test_num):
"""Called after a test is completed, perform cleanup etc."""
if self.report.get('report') is None:
Expand Down
22 changes: 13 additions & 9 deletions apifuzzer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,26 @@ def get_sample_data_by_type(param_type):
u'integer': 1,
u'number': 667.5,
u'boolean': False,
u'array': ['a', 'b', 'c']
u'array': [1, 2, 3] # transform_data_to_bytes complains when this array contains strings.
}
return types.get(param_type, b'\x00')


def set_logger(level='warning'):
handler = logging.StreamHandler()
if os.path.exists('/dev/log'):
handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_LOCAL2)
handler.setFormatter(Formatter('%(process)d [%(levelname)s] %(name)s: %(message)s'))
logger = logging.getLogger()
def set_logger(level='warning', basic_output=False):
fmt = '%(process)d [%(levelname)s] %(name)s: %(message)s'
if (basic_output):
logging.basicConfig(format=fmt)
logger = logging.getLogger()
else:
handler = logging.StreamHandler()
if os.path.exists('/dev/log'):
handler = SysLogHandler(address='/dev/log', facility=SysLogHandler.LOG_LOCAL2)
handler.setFormatter(Formatter('%(process)d [%(levelname)s] %(name)s: %(message)s'))
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(level=level.upper())
logger.addHandler(handler)
return logger


def transform_data_to_bytes(data_in):
if isinstance(data_in, float):
return bytes(int(data_in))
Expand Down
21 changes: 19 additions & 2 deletions fuzzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

class Fuzzer(object):

def __init__(self, api_resources, report_dir, test_level, log_level, alternate_url=None, test_result_dst=None,
def __init__(self, api_resources, report_dir, test_level, log_level, basic_output, alternate_url=None, test_result_dst=None,
auth_headers=None):
self.api_resources = api_resources
self.base_url = None
Expand All @@ -31,7 +31,7 @@ def __init__(self, api_resources, report_dir, test_level, log_level, alternate_u
self.report_dir = report_dir
self.test_result_dst = test_result_dst
self.auth_headers = auth_headers if auth_headers else {}
self.logger = set_logger(log_level)
self.logger = set_logger(log_level, basic_output)
self.logger.info('APIFuzzer initialized')

def prepare(self):
Expand All @@ -54,6 +54,16 @@ def run(self):
fuzzer.set_interface(interface)
fuzzer.start()

def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1', 'True', 'T'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0', 'False', 'F'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')


if __name__ == '__main__':

Expand Down Expand Up @@ -104,6 +114,12 @@ def json_data(arg_string):
dest='log_level',
default='warning',
choices=[level.lower() for level in levelNames if isinstance(level, str)])
parser.add_argument('--basic_output',
type=str2bool,
required=False,
help='Use basic output for logging (useful if running in jenkins). Example --basic_output=True',
dest='basic_output',
default=False) # Useful if running in jenkins.
parser.add_argument('--headers',
type=json_data,
required=False,
Expand All @@ -125,6 +141,7 @@ def json_data(arg_string):
alternate_url=args.alternate_url,
test_result_dst=args.test_result_dst,
log_level=args.log_level,
basic_output=args.basic_output,
auth_headers=args.headers
)
prog.prepare()
Expand Down

0 comments on commit 217ac1d

Please sign in to comment.