diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 34e9765..99d1bcb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,12 @@ Change Log Unreleased ~~~~~~~~~~ +[3.2.0] - 2024-01-09 +~~~~~~~~~~~~~~~~~~~~ +Added +_____ +* Add ``codejail_service`` app for transition to containerized codejail + [3.1.1] - 2023-11-06 ~~~~~~~~~~~~~~~~~~~~ Fixed diff --git a/edx_arch_experiments/__init__.py b/edx_arch_experiments/__init__.py index 2bf91e3..0960636 100644 --- a/edx_arch_experiments/__init__.py +++ b/edx_arch_experiments/__init__.py @@ -2,4 +2,4 @@ A plugin to include applications under development by the architecture team at 2U. """ -__version__ = '3.1.1' +__version__ = '3.2.0' diff --git a/edx_arch_experiments/codejail_service/README.rst b/edx_arch_experiments/codejail_service/README.rst new file mode 100644 index 0000000..b0bb92a --- /dev/null +++ b/edx_arch_experiments/codejail_service/README.rst @@ -0,0 +1,27 @@ +Codejail Service +################ + +When installed in the LMS as a plugin app, the ``codejail_service`` app allows the CMS to delegate codejail executions to the LMS across the network. + +This is intended as a `temporary situation `_ with the following goals: + +- Unblock containerization of the CMS. Codejail cannot be readily containerized due to its reliance on AppArmor, but if codejail execution is outsourced, then we can containerize CMS first and will be in a better position to containerize the LMS afterwards. +- Exercise the remote-codejail pathway and have an opportunity to discover and implement needed improvements before fully building out a separate, dedicated codejail service. + +Setup +***** + +In LMS: + +- Install ``edx-arch-experiments`` as a dependency +- Identify a service account that will be permitted to make calls to the codejail service and ensure it has the ``is_staff`` Django flag. In devstack, this would be ``cms_worker``. +- In Djano admin, under ``Django OAuth Toolkit > Applications``, find or create a Client Credentials application for that service user. + +In CMS: + +- Set ``ENABLE_CODEJAIL_REST_SERVICE`` to ``True`` +- Set ``CODE_JAIL_REST_SERVICE_HOST`` to the URL origin of the LMS (e.g. ``http://edx.devstack.lms:18000`` in devstack) +- Keep ``CODE_JAIL_REST_SERVICE_REMOTE_EXEC`` at its default of ``xmodule.capa.safe_exec.remote_exec.send_safe_exec_request_v0`` +- Adjust ``CODE_JAIL_REST_SERVICE_CONNECT_TIMEOUT`` and ``CODE_JAIL_REST_SERVICE_READ_TIMEOUT`` if needed +- Set ``CODE_JAIL_REST_SERVICE_OAUTH_URL`` to the LMS OAuth endpoint (e.g. ``http://edx.devstack.lms:18000`` in devstack) +- Set ``CODE_JAIL_REST_SERVICE_OAUTH_CLIENT_ID`` and ``CODE_JAIL_REST_SERVICE_OAUTH_CLIENT_SECRET`` to the client credentials app ID and secret that you identified in the LMS. (In devstack, these would be ``cms-backend-service-key`` and ``cms-backend-service-secret``.) diff --git a/edx_arch_experiments/codejail_service/__init__.py b/edx_arch_experiments/codejail_service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/edx_arch_experiments/codejail_service/apps.py b/edx_arch_experiments/codejail_service/apps.py new file mode 100644 index 0000000..0af4167 --- /dev/null +++ b/edx_arch_experiments/codejail_service/apps.py @@ -0,0 +1,22 @@ +""" +App for running answer submissions inside of codejail. +""" + +from django.apps import AppConfig +from edx_django_utils.plugins.constants import PluginURLs + + +class CodejailService(AppConfig): + """ + Django application to run things in codejail. + """ + name = 'edx_arch_experiments.codejail_service' + + plugin_app = { + PluginURLs.CONFIG: { + 'lms.djangoapp': { + PluginURLs.NAMESPACE: 'codejail_service', + PluginURLs.RELATIVE_PATH: 'urls', # .urls is the default place for plugin views + } + }, + } diff --git a/edx_arch_experiments/codejail_service/urls.py b/edx_arch_experiments/codejail_service/urls.py new file mode 100644 index 0000000..18e6d32 --- /dev/null +++ b/edx_arch_experiments/codejail_service/urls.py @@ -0,0 +1,11 @@ +""" +Codejail service URLs. +""" + +from django.urls import path + +from . import views + +urlpatterns = [ + path('api/v0/code-exec', views.code_exec_view_v0, name="code_exec_v0"), +] diff --git a/edx_arch_experiments/codejail_service/views.py b/edx_arch_experiments/codejail_service/views.py new file mode 100644 index 0000000..49bba3b --- /dev/null +++ b/edx_arch_experiments/codejail_service/views.py @@ -0,0 +1,153 @@ +""" +Codejail service API. +""" + +import json +import logging +from copy import deepcopy + +import jsonschema +from codejail.safe_exec import SafeExecException, safe_exec +from django.conf import settings +from edx_toggles.toggles import SettingToggle +from rest_framework.decorators import api_view, parser_classes, permission_classes +from rest_framework.parsers import FormParser, MultiPartParser +from rest_framework.permissions import IsAdminUser +from rest_framework.response import Response + +log = logging.getLogger(__name__) + +# .. toggle_name: CODEJAIL_SERVICE_ENABLED +# .. toggle_implementation: SettingToggle +# .. toggle_default: True +# .. toggle_description: If True, codejail execution calls will be accepted over the network, +# allowing this IDA to act as a codejail service for another IDA. +# .. toggle_use_cases: circuit_breaker +# .. toggle_creation_date: 2023-12-21 +# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/33538 +CODEJAIL_SERVICE_ENABLED = SettingToggle('CODEJAIL_SERVICE_ENABLED', default=True, module_name=__name__) + +# Schema for the JSON passed in the v0 API's 'payload' field. +payload_schema = { + 'type': 'object', + 'properties': { + 'code': {'type': 'string'}, + 'globals_dict': {'type': 'object'}, + # Some of these are configured as union types because + # edx-platform appears to currently default to None for some + # of them (rather than omitting the keys.) + 'python_path': { + 'anyOf': [ + { + 'type': 'array', + 'items': {'type': 'string'}, + }, + {'type': 'null'}, + ], + }, + 'limit_overrides_context': { + 'anyOf': [ + {'type': 'string'}, + {'type': 'null'}, + ], + }, + 'slug': { + 'anyOf': [ + {'type': 'string'}, + {'type': 'null'}, + ], + }, + 'unsafely': {'type': 'boolean'}, + }, + 'required': ['code'], +} + +# A note on the authorization model used here: +# +# We really just need one service account to be able to call this, and +# then also allow is_staff to call it for convenience and debugging +# purposes. +# +# To do this "right", I'd probably have to create an empty abstract +# model, create a permission on it, create a group, add the permission +# to the group, and add the service account to the group. Then I could +# check the calling user's has_perm. If I wanted to use bridgekeeper +# (as we're trying to do more of) I might be able to give bridgekeeper +# a `@blanket_rule` that checks membership in the group, then use +# bridgekeeper here instead of checking permissions directly, but it's +# possible this wouldn't work because bridgekeeper might require there +# to be a model instance to pass in (and there wouldn't be one, since +# it's just an abstract model.) +# +# But... given that the service account will be is_staff, and I'll be +# opening this up to is_staff alongside the intended service account, +# and this is already a hacky intermediate solution... we can just use +# the `IsAdminUser` permission class and be done with it. + + +@api_view(['POST']) +@parser_classes([FormParser, MultiPartParser]) +@permission_classes([IsAdminUser]) +def code_exec_view_v0(request): + """ + Executes code in a codejail sandbox for a remote caller. + + This implements the API used by edxapp's xmodule.capa.safe_exec.remote_exec. + It accepts a POST of a form containing a `payload` value and zero or more + extra files. + + The payload is JSON and contains the parameters to be sent to codejail's + safe_exec (aside from `extra_files`). See payload_schema for type information. + + This API does not permit `unsafely=true`. + """ + if not CODEJAIL_SERVICE_ENABLED.is_enabled(): + return Response("Codejail service not enabled", status=500) + + params_json = request.data['payload'] + params = json.loads(params_json) + jsonschema.validate(params, payload_schema) + + complete_code = params['code'] # includes standard prolog + input_globals_dict = params.get('globals_dict') or {} + python_path = params.get('python_path') or [] + limit_overrides_context = params.get('limit_overrides_context') + slug = params.get('slug') + unsafely = params.get('unsafely') + + extra_files = request.FILES + + # There's a risk of getting into a loop if e.g. the CMS asks the + # LMS to run codejail executions on its behalf, and the LMS is + # *also* inadvertently configured to call the LMS (itself). + # There's no good reason to have a chain of >2 services passing + # codejail requests along, so only allow execution here if we + # aren't going to pass it along to someone else. + if getattr(settings, 'ENABLE_CODEJAIL_REST_SERVICE', False): + raise Exception( + "Refusing to run codejail request from over the network " + "when we're going to pass it to another IDA anyway" + ) + + # Far too dangerous to allow unsafe executions to come in over the + # network, no matter who we think the caller is. The caller is the + # one who has the context on safety. + if unsafely: + raise Exception("Refusing to run codejail request from over the network with unsafely=true") + + output_globals_dict = deepcopy(input_globals_dict) # Output dict will be mutated by safe_exec + try: + safe_exec( + complete_code, + output_globals_dict, + python_path=python_path, + extra_files=extra_files, + limit_overrides_context=limit_overrides_context, + slug=slug, + ) + except SafeExecException as e: + log.debug("CodejailService execution failed with: {e!r}") + return Response({'emsg': f"Code jail execution failed: {e!r}"}) + + log.debug("CodejailService execution succeeded, with globals={output_globals_dict!r}") + return Response({'globals_dict': output_globals_dict}) diff --git a/requirements/base.in b/requirements/base.in index 0935bef..924dd37 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -4,3 +4,8 @@ Django # Web application framework edx_django_utils django-waffle # Configuration switches and flags -- used by config_watcher app +edx-codejail # Actual codejail library; used by codejail_service app +djangorestframework # Used by codejail_service app +edx-drf-extensions # Used by codejail_service app +edx-toggles # Used by codejail_service app +jsonschema # Parse and validate JSON; used by codejail_service app diff --git a/requirements/base.txt b/requirements/base.txt index bb88a7c..49f7249 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -6,40 +6,136 @@ # asgiref==3.7.2 # via django +attrs==23.2.0 + # via + # jsonschema + # referencing +certifi==2023.11.17 + # via requests cffi==1.16.0 - # via pynacl + # via + # cryptography + # pynacl +charset-normalizer==3.3.2 + # via requests click==8.1.7 - # via edx-django-utils + # via + # code-annotations + # edx-django-utils +code-annotations==1.5.0 + # via edx-toggles +cryptography==41.0.7 + # via pyjwt django==3.2.23 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.in # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions + # edx-toggles django-crum==0.7.9 - # via edx-django-utils + # via + # edx-django-utils + # edx-toggles django-waffle==4.1.0 # via # -r requirements/base.in # edx-django-utils + # edx-drf-extensions + # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/base.in + # drf-jwt + # edx-drf-extensions +drf-jwt==1.19.2 + # via edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/base.in edx-django-utils==5.9.0 + # via + # -r requirements/base.in + # edx-drf-extensions + # edx-toggles +edx-drf-extensions==9.0.1 # via -r requirements/base.in +edx-opaque-keys==2.5.1 + # via edx-drf-extensions +edx-toggles==5.1.0 + # via -r requirements/base.in +idna==3.6 + # via requests +importlib-resources==6.1.1 + # via + # jsonschema + # jsonschema-specifications +jinja2==3.1.2 + # via code-annotations +jsonschema==4.20.0 + # via -r requirements/base.in +jsonschema-specifications==2023.12.1 + # via jsonschema +markupsafe==2.1.3 + # via jinja2 newrelic==9.3.0 # via edx-django-utils pbr==6.0.0 # via stevedore -psutil==5.9.6 +pkgutil-resolve-name==1.3.10 + # via jsonschema +psutil==5.9.7 # via edx-django-utils pycparser==2.21 # via cffi +pyjwt[crypto]==2.8.0 + # via + # drf-jwt + # edx-drf-extensions + # pyjwt +pymongo==3.13.0 + # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils +python-slugify==8.0.1 + # via code-annotations pytz==2023.3.post1 - # via django + # via + # django + # djangorestframework +pyyaml==6.0.1 + # via code-annotations +referencing==0.32.0 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via edx-drf-extensions +rpds-py==0.16.2 + # via + # jsonschema + # referencing +semantic-version==2.10.0 + # via edx-drf-extensions +six==1.16.0 + # via edx-codejail sqlparse==0.4.4 # via django stevedore==5.1.0 - # via edx-django-utils + # via + # code-annotations + # edx-django-utils + # edx-opaque-keys +text-unidecode==1.3 + # via python-slugify typing-extensions==4.9.0 - # via asgiref + # via + # asgiref + # edx-opaque-keys +urllib3==2.1.0 + # via requests +zipp==3.17.0 + # via importlib-resources diff --git a/requirements/dev.txt b/requirements/dev.txt index 6c5aa7e..c6043d6 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -13,6 +13,11 @@ astroid==3.0.2 # -r requirements/quality.txt # pylint # pylint-celery +attrs==23.2.0 + # via + # -r requirements/quality.txt + # jsonschema + # referencing build==1.0.3 # via # -r requirements/pip-tools.txt @@ -56,11 +61,12 @@ code-annotations==1.5.0 # via # -r requirements/quality.txt # edx-lint + # edx-toggles colorama==0.4.6 # via # -r requirements/ci.txt # tox -coverage[toml]==7.3.3 +coverage[toml]==7.4.0 # via # -r requirements/quality.txt # coverage @@ -68,6 +74,7 @@ coverage[toml]==7.3.3 cryptography==41.0.7 # via # -r requirements/quality.txt + # pyjwt # secretstorage diff-cover==8.0.2 # via -r requirements/dev.in @@ -85,26 +92,55 @@ django==3.2.23 # -r requirements/quality.txt # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions # edx-i18n-tools + # edx-toggles django-crum==0.7.9 # via # -r requirements/quality.txt # edx-django-utils + # edx-toggles django-waffle==4.1.0 # via # -r requirements/quality.txt # edx-django-utils + # edx-drf-extensions + # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/quality.txt + # drf-jwt + # edx-drf-extensions docutils==0.20.1 # via # -r requirements/quality.txt # readme-renderer +drf-jwt==1.19.2 + # via + # -r requirements/quality.txt + # edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/quality.txt edx-django-utils==5.9.0 + # via + # -r requirements/quality.txt + # edx-drf-extensions + # edx-toggles +edx-drf-extensions==9.0.1 # via -r requirements/quality.txt edx-i18n-tools==1.3.0 # via -r requirements/dev.in edx-lint==5.3.6 # via -r requirements/quality.txt +edx-opaque-keys==2.5.1 + # via + # -r requirements/quality.txt + # edx-drf-extensions +edx-toggles==5.1.0 + # via -r requirements/quality.txt exceptiongroup==1.2.0 # via # -r requirements/quality.txt @@ -118,7 +154,7 @@ idna==3.6 # via # -r requirements/quality.txt # requests -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via # -r requirements/pip-tools.txt # -r requirements/quality.txt @@ -128,6 +164,8 @@ importlib-metadata==7.0.0 importlib-resources==6.1.1 # via # -r requirements/quality.txt + # jsonschema + # jsonschema-specifications # keyring iniconfig==2.0.0 # via @@ -151,11 +189,17 @@ jinja2==3.1.2 # -r requirements/quality.txt # code-annotations # diff-cover +jsonschema==4.20.0 + # via -r requirements/quality.txt +jsonschema-specifications==2023.12.1 + # via + # -r requirements/quality.txt + # jsonschema keyring==24.3.0 # via # -r requirements/quality.txt # twine -lxml==4.9.3 +lxml==5.0.0 # via edx-i18n-tools markdown-it-py==3.0.0 # via @@ -206,6 +250,10 @@ pkginfo==1.9.6 # via # -r requirements/quality.txt # twine +pkgutil-resolve-name==1.3.10 + # via + # -r requirements/quality.txt + # jsonschema platformdirs==4.1.0 # via # -r requirements/ci.txt @@ -222,7 +270,7 @@ pluggy==1.3.0 # tox polib==1.2.0 # via edx-i18n-tools -psutil==5.9.6 +psutil==5.9.7 # via # -r requirements/quality.txt # edx-django-utils @@ -240,6 +288,12 @@ pygments==2.17.2 # diff-cover # readme-renderer # rich +pyjwt[crypto]==2.8.0 + # via + # -r requirements/quality.txt + # drf-jwt + # edx-drf-extensions + # pyjwt pylint==3.0.3 # via # -r requirements/quality.txt @@ -260,6 +314,10 @@ pylint-plugin-utils==0.8.2 # -r requirements/quality.txt # pylint-celery # pylint-django +pymongo==3.13.0 + # via + # -r requirements/quality.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/quality.txt @@ -272,7 +330,7 @@ pyproject-hooks==1.0.0 # via # -r requirements/pip-tools.txt # build -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/quality.txt # pytest-cov @@ -289,6 +347,7 @@ pytz==2023.3.post1 # via # -r requirements/quality.txt # django + # djangorestframework pyyaml==6.0.1 # via # -r requirements/quality.txt @@ -298,9 +357,15 @@ readme-renderer==42.0 # via # -r requirements/quality.txt # twine +referencing==0.32.0 + # via + # -r requirements/quality.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 # via # -r requirements/quality.txt + # edx-drf-extensions # requests-toolbelt # twine requests-toolbelt==1.0.0 @@ -315,13 +380,23 @@ rich==13.7.0 # via # -r requirements/quality.txt # twine +rpds-py==0.16.2 + # via + # -r requirements/quality.txt + # jsonschema + # referencing secretstorage==3.3.3 # via # -r requirements/quality.txt # keyring +semantic-version==2.10.0 + # via + # -r requirements/quality.txt + # edx-drf-extensions six==1.16.0 # via # -r requirements/quality.txt + # edx-codejail # edx-lint snowballstemmer==2.2.0 # via @@ -336,6 +411,7 @@ stevedore==5.1.0 # -r requirements/quality.txt # code-annotations # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 # via # -r requirements/quality.txt @@ -366,6 +442,7 @@ typing-extensions==4.9.0 # -r requirements/quality.txt # asgiref # astroid + # edx-opaque-keys # pylint # rich urllib3==2.1.0 diff --git a/requirements/doc.txt b/requirements/doc.txt index 793120e..3d06a41 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -10,43 +10,71 @@ asgiref==3.7.2 # via # -r requirements/test.txt # django +attrs==23.2.0 + # via + # -r requirements/test.txt + # jsonschema + # referencing babel==2.14.0 # via sphinx certifi==2023.11.17 - # via requests + # via + # -r requirements/test.txt + # requests cffi==1.16.0 # via # -r requirements/test.txt + # cryptography # pynacl charset-normalizer==3.3.2 - # via requests + # via + # -r requirements/test.txt + # requests click==8.1.7 # via # -r requirements/test.txt # code-annotations # edx-django-utils code-annotations==1.5.0 - # via -r requirements/test.txt -coverage[toml]==7.3.3 + # via + # -r requirements/test.txt + # edx-toggles +coverage[toml]==7.4.0 # via # -r requirements/test.txt # coverage # pytest-cov +cryptography==41.0.7 + # via + # -r requirements/test.txt + # pyjwt django==3.2.23 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/test.txt # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions + # edx-toggles django-crum==0.7.9 # via # -r requirements/test.txt # edx-django-utils + # edx-toggles django-waffle==4.1.0 # via # -r requirements/test.txt # edx-django-utils + # edx-drf-extensions + # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/test.txt + # drf-jwt + # edx-drf-extensions doc8==1.1.1 # via -r requirements/doc.in docutils==0.19 @@ -55,20 +83,44 @@ docutils==0.19 # readme-renderer # restructuredtext-lint # sphinx +drf-jwt==1.19.2 + # via + # -r requirements/test.txt + # edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/test.txt edx-django-utils==5.9.0 + # via + # -r requirements/test.txt + # edx-drf-extensions + # edx-toggles +edx-drf-extensions==9.0.1 # via -r requirements/test.txt +edx-opaque-keys==2.5.1 + # via + # -r requirements/test.txt + # edx-drf-extensions edx-sphinx-theme==3.1.0 # via -r requirements/doc.in +edx-toggles==5.1.0 + # via -r requirements/test.txt exceptiongroup==1.2.0 # via # -r requirements/test.txt # pytest idna==3.6 - # via requests + # via + # -r requirements/test.txt + # requests imagesize==1.4.1 # via sphinx -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via sphinx +importlib-resources==6.1.1 + # via + # -r requirements/test.txt + # jsonschema + # jsonschema-specifications iniconfig==2.0.0 # via # -r requirements/test.txt @@ -78,6 +130,12 @@ jinja2==3.1.2 # -r requirements/test.txt # code-annotations # sphinx +jsonschema==4.20.0 + # via -r requirements/test.txt +jsonschema-specifications==2023.12.1 + # via + # -r requirements/test.txt + # jsonschema markupsafe==2.1.3 # via # -r requirements/test.txt @@ -97,11 +155,15 @@ pbr==6.0.0 # via # -r requirements/test.txt # stevedore +pkgutil-resolve-name==1.3.10 + # via + # -r requirements/test.txt + # jsonschema pluggy==1.3.0 # via # -r requirements/test.txt # pytest -psutil==5.9.6 +psutil==5.9.7 # via # -r requirements/test.txt # edx-django-utils @@ -114,11 +176,21 @@ pygments==2.17.2 # doc8 # readme-renderer # sphinx +pyjwt[crypto]==2.8.0 + # via + # -r requirements/test.txt + # drf-jwt + # edx-drf-extensions + # pyjwt +pymongo==3.13.0 + # via + # -r requirements/test.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/test.txt # edx-django-utils -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/test.txt # pytest-cov @@ -136,18 +208,39 @@ pytz==2023.3.post1 # -r requirements/test.txt # babel # django + # djangorestframework pyyaml==6.0.1 # via # -r requirements/test.txt # code-annotations readme-renderer==42.0 # via -r requirements/doc.in +referencing==0.32.0 + # via + # -r requirements/test.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 - # via sphinx + # via + # -r requirements/test.txt + # edx-drf-extensions + # sphinx restructuredtext-lint==1.4.0 # via doc8 +rpds-py==0.16.2 + # via + # -r requirements/test.txt + # jsonschema + # referencing +semantic-version==2.10.0 + # via + # -r requirements/test.txt + # edx-drf-extensions six==1.16.0 - # via edx-sphinx-theme + # via + # -r requirements/test.txt + # edx-codejail + # edx-sphinx-theme snowballstemmer==2.2.0 # via sphinx sphinx==5.3.0 @@ -176,6 +269,7 @@ stevedore==5.1.0 # code-annotations # doc8 # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 # via # -r requirements/test.txt @@ -190,7 +284,13 @@ typing-extensions==4.9.0 # via # -r requirements/test.txt # asgiref + # edx-opaque-keys urllib3==2.1.0 - # via requests + # via + # -r requirements/test.txt + # requests zipp==3.17.0 - # via importlib-metadata + # via + # -r requirements/test.txt + # importlib-metadata + # importlib-resources diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index 93a9cee..0e88226 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -8,7 +8,7 @@ build==1.0.3 # via pip-tools click==8.1.7 # via pip-tools -importlib-metadata==7.0.0 +importlib-metadata==7.0.1 # via build packaging==23.2 # via build diff --git a/requirements/pip.txt b/requirements/pip.txt index 14cb99c..a4cf530 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -8,7 +8,7 @@ wheel==0.42.0 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==23.3.1 +pip==23.3.2 # via -r requirements/pip.in -setuptools==69.0.2 +setuptools==69.0.3 # via -r requirements/pip.in diff --git a/requirements/quality.txt b/requirements/quality.txt index d0dc4f3..a6dd1e6 100644 --- a/requirements/quality.txt +++ b/requirements/quality.txt @@ -12,15 +12,24 @@ astroid==3.0.2 # via # pylint # pylint-celery +attrs==23.2.0 + # via + # -r requirements/test.txt + # jsonschema + # referencing certifi==2023.11.17 - # via requests + # via + # -r requirements/test.txt + # requests cffi==1.16.0 # via # -r requirements/test.txt # cryptography # pynacl charset-normalizer==3.3.2 - # via requests + # via + # -r requirements/test.txt + # requests click==8.1.7 # via # -r requirements/test.txt @@ -34,13 +43,17 @@ code-annotations==1.5.0 # via # -r requirements/test.txt # edx-lint -coverage[toml]==7.3.3 + # edx-toggles +coverage[toml]==7.4.0 # via # -r requirements/test.txt # coverage # pytest-cov cryptography==41.0.7 - # via secretstorage + # via + # -r requirements/test.txt + # pyjwt + # secretstorage dill==0.3.7 # via pylint django==3.2.23 @@ -49,33 +62,68 @@ django==3.2.23 # -r requirements/test.txt # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions + # edx-toggles django-crum==0.7.9 # via # -r requirements/test.txt # edx-django-utils + # edx-toggles django-waffle==4.1.0 # via # -r requirements/test.txt # edx-django-utils + # edx-drf-extensions + # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/test.txt + # drf-jwt + # edx-drf-extensions docutils==0.20.1 # via readme-renderer +drf-jwt==1.19.2 + # via + # -r requirements/test.txt + # edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/test.txt edx-django-utils==5.9.0 + # via + # -r requirements/test.txt + # edx-drf-extensions + # edx-toggles +edx-drf-extensions==9.0.1 # via -r requirements/test.txt edx-lint==5.3.6 # via -r requirements/quality.in +edx-opaque-keys==2.5.1 + # via + # -r requirements/test.txt + # edx-drf-extensions +edx-toggles==5.1.0 + # via -r requirements/test.txt exceptiongroup==1.2.0 # via # -r requirements/test.txt # pytest idna==3.6 - # via requests -importlib-metadata==7.0.0 + # via + # -r requirements/test.txt + # requests +importlib-metadata==7.0.1 # via # keyring # twine importlib-resources==6.1.1 - # via keyring + # via + # -r requirements/test.txt + # jsonschema + # jsonschema-specifications + # keyring iniconfig==2.0.0 # via # -r requirements/test.txt @@ -94,6 +142,12 @@ jinja2==3.1.2 # via # -r requirements/test.txt # code-annotations +jsonschema==4.20.0 + # via -r requirements/test.txt +jsonschema-specifications==2023.12.1 + # via + # -r requirements/test.txt + # jsonschema keyring==24.3.0 # via twine markdown-it-py==3.0.0 @@ -124,13 +178,17 @@ pbr==6.0.0 # stevedore pkginfo==1.9.6 # via twine +pkgutil-resolve-name==1.3.10 + # via + # -r requirements/test.txt + # jsonschema platformdirs==4.1.0 # via pylint pluggy==1.3.0 # via # -r requirements/test.txt # pytest -psutil==5.9.6 +psutil==5.9.7 # via # -r requirements/test.txt # edx-django-utils @@ -146,6 +204,12 @@ pygments==2.17.2 # via # readme-renderer # rich +pyjwt[crypto]==2.8.0 + # via + # -r requirements/test.txt + # drf-jwt + # edx-drf-extensions + # pyjwt pylint==3.0.3 # via # edx-lint @@ -160,11 +224,15 @@ pylint-plugin-utils==0.8.2 # via # pylint-celery # pylint-django +pymongo==3.13.0 + # via + # -r requirements/test.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/test.txt # edx-django-utils -pytest==7.4.3 +pytest==7.4.4 # via # -r requirements/test.txt # pytest-cov @@ -181,14 +249,22 @@ pytz==2023.3.post1 # via # -r requirements/test.txt # django + # djangorestframework pyyaml==6.0.1 # via # -r requirements/test.txt # code-annotations readme-renderer==42.0 # via twine +referencing==0.32.0 + # via + # -r requirements/test.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 # via + # -r requirements/test.txt + # edx-drf-extensions # requests-toolbelt # twine requests-toolbelt==1.0.0 @@ -197,10 +273,22 @@ rfc3986==2.0.0 # via twine rich==13.7.0 # via twine +rpds-py==0.16.2 + # via + # -r requirements/test.txt + # jsonschema + # referencing secretstorage==3.3.3 # via keyring +semantic-version==2.10.0 + # via + # -r requirements/test.txt + # edx-drf-extensions six==1.16.0 - # via edx-lint + # via + # -r requirements/test.txt + # edx-codejail + # edx-lint snowballstemmer==2.2.0 # via pydocstyle sqlparse==0.4.4 @@ -212,6 +300,7 @@ stevedore==5.1.0 # -r requirements/test.txt # code-annotations # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 # via # -r requirements/test.txt @@ -231,13 +320,16 @@ typing-extensions==4.9.0 # -r requirements/test.txt # asgiref # astroid + # edx-opaque-keys # pylint # rich urllib3==2.1.0 # via + # -r requirements/test.txt # requests # twine zipp==3.17.0 # via + # -r requirements/test.txt # importlib-metadata # importlib-resources diff --git a/requirements/scripts.txt b/requirements/scripts.txt index 90ce1d7..0847847 100644 --- a/requirements/scripts.txt +++ b/requirements/scripts.txt @@ -8,34 +8,52 @@ asgiref==3.7.2 # via # -r requirements/base.txt # django -attrs==23.1.0 - # via openedx-events +attrs==23.2.0 + # via + # -r requirements/base.txt + # jsonschema + # openedx-events + # referencing avro==1.11.3 # via confluent-kafka certifi==2023.11.17 - # via requests + # via + # -r requirements/base.txt + # requests cffi==1.16.0 # via # -r requirements/base.txt + # cryptography # pynacl charset-normalizer==3.3.2 - # via requests + # via + # -r requirements/base.txt + # requests click==8.1.7 # via # -r requirements/base.txt # code-annotations # edx-django-utils code-annotations==1.5.0 - # via edx-toggles + # via + # -r requirements/base.txt + # edx-toggles confluent-kafka[avro]==2.3.0 # via -r requirements/scripts.in +cryptography==41.0.7 + # via + # -r requirements/base.txt + # pyjwt django==3.2.23 # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.txt # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions # edx-event-bus-kafka # edx-toggles # openedx-events @@ -48,28 +66,65 @@ django-waffle==4.1.0 # via # -r requirements/base.txt # edx-django-utils + # edx-drf-extensions # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions +drf-jwt==1.19.2 + # via + # -r requirements/base.txt + # edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/base.txt edx-django-utils==5.9.0 # via # -r requirements/base.txt + # edx-drf-extensions # edx-event-bus-kafka # edx-toggles +edx-drf-extensions==9.0.1 + # via -r requirements/base.txt edx-event-bus-kafka==5.5.0 # via -r requirements/scripts.in edx-opaque-keys[django]==2.5.1 - # via openedx-events + # via + # -r requirements/base.txt + # edx-drf-extensions + # openedx-events edx-toggles==5.1.0 - # via edx-event-bus-kafka -fastavro==1.9.1 + # via + # -r requirements/base.txt + # edx-event-bus-kafka +fastavro==1.9.2 # via # confluent-kafka # openedx-events idna==3.6 - # via requests + # via + # -r requirements/base.txt + # requests +importlib-resources==6.1.1 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications jinja2==3.1.2 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations +jsonschema==4.20.0 + # via -r requirements/base.txt +jsonschema-specifications==2023.12.1 + # via + # -r requirements/base.txt + # jsonschema markupsafe==2.1.3 - # via jinja2 + # via + # -r requirements/base.txt + # jinja2 newrelic==9.3.0 # via # -r requirements/base.txt @@ -80,7 +135,11 @@ pbr==6.0.0 # via # -r requirements/base.txt # stevedore -psutil==5.9.6 +pkgutil-resolve-name==1.3.10 + # via + # -r requirements/base.txt + # jsonschema +psutil==5.9.7 # via # -r requirements/base.txt # edx-django-utils @@ -88,22 +147,56 @@ pycparser==2.21 # via # -r requirements/base.txt # cffi +pyjwt[crypto]==2.8.0 + # via + # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions + # pyjwt pymongo==3.13.0 - # via edx-opaque-keys + # via + # -r requirements/base.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/base.txt # edx-django-utils python-slugify==8.0.1 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations pytz==2023.3.post1 # via # -r requirements/base.txt # django + # djangorestframework pyyaml==6.0.1 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations +referencing==0.32.0 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications requests==2.31.0 - # via confluent-kafka + # via + # -r requirements/base.txt + # confluent-kafka + # edx-drf-extensions +rpds-py==0.16.2 + # via + # -r requirements/base.txt + # jsonschema + # referencing +semantic-version==2.10.0 + # via + # -r requirements/base.txt + # edx-drf-extensions +six==1.16.0 + # via + # -r requirements/base.txt + # edx-codejail sqlparse==0.4.4 # via # -r requirements/base.txt @@ -115,11 +208,19 @@ stevedore==5.1.0 # edx-django-utils # edx-opaque-keys text-unidecode==1.3 - # via python-slugify + # via + # -r requirements/base.txt + # python-slugify typing-extensions==4.9.0 # via # -r requirements/base.txt # asgiref # edx-opaque-keys urllib3==2.1.0 - # via requests + # via + # -r requirements/base.txt + # requests +zipp==3.17.0 + # via + # -r requirements/base.txt + # importlib-resources diff --git a/requirements/test.txt b/requirements/test.txt index 5c89cd3..f88fdf7 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -8,45 +8,114 @@ asgiref==3.7.2 # via # -r requirements/base.txt # django +attrs==23.2.0 + # via + # -r requirements/base.txt + # jsonschema + # referencing +certifi==2023.11.17 + # via + # -r requirements/base.txt + # requests cffi==1.16.0 # via # -r requirements/base.txt + # cryptography # pynacl +charset-normalizer==3.3.2 + # via + # -r requirements/base.txt + # requests click==8.1.7 # via # -r requirements/base.txt # code-annotations # edx-django-utils code-annotations==1.5.0 - # via -r requirements/test.in -coverage[toml]==7.3.3 + # via + # -r requirements/base.txt + # -r requirements/test.in + # edx-toggles +coverage[toml]==7.4.0 # via # coverage # pytest-cov +cryptography==41.0.7 + # via + # -r requirements/base.txt + # pyjwt # via # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.txt # django-crum # django-waffle + # djangorestframework + # drf-jwt # edx-django-utils + # edx-drf-extensions + # edx-toggles django-crum==0.7.9 # via # -r requirements/base.txt # edx-django-utils + # edx-toggles django-waffle==4.1.0 # via # -r requirements/base.txt # edx-django-utils + # edx-drf-extensions + # edx-toggles +djangorestframework==3.14.0 + # via + # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions +drf-jwt==1.19.2 + # via + # -r requirements/base.txt + # edx-drf-extensions +edx-codejail==3.3.3 + # via -r requirements/base.txt edx-django-utils==5.9.0 + # via + # -r requirements/base.txt + # edx-drf-extensions + # edx-toggles +edx-drf-extensions==9.0.1 + # via -r requirements/base.txt +edx-opaque-keys==2.5.1 + # via + # -r requirements/base.txt + # edx-drf-extensions +edx-toggles==5.1.0 # via -r requirements/base.txt exceptiongroup==1.2.0 # via pytest +idna==3.6 + # via + # -r requirements/base.txt + # requests +importlib-resources==6.1.1 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications iniconfig==2.0.0 # via pytest jinja2==3.1.2 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations +jsonschema==4.20.0 + # via -r requirements/base.txt +jsonschema-specifications==2023.12.1 + # via + # -r requirements/base.txt + # jsonschema markupsafe==2.1.3 - # via jinja2 + # via + # -r requirements/base.txt + # jinja2 newrelic==9.3.0 # via # -r requirements/base.txt @@ -57,9 +126,13 @@ pbr==6.0.0 # via # -r requirements/base.txt # stevedore +pkgutil-resolve-name==1.3.10 + # via + # -r requirements/base.txt + # jsonschema pluggy==1.3.0 # via pytest -psutil==5.9.6 +psutil==5.9.7 # via # -r requirements/base.txt # edx-django-utils @@ -67,11 +140,21 @@ pycparser==2.21 # via # -r requirements/base.txt # cffi +pyjwt[crypto]==2.8.0 + # via + # -r requirements/base.txt + # drf-jwt + # edx-drf-extensions + # pyjwt +pymongo==3.13.0 + # via + # -r requirements/base.txt + # edx-opaque-keys pynacl==1.5.0 # via # -r requirements/base.txt # edx-django-utils -pytest==7.4.3 +pytest==7.4.4 # via # pytest-cov # pytest-django @@ -80,13 +163,40 @@ pytest-cov==4.1.0 pytest-django==4.7.0 # via -r requirements/test.in python-slugify==8.0.1 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations pytz==2023.3.post1 # via # -r requirements/base.txt # django + # djangorestframework pyyaml==6.0.1 - # via code-annotations + # via + # -r requirements/base.txt + # code-annotations +referencing==0.32.0 + # via + # -r requirements/base.txt + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # -r requirements/base.txt + # edx-drf-extensions +rpds-py==0.16.2 + # via + # -r requirements/base.txt + # jsonschema + # referencing +semantic-version==2.10.0 + # via + # -r requirements/base.txt + # edx-drf-extensions +six==1.16.0 + # via + # -r requirements/base.txt + # edx-codejail sqlparse==0.4.4 # via # -r requirements/base.txt @@ -96,8 +206,11 @@ stevedore==5.1.0 # -r requirements/base.txt # code-annotations # edx-django-utils + # edx-opaque-keys text-unidecode==1.3 - # via python-slugify + # via + # -r requirements/base.txt + # python-slugify tomli==2.0.1 # via # coverage @@ -106,3 +219,12 @@ typing-extensions==4.9.0 # via # -r requirements/base.txt # asgiref + # edx-opaque-keys +urllib3==2.1.0 + # via + # -r requirements/base.txt + # requests +zipp==3.17.0 + # via + # -r requirements/base.txt + # importlib-resources diff --git a/setup.py b/setup.py index 0a6fb7e..4b0d2af 100644 --- a/setup.py +++ b/setup.py @@ -163,6 +163,7 @@ def is_requirement(line): "lms.djangoapp": [ "arch_experiments = edx_arch_experiments.apps:EdxArchExperimentsConfig", "config_watcher = edx_arch_experiments.config_watcher.apps:ConfigWatcher", + "codejail_service = edx_arch_experiments.codejail_service.apps:CodejailService", ], }, )