Skip to content

Commit cdf49a4

Browse files
committed
feat: support the openedx/codejail-service implementation
1 parent 41cec7c commit cdf49a4

13 files changed

Lines changed: 496 additions & 65 deletions

File tree

README.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ secure execution of untrusted code within sandboxes, providing a safe environmen
66

77
.. _Tutor: https://docs.tutor.overhang.io
88
.. _Codejail Service: https://github.com/eduNEXT/codejailservice
9+
.. _Codejail Service V2: https://github.com/openedx/codejail-service
910
.. _Codejail: https://github.com/openedx/codejail
1011

1112
Installation
@@ -23,9 +24,9 @@ You can install a specific version by adding the tag, branch, or commit:
2324

2425
.. code-block:: bash
2526
26-
pip install tutor-contrib-codejail==v20.0.0
27+
pip install tutor-contrib-codejail~=21.0
2728
# or install from the source
28-
pip install git+https://github.com/edunext/tutor-contrib-codejail@v20.0.0
29+
pip install git+https://github.com/edunext/tutor-contrib-codejail@v21.0.0
2930
3031
Usage
3132
-----
@@ -55,14 +56,20 @@ Configuration
5556
To customize the configuration, update the following settings in Tutor:
5657

5758
- ``CODEJAIL_APPARMOR_DOCKER_IMAGE``: (default: ``docker.io/ednxops/codejail_apparmor_loader:latest``)
59+
- ``CODEJAIL_DOCKER_IMAGE_V2`` : (default: ``{{ CODEJAIL_DOCKER_IMAGE }}-v2``)
5860
- ``CODEJAIL_DOCKER_IMAGE``: (default: ``docker.io/ednxops/codejailservice:{{__version__}}``)
5961
- ``CODEJAIL_ENABLE_K8S_DAEMONSET`` (default: ``False``)
6062
- ``CODEJAIL_ENFORCE_APPARMOR`` (default: ``True``)
6163
- ``CODEJAIL_EXTRA_PIP_REQUIREMENTS`` (default: ``[]``)
6264
- ``CODEJAIL_SANDBOX_PYTHON_VERSION`` (default: ``3.11.9``)
63-
- ``CODEJAIL_SERVICE_REPOSITORY`` (default ``https://github.com/edunext/codejailservice.git```)
64-
- ``CODEJAIL_SERVICE_VERSION`` (default: ``release/teak.1``),
65+
- ``CODEJAIL_SERVICE_REPOSITORY`` (default: ``https://github.com/edunext/codejailservice.git```)
66+
- ``CODEJAIL_SERVICE_VERSION`` (default: ``{{ OPENEDX_COMMON_VERSION }}``),
6567
- ``CODEJAIL_SKIP_INIT`` (default: ``False``)
68+
- ``SERVICE_V2_REPOSITORY``: (default: ``https://github.com/openedx/codejail-service.git``)
69+
- ``SERVICE_V2_VERSION``: (default: ``{{ OPENEDX_COMMON_VERSION }}``)
70+
- ``USE_SERVICE_V2``: (default: ``False``)
71+
72+
The ``CODEJAIL_V2_*`` settings are meant to be used only during the Ulmo release a
6673

6774
Custom Image
6875
~~~~~~~~~~~~

tutorcodejail/patches/k8s-deployments

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,41 @@
11
---
2+
{% if CODEJAIL_USE_SERVICE_V2 %}
3+
apiVersion: apps/v1
4+
kind: Deployment
5+
metadata:
6+
name: codejailservice
7+
labels:
8+
app.kubernetes.io/name: codejailservice
9+
spec:
10+
selector:
11+
matchLabels:
12+
app.kubernetes.io/name: codejailservice
13+
template:
14+
metadata:
15+
labels:
16+
app.kubernetes.io/name: codejailservice
17+
spec:
18+
securityContext:
19+
appArmorProfile:
20+
type: Localhost
21+
localhostProfile: openedx_codejail_service
22+
containers:
23+
- name: codejailservice
24+
image: {{ CODEJAIL_DOCKER_IMAGE_V2 }}
25+
ports:
26+
- containerPort: 8550
27+
env:
28+
- name: DJANGO_SETTINGS_MODULE
29+
value: codejail_service.settings.tutor
30+
volumeMounts:
31+
- mountPath: /app/codejail_service/settings/tutor.py
32+
name: settings-codejail
33+
subPath: tutor.py
34+
volumes:
35+
- name: settings-codejail
36+
configMap:
37+
name: settings-codejail
38+
{% else %}
239
apiVersion: apps/v1
340
kind: Deployment
441
metadata:
@@ -36,6 +73,7 @@ spec:
3673
- name: settings-codejail
3774
configMap:
3875
name: settings-codejail
76+
{% endif %}
3977
{% if CODEJAIL_ENABLE_K8S_DAEMONSET %}
4078
---
4179
apiVersion: apps/v1

tutorcodejail/patches/k8s-services

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ apiVersion: v1
33
kind: Service
44
metadata:
55
name: codejailservice
6+
labels:
7+
app.kubernetes.io/name: codejailservice
68
spec:
79
type: ClusterIP
810
ports:
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
- name: codejail-profile
22
files:
3-
- plugins/codejail/apps/profiles/docker-edx-sandbox
3+
- plugins/codejail/apps/profiles/docker-edx-sandbox.profile
4+
- plugins/codejail/apps/profiles/openedx-codejail-service.profile
45
options:
56
labels:
67
app.kubernetes.io/name: codejail-aa-loader
78
- name: settings-codejail
89
files:
9-
- plugins/codejail/apps/config/tutor.py
10+
{% if CODEJAIL_USE_SERVICE_V2 %}
11+
- plugins/codejail/apps/codejail-service-v2/tutor.py
12+
{% else %}
13+
- plugins/codejail/apps/codejail/tutor.py
14+
{% endif %}
1015
options:
1116
labels:
1217
app.kubernetes.io/name: codejailservice
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
codejail-apparmor-job:
2+
image: {{ CODEJAIL_APPARMOR_DOCKER_IMAGE }}
3+
privileged: true
4+
environment:
5+
SKIP_INIT: "{{ CODEJAIL_SKIP_INIT }}"
6+
volumes:
7+
- ../plugins/codejail/apps/profiles/:/profiles/:ro
8+
- /sys:/sys
9+
- /etc/apparmor.d:/etc/apparmor.d

tutorcodejail/patches/local-docker-compose-services

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
#############Codejail service
2+
{% if CODEJAIL_USE_SERVICE_V2 %}
3+
codejailservice:
4+
image: {{ CODEJAIL_DOCKER_IMAGE_V2 }}
5+
ports:
6+
- 8550:8550
7+
environment:
8+
DJANGO_SETTINGS_MODULE: codejail_service.settings.tutor
9+
security_opt:
10+
- apparmor:openedx_codejail_service
11+
volumes:
12+
- ../plugins/codejail/apps/codejail-service-v2/tutor.py:/app/codejail_service/settings/tutor.py:ro
13+
restart: unless-stopped
14+
depends_on:
15+
- codejail-apparmor-loader
16+
{% else %}
217
codejailservice:
318
image: {{ CODEJAIL_DOCKER_IMAGE }}
419
environment:
@@ -8,11 +23,11 @@ codejailservice:
823
- apparmor:docker-edx-sandbox
924
{% endif %}
1025
volumes:
11-
- ../plugins/codejail/apps/config/tutor.py:/openedx/codejailservice/codejailservice/tutor.py:ro
12-
- ../../data/codejail:/openedx/data
26+
- ../plugins/codejail/apps/codejail/tutor.py:/openedx/codejailservice/codejailservice/tutor.py:ro
1327
restart: unless-stopped
1428
depends_on:
1529
- codejail-apparmor-loader
30+
{% endif %}
1631

1732
codejail-apparmor-loader:
1833
image: {{ CODEJAIL_APPARMOR_DOCKER_IMAGE }}

tutorcodejail/plugin.py

Lines changed: 69 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
"""Manage the plugin for the tutorcodejail."""
2+
23
from __future__ import annotations
34

45
import os
56
from glob import glob
67
from pathlib import Path
78

9+
import typing as t
10+
811
import importlib_resources
912
from tutor import hooks
13+
from tutor.types import Config
1014

1115
from .__about__ import __version__
1216

@@ -17,16 +21,20 @@
1721
"SECRET_KEY": "{{ 24|random_string }}",
1822
},
1923
"defaults": {
20-
"APPARMOR_DOCKER_IMAGE": "docker.io/ednxops/codejail_apparmor_loader:apparmor-3",
24+
"APPARMOR_DOCKER_IMAGE": "docker.io/ednxops/codejail_apparmor_loader:apparmor-4",
2125
"DOCKER_IMAGE": f"docker.io/ednxops/codejailservice:{__version__}",
26+
"DOCKER_IMAGE_V2": "{{ CODEJAIL_DOCKER_IMAGE }}-v2",
2227
"ENABLE_K8S_DAEMONSET": False,
2328
"ENFORCE_APPARMOR": True,
2429
"EXTRA_PIP_REQUIREMENTS": [],
2530
"HOST": "codejailservice",
2631
"SANDBOX_PYTHON_VERSION": "3.11.14",
2732
"SERVICE_REPOSITORY": "https://github.com/edunext/codejailservice.git",
33+
"SERVICE_V2_REPOSITORY": "https://github.com/openedx/codejail-service.git",
34+
"SERVICE_V2_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
2835
"SERVICE_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
2936
"SKIP_INIT": False,
37+
"USE_SERVICE_V2": False,
3038
"VERSION": __version__,
3139
},
3240
"overrides": {},
@@ -35,23 +43,27 @@
3543

3644
def get_apparmor_abi():
3745
"""
38-
Return the default abi 3.0 rule if available in the system.
46+
Return the latest default abi rule if available in the system.
3947
4048
AppArmor uses the Policy feature ABI to establish which rules it can
4149
enforce based on the kernel capabilities. AppArmor profiles can include an
4250
ABI rule to indicate the ABI they were developed under. If no rule is used
4351
AppArmor will fallback to whichever rule is pinned in the
4452
`/etc/apparmor/parser.conf` file.
4553
46-
We try to use the 3.0 abi whenever it's available at `/etc/apparmor.d/abi/`
54+
We try to use at least the 3.0 abi whenever it's available at `/etc/apparmor.d/abi/`
4755
to guarantee that network rules are correctly enforced on newer versions of
48-
the kernel. If the ABI is not present we don't set the abi rule and instead
49-
rely on the default fallback.
56+
the kernel. If neither the 3.0 ABI nor the 4.0 ABI are present we don't set
57+
the abi rule and instead rely on the default fallback.
5058
5159
See: https://github.com/netblue30/firejail/issues/3659#issuecomment-711074899
5260
"""
61+
if Path(f"{ABI_PATH}/4.0").exists():
62+
return "abi <abi/4.0>,"
63+
5364
if Path(f"{ABI_PATH}/3.0").exists():
5465
return "abi <abi/3.0>,"
66+
5567
return ""
5668

5769

@@ -62,45 +74,56 @@ def get_apparmor_abi():
6274
)
6375

6476

65-
hooks.Filters.IMAGES_BUILD.add_item((
66-
"codejail",
67-
("plugins", "codejail", "build", "codejail"),
68-
"{{ CODEJAIL_DOCKER_IMAGE }}",
69-
(),
70-
))
71-
72-
73-
hooks.Filters.IMAGES_BUILD.add_item((
74-
"codejail_apparmor",
75-
("plugins", "codejail", "build", "codejail_apparmor"),
76-
"{{CODEJAIL_APPARMOR_DOCKER_IMAGE}}",
77-
(),
78-
))
79-
80-
81-
hooks.Filters.IMAGES_PULL.add_item((
82-
"codejail",
83-
"{{ CODEJAIL_DOCKER_IMAGE }}",
84-
))
85-
86-
87-
hooks.Filters.IMAGES_PULL.add_item((
88-
"codejail_apparmor",
89-
"{{CODEJAIL_APPARMOR_DOCKER_IMAGE}}",
90-
))
91-
92-
93-
hooks.Filters.IMAGES_PUSH.add_item((
94-
"codejail",
95-
"{{ CODEJAIL_DOCKER_IMAGE }}",
96-
))
97-
98-
99-
hooks.Filters.IMAGES_PUSH.add_item((
100-
"codejail_apparmor",
101-
"{{CODEJAIL_APPARMOR_DOCKER_IMAGE}}",
102-
))
103-
77+
@hooks.Filters.IMAGES_BUILD.add()
78+
def _build_codejail_images(
79+
images: list[tuple[str, t.Union[str, tuple[str, ...]], str, tuple[str, ...]]],
80+
config: Config,
81+
):
82+
# TODO: Remove after the Verawood update
83+
if config.get("CODEJAIL_USE_SERVICE_V2"):
84+
codejail_img = (
85+
"codejail",
86+
"plugins/codejail/build/codejail-service",
87+
"{{ CODEJAIL_DOCKER_IMAGE_V2 }}",
88+
(),
89+
)
90+
else:
91+
codejail_img = (
92+
"codejail",
93+
"plugins/codejail/build/codejail",
94+
"{{ CODEJAIL_DOCKER_IMAGE }}",
95+
(),
96+
)
97+
apparmor_img = (
98+
"codejail_apparmor",
99+
("plugins", "codejail", "build", "codejail_apparmor"),
100+
"{{CODEJAIL_APPARMOR_DOCKER_IMAGE}}",
101+
(),
102+
)
103+
104+
return images + [codejail_img, apparmor_img]
105+
106+
@hooks.Filters.IMAGES_PUSH.add()
107+
def _push_codejail_images(
108+
images: list[tuple[str, t.Union[str, tuple[str, ...]], str, tuple[str, ...]]],
109+
config: Config,
110+
):
111+
# TODO: Remove after the Verawood update
112+
if config.get("CODEJAIL_USE_SERVICE_V2"):
113+
codejail_img = (
114+
"codejail",
115+
"{{ CODEJAIL_DOCKER_IMAGE_V2 }}",
116+
)
117+
else:
118+
codejail_img = (
119+
"codejail",
120+
"{{ CODEJAIL_DOCKER_IMAGE }}",
121+
)
122+
apparmor_img = (
123+
"codejail_apparmor",
124+
"{{CODEJAIL_APPARMOR_DOCKER_IMAGE}}",
125+
)
126+
return images + [codejail_img, apparmor_img]
104127

105128
# Boilerplate code
106129
# Add the "templates" folder as a template root
@@ -121,15 +144,9 @@ def get_apparmor_abi():
121144
hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read()))
122145
# Add configuration entries
123146
hooks.Filters.CONFIG_DEFAULTS.add_items(
124-
[
125-
(f"CODEJAIL_{key}", value)
126-
for key, value in config.get("defaults", {}).items()
127-
]
147+
[(f"CODEJAIL_{key}", value) for key, value in config.get("defaults", {}).items()]
128148
)
129149
hooks.Filters.CONFIG_UNIQUE.add_items(
130-
[
131-
(f"CODEJAIL_{key}", value)
132-
for key, value in config.get("unique", {}).items()
133-
]
150+
[(f"CODEJAIL_{key}", value) for key, value in config.get("unique", {}).items()]
134151
)
135152
hooks.Filters.CONFIG_OVERRIDES.add_items(list(config.get("overrides", {}).items()))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from codejail_service.settings.local import * # pylint: disable=wildcard-import
2+
3+
ALLOWED_HOSTS = [
4+
'codejailservice',
5+
'localhost',
6+
]
7+
8+
CODEJAIL_ENABLED = True
9+
SECRET_KEY = '{{ CODEJAIL_SECRET_KEY }}'
10+
11+
CODE_JAIL = {
12+
'python_bin': '/sandbox/venv/bin/python',
13+
'user': 'sandbox',
14+
15+
# Configurable limits.
16+
'limits': {
17+
# CPU-seconds
18+
'CPU': 3,
19+
# Clock seconds
20+
'REALTIME': 3,
21+
# Need at least 300 MiB memory for matplotlib alone. 512 MiB should be
22+
# enough headroom in general.
23+
'VMEM': 512 * 1024 * 1024,
24+
# 10 MB file size limit
25+
'FSIZE': 10 * 1024 * 1024,
26+
# 15 processes and threads (codejail default)
27+
'NPROC': 15,
28+
# Match production configuration
29+
'PROXY': 0,
30+
},
31+
}
32+
33+
{{ patch("codejail-common-settings") }}
34+
{{ patch("codejail-production-settings") }}

tutorcodejail/templates/codejail/apps/config/tutor.py renamed to tutorcodejail/templates/codejail/apps/codejail/tutor.py

File renamed without changes.

tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox renamed to tutorcodejail/templates/codejail/apps/profiles/docker-edx-sandbox.profile

File renamed without changes.

0 commit comments

Comments
 (0)