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 0a14c0c..1944381 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, @@ -37,6 +40,34 @@ } +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_apparmor/Dockerfile b/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile index f3595d5..76b9fe5 100644 --- a/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile +++ b/tutorcodejail/templates/codejail/build/codejail_apparmor/Dockerfile @@ -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