Skip to content

Commit

Permalink
small improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
KissPeter committed Feb 7, 2021
1 parent 26542f9 commit ccc4f5d
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 121 deletions.
10 changes: 9 additions & 1 deletion APIFuzzer
Expand Up @@ -6,6 +6,7 @@ import sys
import tempfile
from logging import _nameToLevel as levelNames

from apifuzzer.fuzz_utils import FailedToParseFileException
from apifuzzer.fuzzer import Fuzzer
from apifuzzer.utils import json_data, str2bool
from apifuzzer.version import get_version
Expand Down Expand Up @@ -88,6 +89,13 @@ if __name__ == '__main__':
api_definition_file=args.src_file,
junit_report_path=args.test_result_dst
)
prog.prepare()
try:
prog.prepare()
except FailedToParseFileException:
print('Failed to parse API definition')
exit(1)
except Exception as e:
print(f'Unexpected exception happened during fuzz test preparation: {e}. Feel free to report the issue')
exit(1)
signal.signal(signal.SIGINT, signal_handler)
prog.run()
19 changes: 15 additions & 4 deletions README.md
Expand Up @@ -13,10 +13,21 @@
APIFuzzer reads your API description and step by step fuzzes the fields to validate
if you application can cope with the fuzzed parameters. Does not require coding.

### Supported API Description Formats
## Main features
*Parse API definition from local file or remote URL
* JSON and YAML file format support
* GET, POST, PUT, POST, DELETE methods are supported
* Fuzzing of request body, query string, path parameter and request header are supported
* Support CI integration
* Generate JUnit XML test report format
* Send request to alternative URL
* Support HTTP basic auth from configuration
* Save report of failed test in JSON format into the pre-configured folder
* Log to stdout instead of syslog
* Configurable log level

### Supported API definition formats
- [Swagger][]

### Work in progress
- [OpenAPI][]

### Planned
Expand Down Expand Up @@ -61,7 +72,7 @@ optional arguments:
--src_url SRC_URL API definition url. JSON and YAML format is supported
-r REPORT_DIR, --report_dir REPORT_DIR
Directory where error reports will be saved. Default is temporally generated directory
--level LEVEL Test deepness: [1,2], higher is the deeper !!!Not implemented!!!
--level LEVEL Test deepness: [1,2], the higher is the deeper (In progress)
-u ALTERNATE_URL, --url ALTERNATE_URL
Use CLI defined url instead compile the url from the API definition. Useful for testing
-t TEST_RESULT_DST, --test_report TEST_RESULT_DST
Expand Down
2 changes: 1 addition & 1 deletion apifuzzer/__init__.py
@@ -1 +1 @@
__version__ = '0.9.8'
__version__ = '0.9.9'
12 changes: 8 additions & 4 deletions apifuzzer/apifuzzer_report.py → apifuzzer/apifuzzerreport.py
Expand Up @@ -4,14 +4,18 @@
from apifuzzer.utils import try_b64encode


class Apifuzzer_Report(Report):

def is_failed(self):
pass
class ApifuzzerReport(Report):

def __init__(self, name):
super().__init__(name)

def is_failed(self):
"""
.. deprecated:: 0.6.7
use :func:`~kitty.data.report.Report.get_status`
"""
raise NotImplementedError('API was changed, use get_status instead')

def to_dict(self, encoding='base64'):
"""
Return a dictionary version of the report
Expand Down
16 changes: 8 additions & 8 deletions apifuzzer/custom_fuzzers.py
Expand Up @@ -8,19 +8,20 @@


class Utf8Chars(BaseField):
"""
'''
This custom fuzzer iterates through the UTF8 chars and gives back random section between min and max length
Highly relies on random numbers so most probably will give you different values each time to run it.
You can generate the chars like this:
for st in range(0, 1114111):
try:
print('{}-> {}'.format(st, chr(st)))
except (UnicodeEncodeError, ValueError):
pass
:example:
>>>for st in range(0, 1114111):
>>> try:
>>> print(f'{st}-> {chr(st)}')
>>> except (UnicodeEncodeError, ValueError):
>>> pass
Above 1114111 chars started to getting unprocessable so this is the upper limit for now.
'''

