diff --git a/common/lib/capa/capa/safe_exec/safe_exec.py b/common/lib/capa/capa/safe_exec/safe_exec.py index c71854f917..2012d8544f 100644 --- a/common/lib/capa/capa/safe_exec/safe_exec.py +++ b/common/lib/capa/capa/safe_exec/safe_exec.py @@ -2,10 +2,13 @@ import hashlib +import requests +import json from codejail.safe_exec import SafeExecException, json_safe from codejail.safe_exec import not_safe_exec as codejail_not_safe_exec from codejail.safe_exec import safe_exec as codejail_safe_exec +from django.conf import settings from edx_django_utils.monitoring import function_trace import six from six import text_type @@ -143,28 +146,63 @@ def safe_exec( # Create the complete code we'll run. code_prolog = CODE_PROLOG % random_seed - # Decide which code executor to use. - if unsafely: - exec_fn = codejail_not_safe_exec + if settings.FEATURES.get('ENABLE_CODEJAIL_REST_SERVICE', False): + try: + codejail_service_endpoint = "".join([ + settings.CODE_JAIL_REST_SERVICE_HOST, + "/api/v0/code-exec" + ]) + data = { + "code": code_prolog + LAZY_IMPORTS + code, + "globals_dict": globals_dict, + "python_path": python_path, + "limit_overrides_context": limit_overrides_context, + "slug": slug, + "unsafely": unsafely + } + datajson = json.dumps(data) + response = requests.request( + "POST", + codejail_service_endpoint, + files=extra_files, + data={'payload': datajson} + ) + response_json = response.json() + emsg = response_json["emsg"] + if emsg: + exception_msg = ". ".join([ + emsg, + "For more information check Codejail Service logs." + ]) + + exception = SafeExecException(emsg) + globals_dict.update(response_json["globals_dict"]) + except Exception as e: + raise e + emsg = None else: - exec_fn = codejail_safe_exec + # Decide which code executor to use. + if unsafely: + exec_fn = codejail_not_safe_exec + else: + exec_fn = codejail_safe_exec - # Run the code! Results are side effects in globals_dict. - try: - exec_fn( - code_prolog + LAZY_IMPORTS + code, - globals_dict, - python_path=python_path, - extra_files=extra_files, - limit_overrides_context=limit_overrides_context, - slug=slug, - ) - except SafeExecException as e: - # Saving SafeExecException e in exception to be used later. - exception = e - emsg = text_type(e) - else: - emsg = None + # Run the code! Results are side effects in globals_dict. + try: + exec_fn( + code_prolog + LAZY_IMPORTS + code, + globals_dict, + python_path=python_path, + extra_files=extra_files, + limit_overrides_context=limit_overrides_context, + slug=slug, + ) + except SafeExecException as e: + # Saving SafeExecException e in exception to be used later. + exception = e + emsg = text_type(e) + else: + emsg = None # Put the result back in the cache. This is complicated by the fact that # the globals dict might not be entirely serializable. diff --git a/lms/envs/common.py b/lms/envs/common.py index 0bb174d0ec..12ad10d314 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -948,6 +948,18 @@ FEATURES = { # .. toggle_target_removal_date: 2021-10-01 # .. toggle_tickets: 'https://openedx.atlassian.net/browse/MICROBA-1405' 'ENABLE_V2_CERT_DISPLAY_SETTINGS': False, + + # .. toggle_name: ENABLE_CODEJAIL_REST_SERVICE + # .. toggle_implementation: DjangoSetting + # .. toggle_default: False + # .. toggle_description: Set this to True if you want to run Codejail code using + # a separate VM or container and communicate with edx-platform using REST API. + # .. toggle_use_cases: tutor + # .. toggle_creation_date: 2021-08-19 + # .. toggle_target_removal_date: None + # .. toggle_warnings: + # .. toggle_tickets: + 'ENABLE_CODEJAIL_REST_SERVICE': False, } # Specifies extra XBlock fields that should available when requested via the Course Blocks API @@ -1629,6 +1641,9 @@ CODE_JAIL = { # ] COURSES_WITH_UNSAFE_CODE = [] +# Cojail REST service +CODE_JAIL_REST_SERVICE_HOST = 'http://127.0.0.1:8550' + ############################### DJANGO BUILT-INS ############################### # Change DEBUG in your environment settings files, not here DEBUG = False