Skip to content

Commit

Permalink
fix: adjust the globing and abi rules in the apparmor profile
Browse files Browse the repository at this point in the history
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 committed Dec 17, 2024
1 parent b6171c7 commit 8367bf9
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 17 deletions.
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
33 changes: 32 additions & 1 deletion 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 @@ -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 <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
Original file line number Diff line number Diff line change
Expand Up @@ -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 8367bf9

Please sign in to comment.