"""
MAX = 1114111

def __init__(self, value, name, fuzzable=True, min_length=20, max_length=100, num_mutations=80):
Expand Down Expand Up @@ -61,7 +62,6 @@ def to_bits(self, val):
return Bits(self.str_to_bytes(val))

def _mutate(self):

current_value = list()
current_mutation_length = secure_randint(self.min_length, self.max_length)
for st in range(self.position, self.position + current_mutation_length):
Expand Down
2 changes: 1 addition & 1 deletion apifuzzer/fuzzer_target/fuzz_request_sender.py
Expand Up @@ -9,7 +9,7 @@
from junit_xml import TestSuite, TestCase, to_xml_report_file
from kitty.targets.server import ServerTarget

from apifuzzer.apifuzzer_report import Apifuzzer_Report as Report
from apifuzzer.apifuzzerreport import ApifuzzerReport as Report
from apifuzzer.fuzzer_target.request_base_functions import FuzzerTargetBase
from apifuzzer.utils import try_b64encode, init_pycurl, get_logger

Expand Down
10 changes: 10 additions & 0 deletions docs/Makefile
Expand Up @@ -2,11 +2,21 @@ SHELL:=$(shell which bash)
parent_dir:=$(shell dirname $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))))
.PHONY: all
all: clean
all: readme
all: apidoc
all: sphinx


SPHINXOPTS= -j 4 -d _build/doctrees .


.PHONY: readme
readme:
rm -f readme.md readme.rst
sed -e '1,/APIFuzzer — HTTP API Testing Framework/d' ../README.md > readme.md
m2r readme.md


.PHONY: sphinx
sphinx:
sphinx-build -b html $(SPHINXOPTS) _build/html
Expand Down
104 changes: 17 additions & 87 deletions docs/apifuzzer.rst
Expand Up @@ -4,93 +4,23 @@ apifuzzer package
Submodules
----------

apifuzzer.apifuzzer\_report module
----------------------------------

.. automodule:: apifuzzer.apifuzzer_report
:members:
:undoc-members:
:show-inheritance:

apifuzzer.base\_template module
-------------------------------

.. automodule:: apifuzzer.base_template
:members:
:undoc-members:
:show-inheritance:

apifuzzer.custom\_fuzzers module
--------------------------------

.. automodule:: apifuzzer.custom_fuzzers
:members:
:undoc-members:
:show-inheritance:

apifuzzer.exceptions module
---------------------------

.. automodule:: apifuzzer.exceptions
:members:
:undoc-members:
:show-inheritance:

apifuzzer.fuzz\_utils module
----------------------------

.. automodule:: apifuzzer.fuzz_utils
:members:
:undoc-members:
:show-inheritance:

apifuzzer.fuzzer module
-----------------------

.. automodule:: apifuzzer.fuzzer
:members:
:undoc-members:
:show-inheritance:

apifuzzer.openapi\_template\_generator module
---------------------------------------------

.. automodule:: apifuzzer.openapi_template_generator
:members:
:undoc-members:
:show-inheritance:

apifuzzer.server\_fuzzer module
-------------------------------

.. automodule:: apifuzzer.server_fuzzer
:members:
:undoc-members:
:show-inheritance:

apifuzzer.template\_generator\_base module
------------------------------------------

.. automodule:: apifuzzer.template_generator_base
:members:
:undoc-members:
:show-inheritance:

apifuzzer.utils module
----------------------

.. automodule:: apifuzzer.utils
:members:
:undoc-members:
:show-inheritance:

apifuzzer.version module
------------------------

.. automodule:: apifuzzer.version
:members:
:undoc-members:
:show-inheritance:
.. toctree::
:maxdepth: 4

apifuzzer.apifuzzerreport
apifuzzer.base_template
apifuzzer.custom_fuzzers
apifuzzer.exceptions
apifuzzer.fuzz_model
apifuzzer.fuzz_utils
apifuzzer.fuzzer
apifuzzer.move_json_parts
apifuzzer.openapi_template_generator
apifuzzer.resolve_json_reference
apifuzzer.server_fuzzer
apifuzzer.template_generator_base
apifuzzer.utils
apifuzzer.version

Module contents
---------------
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -4,4 +4,5 @@ Table of contents
=================

.. toctree::
readme
modules
1 change: 1 addition & 0 deletions docs/requirements.readthedocs.txt
Expand Up @@ -2,3 +2,4 @@ kittyfuzzer==0.7.4
ruamel.yaml==0.16.12
junit-xml==1.9
jsonpath-ng==1.5.2
m2r
37 changes: 22 additions & 15 deletions setup.py
Expand Up @@ -2,7 +2,6 @@
"""
Preparation instructions: https://packaging.python.org/tutorials/packaging-projects/
"""
import codecs
import os.path
import re

Expand All @@ -11,38 +10,46 @@
here = os.path.abspath(os.path.dirname(__file__))

__version__ = re.search(
r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]', # It excludes inline comment too
r'__version__\s*=\s*[\'"]([^\'"]*)[\'"]',
open("apifuzzer/__init__.py").read(),
).group(1)

REQUIREMENTS_FILE_PATH = os.path.join(
os.path.abspath(os.path.dirname(__file__)), "requirements.txt"
)

def get_readme():
readme = list()
with open(os.path.join(here, "README.md"), "r") as f:
skip_lines = True
for line in f.read().splitlines():
if line.startswith('# APIFuzzer — HTTP API Testing Framework'):
skip_lines = False
if skip_lines:
continue
else:
readme.append(line)
return '\n'.join(readme)

def read(*parts):
return codecs.open(os.path.join(here, *parts), 'r').read()

def get_requirements():
requirements = list()
with open(os.path.join(here, "requirements.txt"), "r") as f:
for line in f.read().splitlines():
if not line.startswith("#") and not line.startswith("--"):
requirements.append(line)
return '\n'.join(requirements)

with open(REQUIREMENTS_FILE_PATH, "r") as f:
REQUIREMENTS_FILE = [
line
for line in f.read().splitlines()
if not line.startswith("#") and not line.startswith("--")
]

setup_options = dict(
name='APIFuzzer',
version=__version__,
description='Fuzz test your application using Swagger or OpenAPI definition without coding',
long_description=read('README.md'),
long_description=get_readme(),
long_description_content_type="text/markdown",
author='Peter Kiss',
author_email='peter.kiss@linuxadm.hu',
url='https://github.com/KissPeter/APIFuzzer/',
scripts=['APIFuzzer'],
packages=find_packages(exclude=["test"]),
install_requires=REQUIREMENTS_FILE,
install_requires=get_requirements(),
license="GNU General Public License v3.0",
classifiers=[ # https://pypi.org/classifiers/
'Development Status :: 4 - Beta',
Expand Down

0 comments on commit ccc4f5d

Please sign in to comment.