Home

Awesome

Flask-Shell2HTTP

flask-shell2http on pypi Build Status codecov CodeFactor <a href="https://lgtm.com/projects/g/Eshaan7/Flask-Shell2HTTP/context:python"> <img alt="Language grade: Python" src="https://img.shields.io/lgtm/grade/python/g/Eshaan7/Flask-Shell2HTTP.svg?logo=lgtm&logoWidth=18"/> </a>

A minimalist Flask extension that serves as a RESTful/HTTP wrapper for python's subprocess API.

Use Cases

Note: This extension is primarily meant for executing long-running shell commands/scripts (like nmap, code-analysis' tools) in background from an HTTP request and getting the result at a later time.

Documentation

Documentation Status

Quick Start

Dependencies
Installation
$ pip install flask flask_shell2http
Example Program

Create a file called app.py.

from flask import Flask
from flask_executor import Executor
from flask_shell2http import Shell2HTTP

# Flask application instance
app = Flask(__name__)

executor = Executor(app)
shell2http = Shell2HTTP(app=app, executor=executor, base_url_prefix="/commands/")

def my_callback_fn(context, future):
  # optional user-defined callback function
  print(context, future.result())

shell2http.register_command(endpoint="saythis", command_name="echo", callback_fn=my_callback_fn, decorators=[])

Run the application server with, $ flask run -p 4000.

With <10 lines of code, we succesfully mapped the shell command echo to the endpoint /commands/saythis.

Making HTTP calls

This section demonstrates how we can now call/ execute commands over HTTP that we just mapped in the example above.

$ curl -X POST -H 'Content-Type: application/json' -d '{"args": ["Hello", "World!"]}' http://localhost:4000/commands/saythis
<details><summary>or using python's requests module,</summary>
# You can also add a timeout if you want, default value is 3600 seconds
data = {"args": ["Hello", "World!"], "timeout": 60}
resp = requests.post("http://localhost:4000/commands/saythis", json=data)
print("Result:", resp.json())
</details>

Note: You can see the JSON schema for the POST request here.

returns JSON,

{
  "key": "ddbe0a94",
  "result_url": "http://localhost:4000/commands/saythis?key=ddbe0a94&wait=false",
  "status": "running"
}

Then using this key you can query for the result or just by going to the result_url,

$ curl http://localhost:4000/commands/saythis?key=ddbe0a94&wait=true # wait=true so we do not have to poll

Returns result in JSON,

{
  "report": "Hello World!\n",
  "key": "ddbe0a94",
  "start_time": 1593019807.7754705,
  "end_time": 1593019807.782958,
  "process_time": 0.00748753547668457,
  "returncode": 0,
  "error": null
}

Inspiration

This was initially made to integrate various command-line tools easily with Intel Owl, which I am working on as part of Google Summer of Code.

The name was inspired by the awesome folks over at msoap/shell2http.