Skip to content

Commit

Permalink
feat: sumac upgrade (#59)
Browse files Browse the repository at this point in the history
Adjust the globing and abi rules in the apparmor profile:

Newer versions of ubuntu (>24.04) do not pin the AppArmor Policy feature
ABI which causes certain rules to not be enforced. We include an abi
rule to use the relatively common 3.0 policy whenever it's available in
the system, if it's not available we rely on the default fallback
behaviour. The 3.0 policy should be present on any system using
AppArmor>3.x (e.g. Ubuntu 22.04 or newer).

The globbing rules in the profile were adjusted to cover a larger range
of python versions and avoid creating new profiles for different
versions of python used by the sandbox environment.

To load the profile we need at least AppArmor 3.0, to avoid confusion in
the future we pin the alpine base image and define a proper tag for the
apparmorloader image.
  • Loading branch information
MoisesGSalas authored Dec 17, 2024
1 parent 6b40a36 commit 8a9e678
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 44 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion tutorcodejail/__about__.py
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion tutorcodejail/patches/k8s-deployments
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion tutorcodejail/patches/local-docker-compose-services
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
35 changes: 33 additions & 2 deletions tutorcodejail/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 <abi/3.0>,"
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:
Expand Down
22 changes: 11 additions & 11 deletions tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <tunables/global>

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 <abstractions/base>

network,
Expand All @@ -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/<number>/** or /proc/sys/**
Expand All @@ -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){
Expand All @@ -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,
Expand Down
46 changes: 25 additions & 21 deletions tutorcodejail/templates/codejail/build/codejail/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
FROM docker.io/ubuntu:22.04 as minimal
MAINTAINER edunext.co <[email protected]>
FROM docker.io/ubuntu:22.04 AS minimal
LABEL mantainer="edunext.co <[email protected]>"

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
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 %}
Expand All @@ -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 && \
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:latest as go_compiler
FROM golang:latest AS go_compiler

RUN mkdir /app
WORKDIR /app
Expand All @@ -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

0 comments on commit 8a9e678

Please sign in to comment.