Skip to main content

EpicBox fork. Original package developers is StepicOrg.

Project description

Epicboxie

Forked from StepicOrg/epicbox for some improvements.

This fork allows to expose container ports with host machine and to work with sandbox interactively.

epicboxie.run_interactive is a context manager that runs sandbox:

import time
import requests
import epicboxie

epicboxie.configure(
    profiles=[
        epicboxie.Profile('python', 'python:3.6.5-alpine')
    ]
)

with open('server.py', 'rb') as f:
    contents = f.read()
files = [{'name': 'main.py', 'content': contents}]
limits = {'cputime': 1, 'memory': 64}
ports = {8000: 8000}

with epicboxie.run_interactive('python', 'python3 main.py', files=files, limits=limits, ports=ports) as run:
    time.sleep(2)
    print(requests.get('http://localhost:8000').status_code)

result = run.results

The ports parameter is also added to old run function.

Interaction with standard I/O is done with run.docker_interaction.read_sock() and run.docker_interaction.write_sock():

import time
import requests
import epicboxie

epicboxie.configure(
    profiles=[
        epicboxie.Profile('python', 'python:3.6.5-alpine')
    ]
)
files = [{'name': 'main.py', 'content': b'print(input("Input data: ")[::-1])'}]
limits = {'cputime': 1, 'memory': 64}
ports = {8000: 8000}

with epicboxie.run_interactive('python', 'python3 main.py', files=files, limits=limits, ports=ports) as run:
    time.sleep(0.5)
    prompt = run.docker_interaction.read_sock()[0].decode('utf8')  # read_sock returns tuple (stdout, stderr)
    run.docker_interaction.write_sock(input(prompt).encode())
    time.sleep(0.5)
    print(run.docker_interaction.read_sock()[0].decode('utf8'))

result = run.results

If you need to use old-style automatic interaction (pass whole stdin and wait for termination) when using run_interactive, you can use run.docker_interaction.interact(stdin, timeout, close=True)

Original README.md:

epicbox

Build Status

A Python library to run untrusted code in secure, isolated Docker based sandboxes. It is used to automatically grade programming assignments on Stepik.org.

It allows to spawn a process inside one-time Docker container, send data to stdin, and obtain its exit code and stdout/stderr output. It's very similar to what the subprocess module does but additionally you can specify a custom environment for the process (a Docker image) and limit the CPU, memory, disk, and network usage for the running process.

Usage

Run a simple Python script in a one-time Docker container using the python:3.6.5-alpine image:

import epicboxie

epicboxie.configure(
    profiles=[
        epicboxie.Profile('python', 'python:3.6.5-alpine')
    ]
)
files = [{'name': 'main.py', 'content': b'print(42)'}]
limits = {'cputime': 1, 'memory': 64}
result = epicbox.run('python', 'python3 main.py', files=files, limits=limits)

The result value is:

{'exit_code': 0,
 'stdout': b'42\n',
 'stderr': b'',
 'duration': 0.143358,
 'timeout': False,
 'oom_killed': False}

Available Limit Options

The available limit options and default values:

DEFAULT_LIMITS = {
    # CPU time in seconds, None for unlimited
    'cputime': 1,
    # Real time in seconds, None for unlimited
    'realtime': 5,
    # Memory in megabytes, None for unlimited
    'memory': 64,

    # limit the max processes the sandbox can have
    # -1 or None for unlimited(default)
    'processes': -1,
}

Advanced usage

A more advanced usage example of epicbox is to compile a C++ program and then run it multiple times on different input data. In this example epicbox will run containers on a dedicated Docker Swarm cluster instead of locally installed Docker engine:

import epicboxie

PROFILES = {
    'gcc_compile': {
        'docker_image': 'stepik/epicboxie-gcc:6.3.0',
        'user': 'root',
    },
    'gcc_run': {
        'docker_image': 'stepik/epicboxie-gcc:6.3.0',
        # It's safer to run untrusted code as a non-root user (even in a container)
        'user': 'sandbox',
        'read_only': True,
        'network_disabled': False,
    },
}
epicboxie.configure(profiles=PROFILES, docker_url='tcp://1.2.3.4:2375')

untrusted_code = b"""
// C++ program
#include <iostream>

int main() {
    int a, b;
    std::cin >> a >> b;
    std::cout << a + b << std::endl;
}
"""
# A working directory allows to preserve files created in a one-time container
# and access them from another one. Internally it is a temporary Docker volume.
with epicboxie.working_directory() as workdir:
    epicboxie.run('gcc_compile', 'g++ -pipe -O2 -static -o main main.cpp',
                files=[{'name': 'main.cpp', 'content': untrusted_code}],
                workdir=workdir)
    epicboxie.run('gcc_run', './main', stdin='2 2',
                limits={'cputime': 1, 'memory': 64},
                workdir=workdir)
    # {'exit_code': 0, 'stdout': b'4\n', 'stderr': b'', 'duration': 0.095318, 'timeout': False, 'oom_killed': False}
    epicboxie.run('gcc_run', './main', stdin='14 5',
                limits={'cputime': 1, 'memory': 64},
                workdir=workdir)
    # {'exit_code': 0, 'stdout': b'19\n', 'stderr': b'', 'duration': 0.10285, 'timeout': False, 'oom_killed': False}

Installation

epicbox can be installed by running pip install epicbox. It's tested on Python 3.4+ and Docker 1.12+.

You can also check the epicbox-images repository that contains Docker images used to automatically grade programming assignments on Stepik.org.

Contributing

Contributions are welcome, and they are greatly appreciated! More details can be found in CONTRIBUTING.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

epicboxie-1.1.1.dev4-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file epicboxie-1.1.1.dev4-py3-none-any.whl.

File metadata

  • Download URL: epicboxie-1.1.1.dev4-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.43.0 CPython/3.6.9

File hashes

Hashes for epicboxie-1.1.1.dev4-py3-none-any.whl
Algorithm Hash digest
SHA256 8924c58c20c5dd4b63497d7c74f48c637dcdf12c65d14d64be30be15c09b3d78
MD5 082794db2f4b2c6599c25451173043ec
BLAKE2b-256 594065d4bf85be72446db67a80d56ae964e77351dd041b5c6708f73e2cf6a6e1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page