From 90f0359403fcbaffcddd49a1ca4ff55719ba95cb Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 10 Jan 2021 13:26:30 -0800 Subject: Compile the NsJail config protobuf into Python code Include a helper shell script for compilation. --- scripts/protoc.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 scripts/protoc.sh (limited to 'scripts') diff --git a/scripts/protoc.sh b/scripts/protoc.sh new file mode 100755 index 0000000..5771b95 --- /dev/null +++ b/scripts/protoc.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +set -eu + +URL='https://raw.githubusercontent.com/google/nsjail/2.9/config.proto' +SRC_DIR='snekbox' +FILE_NAME='config' +PROTO_PATH="${SRC_DIR}/${FILE_NAME}.proto" + +curl -SsL "${URL}" -o "${PROTO_PATH}" +protoc --proto_path="${SRC_DIR}" --python_out="${SRC_DIR}" "${PROTO_PATH}" + +rm -f "${PROTO_PATH}" +mv -f "${SRC_DIR}/${FILE_NAME}_pb"*.py "${SRC_DIR}/${FILE_NAME}.py" -- cgit v1.2.3 From dab2a0ac4f9e5080865e77048c936ab279e5918d Mon Sep 17 00:00:00 2001 From: MarkKoz Date: Sun, 10 Jan 2021 21:19:44 -0800 Subject: Replace nsjpy alias with a Python script The Python script uses the same underlying code Falcon uses to invoke nsjail. It allows for the omission of redundant shell code that set up cgroups and nsjail args. This is also a step towards removing dependence on shell scripts and thus resolving #73. --- .github/workflows/lint-test-build-push.yaml | 1 - Pipfile | 1 + README.md | 6 +++--- scripts/.profile | 21 --------------------- scripts/dev.sh | 3 +-- snekbox/__main__.py | 28 ++++++++++++++++++++++++++++ 6 files changed, 33 insertions(+), 27 deletions(-) delete mode 100644 scripts/.profile create mode 100644 snekbox/__main__.py (limited to 'scripts') diff --git a/.github/workflows/lint-test-build-push.yaml b/.github/workflows/lint-test-build-push.yaml index 5aa2180..671e576 100644 --- a/.github/workflows/lint-test-build-push.yaml +++ b/.github/workflows/lint-test-build-push.yaml @@ -90,7 +90,6 @@ jobs: --hostname pdsnk-dev -e PYTHONDONTWRITEBYTECODE=1 -e PIPENV_PIPFILE='/snekbox/Pipfile' - -e ENV="${PWD}/scripts/.profile" --volume "${PWD}":"${PWD}" --workdir "${PWD}" --entrypoint /bin/bash diff --git a/Pipfile b/Pipfile index 5609128..2e86b25 100644 --- a/Pipfile +++ b/Pipfile @@ -41,6 +41,7 @@ testb = """ """ report = "coverage report" snekbox = "gunicorn -c config/gunicorn.conf.py snekbox.api.app" +eval = "python -m snekbox" devsh = "sh scripts/dev.sh" protoc = "sh scripts/protoc.sh" build = """ diff --git a/README.md b/README.md index 453eb4c..eaa3eb6 100644 --- a/README.md +++ b/README.md @@ -153,13 +153,13 @@ pipenv run devsh [--build [--clean]] [bash_args ...] #### Invoking NsJail -A shell alias named `nsjpy` is included and is basically `nsjail python -c ` but NsJail is configured as it would be if snekbox invoked it (such as the time and memory limits). It provides an easy way to run Python code inside NsJail without the need to run snekbox with its webserver and send HTTP requests. Example usage: +NsJail can be invoked in a more direction manner that does not require using a web server or its API. See `python -m snekbox --help`. Example usage: ```bash -nsjpy "print('hello world!')" +python -m snekbox 'print("hello world!")' --time_limit 0 ``` -The alias can be found in `./scripts/.profile`, which is automatically added when the shell is launched in the container. +With this command, NsJail uses the same configuration normally used through the web API. It also has an alias, `pipenv run eval`. [1]: https://github.com/python-discord/snekbox/workflows/Lint,%20Test,%20Build,%20Push/badge.svg?branch=master [2]: https://github.com/python-discord/snekbox/actions?query=workflow%3A%22Lint%2C+Test%2C+Build%2C+Push%22+branch%3Amaster diff --git a/scripts/.profile b/scripts/.profile deleted file mode 100644 index 11c8d78..0000000 --- a/scripts/.profile +++ /dev/null @@ -1,21 +0,0 @@ -nsjpy() { - local MEM_MAX=52428800 - - # All arguments except the last are considered to be for NsJail, not Python. - local nsj_args="" - while [ "$#" -gt 1 ]; do - nsj_args="${nsj_args:+${nsj_args} }$1" - shift - done - - # Set up cgroups and disable memory swapping. - mkdir -p /sys/fs/cgroup/pids/NSJAIL - mkdir -p /sys/fs/cgroup/memory/NSJAIL - echo "${MEM_MAX}" > /sys/fs/cgroup/memory/NSJAIL/memory.limit_in_bytes - echo "${MEM_MAX}" > /sys/fs/cgroup/memory/NSJAIL/memory.memsw.limit_in_bytes - - nsjail \ - --config "${NSJAIL_CFG:-/snekbox/config/snekbox.cfg}" \ - $nsj_args -- \ - /usr/local/bin/python -Squ -c "$@" -} diff --git a/scripts/dev.sh b/scripts/dev.sh index 3f94874..efbd93a 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -44,7 +44,6 @@ docker run \ --ipc="none" \ -e PYTHONDONTWRITEBYTECODE=1 \ -e PIPENV_PIPFILE="/snekbox/Pipfile" \ - -e BASH_ENV="${PWD}/scripts/.profile" \ --volume "${PWD}":"${PWD}" \ --workdir "${PWD}"\ --entrypoint /bin/bash \ @@ -52,7 +51,7 @@ docker run \ >/dev/null \ # Execute the given command(s) -docker exec -it snekbox_test /bin/bash --rcfile "${PWD}/scripts/.profile" "$@" +docker exec -it snekbox_test /bin/bash "$@" # Fix ownership of coverage file # BusyBox doesn't support --reference for chown diff --git a/snekbox/__main__.py b/snekbox/__main__.py new file mode 100644 index 0000000..a63fd3c --- /dev/null +++ b/snekbox/__main__.py @@ -0,0 +1,28 @@ +import argparse + +from snekbox.nsjail import NsJail + + +def parse_args() -> argparse.Namespace: + """Parse the command-line arguments and return the populated namespace.""" + parser = argparse.ArgumentParser(prog="snekbox", usage="%(prog)s code [nsjail_args ...]") + parser.add_argument("code", help="the Python code to evaluate") + parser.add_argument("nsjail_args", nargs="?", help="override configured NsJail options") + + # nsjail_args is just a dummy for documentation purposes. + # Its actual value comes from all the unknown arguments. + # There doesn't seem to be a better solution with argparse. + args, unknown = parser.parse_known_args() + args.nsjail_args = unknown + return args + + +def main() -> None: + """Evaluate Python code through NsJail.""" + args = parse_args() + result = NsJail().python3(args.code, *args.nsjail_args) + print(result.stdout) + + +if __name__ == "__main__": + main() -- cgit v1.2.3