aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christopher Goes <[email protected]>2019-03-19 18:48:33 -0600
committerGravatar Christopher Goes <[email protected]>2019-03-19 18:48:33 -0600
commit42f9140c413aba70b62c085f1d1f6b5356a684a0 (patch)
tree0221f692f7db4da6b66c8f96682e5eff01c77c71
parentAdd flake8-docstrings to Pipenv (diff)
Add docstrings
-rw-r--r--config.py5
-rw-r--r--rmq.py11
-rw-r--r--snekbox.py28
-rw-r--r--snekweb.py2
4 files changed, 33 insertions, 13 deletions
diff --git a/config.py b/config.py
index 846ad4a..10218eb 100644
--- a/config.py
+++ b/config.py
@@ -1,10 +1,10 @@
import os
import docker
from docker.errors import NotFound
-# import traceback
def autodiscover():
+ """Search for the snekbox container and return it's IPv4 address."""
container_names = ["rmq", "pdrmq", "snekbox_pdrmq_1"]
client = docker.from_env()
@@ -15,13 +15,10 @@ def autodiscover():
host = list(container.attrs.get('NetworkSettings').get('Networks').values())
host = host[0]['IPAddress']
return host
-
except NotFound:
continue
-
except Exception:
pass
- # print(traceback.format_exc())
return '127.0.0.1'
diff --git a/rmq.py b/rmq.py
index 493a38f..a0dade7 100644
--- a/rmq.py
+++ b/rmq.py
@@ -16,7 +16,8 @@ from config import EXCHANGE
from logs import log
-class Rmq(object):
+class Rmq:
+ """Rabbit MQ (RMQ) implementation used for communication with the bot."""
def __init__(self,
username=USERNAME,
@@ -42,6 +43,7 @@ class Rmq(object):
auto_delete=True) # Delete queue when all connection are closed
def consume(self, queue=QUEUE, callback=None, thread_ws=None, run_once=False):
+ """Subscribe to read from a RMQ channel."""
while True:
try:
connection = pika.BlockingConnection(self.con_params)
@@ -86,11 +88,8 @@ class Rmq(object):
time.sleep(2)
- def publish(self,
- message,
- queue=QUEUE,
- routingkey=ROUTING_KEY,
- exchange=EXCHANGE):
+ def publish(self, message, queue=QUEUE, routingkey=ROUTING_KEY, exchange=EXCHANGE):
+ """Open a connection to publish (write) to a RMQ channel."""
try:
connection = pika.BlockingConnection(self.con_params)
diff --git a/snekbox.py b/snekbox.py
index 37d7993..5f7b42f 100644
--- a/snekbox.py
+++ b/snekbox.py
@@ -7,14 +7,16 @@ import sys
from rmq import Rmq
-class Snekbox(object):
+class Snekbox:
+ """Core snekbox functionality, providing safe execution of Python code."""
+
def __init__(self,
nsjail_binary='nsjail',
python_binary=os.path.dirname(sys.executable)+os.sep+'python3.6'):
self.nsjail_binary = nsjail_binary
self.python_binary = python_binary
- self.nsjail_workaround()
+ self._nsjail_workaround()
env = {
'PATH': (
@@ -27,13 +29,23 @@ class Snekbox(object):
'PYTHONDONTWRITEBYTECODE': '1',
}
- def nsjail_workaround(self):
+ def _nsjail_workaround(self):
dirs = ['/sys/fs/cgroup/pids/NSJAIL', '/sys/fs/cgroup/memory/NSJAIL']
for d in dirs:
if not os.path.exists(d):
os.makedirs(d)
def python3(self, cmd):
+ """
+ Execute Python 3 code in a isolated environment.
+
+ The value of ``cmd`` is passed using '-c' to a Python
+ interpreter that is started in a ``nsjail``, isolating it
+ from the rest of the system.
+
+ Returns the output of executing the command (stdout) if
+ successful, or a error message if the execution failed.
+ """
args = [self.nsjail_binary, '-Mo',
'--rlimit_as', '700',
'--chroot', '/',
@@ -87,6 +99,15 @@ class Snekbox(object):
return output
def execute(self, body):
+ """
+ Handles execution of a raw JSON-formatted RMQ message, contained in ``body``.
+
+ The message metadata, including the Python code to be executed, is
+ extracted from the message body. The code is then executed in the
+ isolated environment, and the results of the execution published
+ to RMQ. Once published, the system exits, since the snekboxes
+ are created and disposed of per-execution.
+ """
msg = body.decode('utf-8')
result = ''
snek_msg = json.loads(msg)
@@ -102,6 +123,7 @@ class Snekbox(object):
exit(0)
def message_handler(self, ch, method, properties, body, thread_ws=None):
+ """Spawns a daemon process that handles RMQ messages."""
p = multiprocessing.Process(target=self.execute, args=(body,))
p.daemon = True
p.start()
diff --git a/snekweb.py b/snekweb.py
index 92e0436..2ed1034 100644
--- a/snekweb.py
+++ b/snekweb.py
@@ -24,11 +24,13 @@ log = app.logger
@app.route('/')
def index():
+ """Root path returns standard index.html."""
return render_template('index.html')
@sockets.route('/ws/<snekboxid>')
def websocket_route(ws, snekboxid):
+ """Opens a websocket that spawns and connects to a snekbox daemon."""
localdata = threading.local()
localdata.thread_ws = ws