]> Vexing Labs - hector.git/commitdiff
First working code, thru paths
authorAdam A.G. Shamblin <adam.shamblin@pgi.com>
Tue, 11 Jun 2019 20:23:13 +0000 (14:23 -0600)
committerAdam A.G. Shamblin <adam.shamblin@pgi.com>
Tue, 11 Jun 2019 20:23:13 +0000 (14:23 -0600)
.gitignore [new file with mode: 0644]
README.md [new file with mode: 0644]
hector.py [new file with mode: 0644]
hector_template.yaml [new file with mode: 0644]
requirements.txt [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..10af746
--- /dev/null
@@ -0,0 +1,2 @@
+__pycache__
+output.yaml
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..ef17349
--- /dev/null
+++ b/README.md
@@ -0,0 +1,55 @@
+# Hector
+
+__Hector__ is an addon for the excellent [mitmproxy](https://mitmproxy.org)
+application, which captures and generates API documentation according to the
+[OpenAPI Specification](https://swagger.io/specification/).
+
+
+## Setup
+
+Create a virtual environment using your preferred method and install
+dependencies. Python 3 is strongly preferred.
+
+```shell
+$ python3 -mvenv ~/env/hector
+$ pip install -r requirements.txt
+```
+
+
+## Usage
+
+```shell
+$ mitmdump -s ./hector.py --set hector_template=template.yaml \
+                          --set hector_input=input.yaml \
+                          --set hector_output=output.yaml
+```
+
+__hector__ will write swagger for every host accessed during your mitmproxy
+session. At the end of the session all swagger data will be written to a single
+yaml file, separated by `--` per host.
+
+
+## Options
+
+### hector_template _(optional)_
+
+This option specifies the base yaml that will be used by __hector__. You may
+provide your own template, or the default, `hector_template.yaml` will be used
+
+### hector output _(optional)_
+
+This option specifies the file to which the swagger yaml will be written at the
+end of the session. Default: `output.yaml`
+
+### hector input _(optional)_
+
+This option allows you to load an existing swagger yaml, perhaps to resume a
+previous session. Default: `None`
+
+
+## TODO
+
+* Add parameter and response details
+* Add option to filter by host or regex
+* Optionally write to multiple files instead of just one
+* Post-process swagger to collapse on base-path
diff --git a/hector.py b/hector.py
new file mode 100644 (file)
index 0000000..e18ed78
--- /dev/null
+++ b/hector.py
@@ -0,0 +1,63 @@
+import copy
+import yaml
+from mitmproxy import ctx
+
+
+class Hector:
+
+    def __init__(self):
+        self._output = {}
+
+    def load(self, loader):
+        loader.add_option(
+                name='hector_template',
+                typespec=str,
+                default='./hector_template.yaml',
+                help='Yaml file to be used as base for swagger output.')
+
+        loader.add_option(
+                name='hector_output',
+                typespec=str,
+                default='./output.yaml',
+                help='Yaml file where the generated swagger will be output.')
+
+        loader.add_option(
+                name='hector_input',
+                typespec=str,
+                default='',
+                help='Swagger yaml file to be loaded and added to.')
+
+    def running(self):
+        with open(ctx.options.hector_template) as template:
+            self._template = yaml.load(template, Loader=yaml.Loader)
+
+        if ctx.options.hector_input != '':
+            with open(ctx.options.hector_input, 'r') as swagger:
+                for doc in yaml.load_all(swagger, Loader=yaml.Loader):
+                    print(doc)
+                    self._output[doc['host']] = doc
+
+    def done(self):
+        with open(ctx.options.hector_output, 'w') as output:
+            print(yaml.dump_all(self._output.values(),
+                                Dumper=yaml.Dumper), file=output)
+
+    def request(self, flow):
+        request = flow.request
+
+        if request.host not in self._output:
+            self._output[request.host] = copy.deepcopy(self._template)
+
+        target = self._output[request.host]
+        target['host'] = request.host
+
+        if request.scheme not in target['schemes']:
+            target['schemes'].append(request.scheme)
+
+        if request.path not in target:
+            target['paths'][request.path] = {}
+
+
+addons = [
+    Hector()
+]
diff --git a/hector_template.yaml b/hector_template.yaml
new file mode 100644 (file)
index 0000000..eae90b8
--- /dev/null
@@ -0,0 +1,13 @@
+swagger: '2.0'
+
+info:
+  version: 0.0.1
+  title: Test API
+  description: Dummy swagger specification
+
+schemes: []
+
+host: example.com
+basePath: /
+
+paths: {}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644 (file)
index 0000000..894157a
--- /dev/null
@@ -0,0 +1,3 @@
+flake8==3.7.7
+mitmproxy==4.0.4
+PyYAML==5.1.1