diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abf9ff6..090344a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,10 +16,10 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.12'] + python-version: ['3.9', '3.12'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/setup.py b/setup.py index 83b0d0c..bf14fc7 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ def load_about(): packages=find_packages(exclude=["tests*"]), include_package_data=True, python_requires=">=3.8", - install_requires=["tutor>=18.0.0, <19"], + install_requires=["tutor>=19.0.0, <20"], entry_points={"tutor.plugin.v1": ["codejail = tutorcodejail.plugin"]}, classifiers=[ "Development Status :: 3 - Alpha", diff --git a/tutorcodejail/__about__.py b/tutorcodejail/__about__.py index f80932a..27a3495 100644 --- a/tutorcodejail/__about__.py +++ b/tutorcodejail/__about__.py @@ -1,2 +1,2 @@ """Helps you keep your cool when creating dozens of open edX and eduNEXT environments.""" -__version__ = "18.0.0" +__version__ = "19.0.0" diff --git a/tutorcodejail/patches/k8s-deployments b/tutorcodejail/patches/k8s-deployments index b828d2b..382b9c0 100644 --- a/tutorcodejail/patches/k8s-deployments +++ b/tutorcodejail/patches/k8s-deployments @@ -15,7 +15,7 @@ spec: app.kubernetes.io/name: codejailservice annotations: {% if CODEJAIL_ENFORCE_APPARMOR %} - container.apparmor.security.beta.kubernetes.io/codejailservice: "localhost/docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}" + container.apparmor.security.beta.kubernetes.io/codejailservice: "localhost/docker-edx-sandbox" {% endif %} spec: containers: diff --git a/tutorcodejail/patches/local-docker-compose-services b/tutorcodejail/patches/local-docker-compose-services index 28211ad..1ef2446 100644 --- a/tutorcodejail/patches/local-docker-compose-services +++ b/tutorcodejail/patches/local-docker-compose-services @@ -5,7 +5,7 @@ codejailservice: FLASK_APP_SETTINGS: codejailservice.tutor.ProductionConfig {% if CODEJAIL_ENFORCE_APPARMOR %} security_opt: - - apparmor:docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }} + - apparmor:docker-edx-sandbox {% endif %} volumes: - ../plugins/codejail/apps/config/tutor.py:/openedx/codejailservice/codejailservice/tutor.py:ro diff --git a/tutorcodejail/plugin.py b/tutorcodejail/plugin.py index 724825a..5865781 100644 --- a/tutorcodejail/plugin.py +++ b/tutorcodejail/plugin.py @@ -3,19 +3,22 @@ import os from glob import glob +from pathlib import Path import importlib_resources from tutor import hooks from .__about__ import __version__ +ABI_PATH = "/etc/apparmor.d/abi" + config = { "unique": { "SECRET_KEY": "{{ 24|random_string }}", }, "defaults": { "VERSION": __version__, - "APPARMOR_DOCKER_IMAGE": "docker.io/ednxops/codejail_apparmor_loader:latest", + "APPARMOR_DOCKER_IMAGE": "docker.io/ednxops/codejail_apparmor_loader:apparmor-3", "DOCKER_IMAGE": f"docker.io/ednxops/codejailservice:{__version__}", "ENABLE_K8S_DAEMONSET": False, "ENFORCE_APPARMOR": True, @@ -30,13 +33,41 @@ "MIN_REPLICAS": 1, "MAX_REPLICAS": 4, "AVG_CPU": 65, - "SERVICE_VERSION": "release/redwood.1", + "SERVICE_VERSION": "release/sumac.1", "SERVICE_REPOSITORY": "https://github.com/edunext/codejailservice.git", }, "overrides": {}, } +def get_apparmor_abi(): + """ + Return the default abi 3.0 rule if available in the system. + + AppArmor uses the Policy feature ABI to establish which rules it can + enforce based on the kernel capabilities. AppArmor profiles can include an + ABI rule to indicate the ABI they were developed under. If no rule is used + AppArmor will fallback to whichever rule is pinned in the + `/etc/apparmor/parser.conf` file. + + We try to use the 3.0 abi whenever it's available at `/etc/apparmor.d/abi/` + to guarantee that network rules are correctly enforced on newer versions of + the kernel. If the ABI is not present we don't set the abi rule and instead + rely on the default fallback. + + See: https://github.com/netblue30/firejail/issues/3659#issuecomment-711074899 + """ + if Path(f"{ABI_PATH}/3.0").exists(): + return "abi ," + return "" + + +hooks.Filters.ENV_TEMPLATE_VARIABLES.add_items( + [ + ("get_apparmor_abi", get_apparmor_abi()), + ] +) + # To add a custom initialization task, create a bash script template under: # tutorcodejail/templates/codejail/tasks/ # and then add it to the MY_INIT_TASKS list. Each task is in the format: diff --git a/tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox b/tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox index e25b4a6..73ad020 100644 --- a/tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox +++ b/tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox @@ -1,6 +1,8 @@ #include -profile docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }} flags=(attach_disconnected,mediate_deleted) { +{{ get_apparmor_abi }} + +profile docker-edx-sandbox flags=(attach_disconnected,mediate_deleted) { #include network, @@ -9,7 +11,7 @@ profile docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }} flags=(attach_d umount, signal (receive) peer=unconfined, signal (receive) peer=cri-containerd.apparmor.d, - signal (send,receive) peer=docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}, + signal (send,receive) peer=docker-edx-sandbox, deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir) # deny write to files not in /proc//** or /proc/sys/** @@ -30,7 +32,7 @@ profile docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }} flags=(attach_d deny /sys/firmware/** rwklx, deny /sys/kernel/security/** rwklx, - ptrace (trace,read) peer=docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}, + ptrace (trace,read) peer=docker-edx-sandbox, /sandbox/venv/bin/python Cx -> child, profile child flags=(attach_disconnected,mediate_deleted){ @@ -39,20 +41,18 @@ profile docker-edx-sandbox-{{ CODEJAIL_SANDBOX_PYTHON_VERSION }} flags=(attach_d # # Python abstractions adapted from https://gitlab.com/apparmor/apparmor/-/raw/master/profiles/apparmor.d/abstractions/python # - /opt/pyenv/versions/3.[0-9].*/lib/python3.[0-9]/**.{pyc,so} mr, - /opt/pyenv/versions/3.[0-9].*/lib/python3.[0-9]/**.{egg,py,pth} r, - /opt/pyenv/versions/3.[0-9].*/lib/python3.[0-9]/site-packages/ r, - /opt/pyenv/versions/3.[0-9].*/lib/python3.[0-9]/lib-dynload/*.so mr, - - /opt/pyenv/versions/3.[0-9].*/include/python3.[0-9]*/pyconfig.h r, - + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*/lib/python{3.[0-9],3.[1-9][0-9]}/**.{pyc,so} mr, + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*/lib/python{3.[0-9],3.[1-9][0-9]}/**.{egg,py,pth} r, + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*/lib/python{3.[0-9],3.[1-9][0-9]}/site-packages/ r, + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*/lib/python{3.[0-9],3.[1-9][0-9]}/lib-dynload/*.so mr, + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*/include/python{3.[0-9],3.[1-9][0-9]}*/pyconfig.h r, # # Whitelist particiclar shared objects from the system # python installation # /sandbox/venv/** mr, - /opt/pyenv/versions/{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}_sandbox/** mr, + /opt/pyenv/versions/{3.[0-9],3.[1-9][0-9]}.*_sandbox/** mr, /tmp/codejail-*/ rix, /tmp/codejail-*/** wrix, /tmp/* wrix, diff --git a/tutorcodejail/templates/codejail/build/codejail/Dockerfile b/tutorcodejail/templates/codejail/build/codejail/Dockerfile index 654089c..868740a 100644 --- a/tutorcodejail/templates/codejail/build/codejail/Dockerfile +++ b/tutorcodejail/templates/codejail/build/codejail/Dockerfile @@ -1,41 +1,42 @@ -FROM docker.io/ubuntu:22.04 as minimal -MAINTAINER edunext.co +FROM docker.io/ubuntu:22.04 AS minimal +LABEL mantainer="edunext.co " ENV DEBIAN_FRONTEND=noninteractive RUN apt update && \ apt install -y build-essential curl git language-pack-en llvm -ENV LC_ALL en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 ###### Install python with pyenv in /opt/pyenv and create virtualenv in /openedx/venv -FROM minimal as python +FROM minimal AS python # https://github.com/pyenv/pyenv/wiki/Common-build-problems#prerequisites RUN apt update && \ apt install -y libssl-dev zlib1g-dev libbz2-dev \ libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \ xz-utils tk-dev libffi-dev liblzma-dev python3-openssl git subversion -ENV PYENV_ROOT /opt/pyenv +ENV PYENV_ROOT=/opt/pyenv RUN git clone https://github.com/pyenv/pyenv $PYENV_ROOT --branch v2.4.0 --depth 1 ARG CODEJAILSERVICE_PYTHON_VERSION=3.11.9 RUN $PYENV_ROOT/bin/pyenv install $CODEJAILSERVICE_PYTHON_VERSION -ARG SANDBOX_PYTHON_VERSION={{ CODEJAIL_SANDBOX_PYTHON_VERSION }} +ARG SANDBOX_PYTHON_VERSION="{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}" RUN git clone https://github.com/esinker/pyenv-version-alias $PYENV_ROOT/plugins/pyenv-alias -RUN VERSION_ALIAS={{ CODEJAIL_SANDBOX_PYTHON_VERSION }}_sandbox $PYENV_ROOT/bin/pyenv install -f $SANDBOX_PYTHON_VERSION +RUN VERSION_ALIAS="{{ CODEJAIL_SANDBOX_PYTHON_VERSION }}_sandbox" \ + $PYENV_ROOT/bin/pyenv install -f $SANDBOX_PYTHON_VERSION -RUN $PYENV_ROOT/versions/$CODEJAILSERVICE_PYTHON_VERSION/bin/python -m venv /openedx/venv -RUN $PYENV_ROOT/versions/"$SANDBOX_PYTHON_VERSION"_sandbox/bin/python -m venv --copies /sandbox/venv +RUN "$PYENV_ROOT/versions/$CODEJAILSERVICE_PYTHON_VERSION/bin/python" -m venv /openedx/venv +RUN "$PYENV_ROOT/versions/"$SANDBOX_PYTHON_VERSION"_sandbox/bin/python" -m venv --copies /sandbox/venv ###### Codejail service code -FROM minimal as code +FROM minimal AS code RUN git clone {{ CODEJAIL_SERVICE_REPOSITORY }} --branch {{ CODEJAIL_SERVICE_VERSION }} --depth 1 /openedx/codejailservice WORKDIR /openedx/codejailservice ###### Install python requirements in virtualenv -FROM python as codejailservice-python-requirements +FROM python AS codejailservice-python-requirements -ENV PATH /openedx/venv/bin:${PATH} -ENV VIRTUAL_ENV /openedx/venv/ +ENV PATH=/openedx/venv/bin:${PATH} +ENV VIRTUAL_ENV=/openedx/venv/ COPY --from=code /openedx/codejailservice /openedx/codejailservice WORKDIR /openedx/codejailservice @@ -43,16 +44,19 @@ RUN pip3 install -r requirements/base.txt RUN pip3 install uwsgi==2.0.21 ###### Install python requirements in virtualenv -FROM python as sandbox-python-requirements +FROM python AS sandbox-python-requirements -ENV PATH /sandbox/venv/bin:${PATH} -ENV VIRTUAL_ENV /sandbox/venv/ +ARG EDX_PLATFORM_REPOSITORY={{ EDX_PLATFORM_REPOSITORY }} +ARG EDX_PLATFORM_VERSION={{ EDX_PLATFORM_VERSION }} + +ENV PATH=/sandbox/venv/bin:${PATH} +ENV VIRTUAL_ENV=/sandbox/venv/ WORKDIR /var/tmp RUN mkdir -p common/lib/ -COPY --from={{ DOCKER_IMAGE_OPENEDX }} /openedx/edx-platform/requirements/edx-sandbox/releases/redwood.txt redwood.txt -RUN pip3 install -r redwood.txt +ADD $EDX_PLATFORM_REPOSITORY#$EDX_PLATFORM_VERSION:requirements/edx-sandbox/releases . +RUN pip3 install -r sumac.txt # Allows you to add extra pip requirements to your codejail sandbox. {% if CODEJAIL_EXTRA_PIP_REQUIREMENTS is defined %} @@ -61,7 +65,7 @@ RUN pip3 install -r redwood.txt {% endif %} ##### Prod image -FROM minimal as production +FROM minimal AS production # Install system requirements RUN apt update && \ @@ -76,8 +80,8 @@ COPY --from=sandbox-python-requirements /sandbox/venv /sandbox/venv ENV SANDBOX_ENV=/sandbox/venv RUN groupadd -r sandbox && useradd -m -r -g sandbox sandbox && chown -R sandbox:sandbox /sandbox -ENV PATH /openedx/venv/bin:${PATH} -ENV VIRTUAL_ENV /openedx/venv/ +ENV PATH=/openedx/venv/bin:${PATH} +ENV VIRTUAL_ENV=/openedx/venv/ WORKDIR /openedx/codejailservice EXPOSE 8550 diff --git a/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile b/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile index f3595d5..b85e87c 100644 --- a/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile +++ b/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:latest as go_compiler +FROM golang:latest AS go_compiler RUN mkdir /app WORKDIR /app @@ -7,9 +7,8 @@ RUN go mod init loader RUN go get k8s.io/klog/v2 RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -installsuffix cgo --ldflags '-w' -o loader . -FROM alpine:latest +FROM alpine:3.20 -RUN apk add apparmor libapparmor --update-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing/ --allow-untrusted && \ - apk add --no-cache musl\>1.1.20 --repository http://dl-cdn.alpinelinux.org/alpine/edge/main/ +RUN apk add apparmor libapparmor --update-cache COPY --from=go_compiler /app/loader /usr/bin/loader