-
Notifications
You must be signed in to change notification settings - Fork 12
feat: AppArmor confinement for codejail-service #109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
f395882
feat: AppArmor confinement for codejail-service
timmc-edx baa60c9
fixup! Switch to no-# include; add comments
timmc-edx 672ca52
fixup! Remove attach_disconnected and add more comments
timmc-edx 0f29e5c
fixup! add explanation for abi
timmc-edx 9d81e2a
fixup! add note about subprofile path
timmc-edx edeeaea
fixup! Make it easier to enable (rather than copying the default)
timmc-edx 260f966
fixup! Deny outbound connections; clean up capabilities
timmc-edx 058065e
fixup! Shrink docs for codejail setup (will move to service repo docs)
timmc-edx 8e50c28
fixup! Clarify instructions
timmc-edx 72ac296
fixup! Clarify discussion of profile renaming
timmc-edx 2171ad7
fixup! Use name of subprofile rather than a description of it
timmc-edx b27d15f
fixup! Link to manpage
timmc-edx 5b07706
fixup! Explain `m` access mode
timmc-edx e826482
fixup! More explicit locations for sandbox path coordination
timmc-edx f89e2ab
fixup! Apply suggestion re: Mac TODO
timmc-edx f9f3eec
fixup! Add "file" for clarity
timmc-edx f0e80ee
fixup! Comment on port mismatch
timmc-edx a77c26c
fixup! Rename child profile to codejail_sandbox
timmc-edx 1adda18
fixup! Clarify what "important" is relative to
timmc-edx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # AppArmor profile for running codejail-service in devstack. | ||
| # | ||
| # #=========# | ||
| # # WARNING # | ||
| # #=========# | ||
| # | ||
| # This is not a complete and secure apparmor profile! Do not use this | ||
| # in any deployed environment (even a staging environment) without | ||
| # careful inspection and modification to fit your needs. | ||
| # | ||
| # Failure to apply a secure apparmor profile *will* likely result in a | ||
| # compromise of your environment by an attacker. | ||
| # | ||
| # We may at some point make this file good enough for confinement in | ||
| # production, but for now it is only intended to be used in devstack. | ||
|
|
||
| # Sets standard variables used by abstractions/base, later. Controlled | ||
| # by OS, see /etc/apparmor.d/tunables/global for contents. | ||
| include <tunables/global> | ||
|
|
||
| # Require that the system understands the feature set that this policy was written | ||
| # for. If we didn't include this, then on Ubuntu >= 22.04, AppArmor might assume | ||
| # the wrong feature set was requested, and some rules might become too permissive. | ||
| # See https://github.com/netblue30/firejail/issues/3659#issuecomment-711074899 | ||
| abi <abi/3.0>, | ||
|
|
||
| # This outer profile applies to the entire container, and isn't as | ||
| # important. If the sandbox profile doesn't work, it's not likely that | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # the outer one is going to help. But there may be some small value in | ||
| # defense-in-depth, as it's possible that a bug in the child (sandbox) | ||
| # profile isn't present in the outer one. | ||
| profile codejail_service flags=(mediate_deleted) { | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Allow access to a variety of commonly needed, generally safe things | ||
| # (such as reading /dev/random, free memory, etc.) | ||
| # | ||
| # Manpage: "Includes files that should be readable and writable in all profiles." | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| include <abstractions/base> | ||
|
|
||
| # Filesystem access -- self-explanatory | ||
| file, | ||
|
|
||
| # `network` is required for sudo | ||
| # TODO: Restrict this so that general network access is not permitted | ||
| network, | ||
|
|
||
| # Various capabilities required for sudoing to sandbox (setuid, | ||
| # setgid, audit_write) and for sending a kill signal (kill). | ||
| capability setuid setgid audit_write kill, | ||
|
|
||
| # Allow sending a kill signal to the sandbox when the execution | ||
| # runs beyond time limits. | ||
| signal (send) set=(kill) peer=codejail_service//child, | ||
|
|
||
| # The core of the confinement: When the sandbox Python is executed, switch to | ||
| # the (extremely constrained) child profile. | ||
| # | ||
| # This path needs to be coordinated with the Dockerfile and Django settings. | ||
| # | ||
| # Manpage: "Cx: transition to subprofile on execute -- scrub the environment" | ||
| /sandbox/venv/bin/python Cx -> child, | ||
timmc-edx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # This is the important apparmor profile -- the one that actually | ||
| # constrains the sandbox Python process. | ||
| # | ||
| # mediate_deleted is not well documented, but it seems to indicate that | ||
| # apparmor will continue to make policy decisions in cases where a confined | ||
| # executable has a handle to a file's inode even after the file is removed | ||
| # from the filesystem. | ||
| profile child flags=(mediate_deleted) { | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| # This inner profile also gets general access to "safe" | ||
| # actions; we could list those explicitly out of caution but | ||
| # it could get pretty verbose. | ||
| include <abstractions/base> | ||
|
|
||
| # Read and run binaries and libraries in the virtualenv. This | ||
| # includes the sandbox's copy of Python as well as any | ||
| # dependencies that have been installed for inclusion in | ||
| # sandboxes. | ||
| /sandbox/venv/** rm, | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Allow access to the temporary directories that are set up by | ||
| # codejail, one for each code-exec call. Each /tmp/code-XXXXX | ||
| # contains one execution. | ||
| # | ||
| # Codejail has a hardcoded reference to this file path, although the | ||
| # use of /tmp specifically may be controllable with environment variables: | ||
| # https://github.com/openedx/codejail/blob/0165d9ca351/codejail/util.py#L15 | ||
| /tmp/codejail-*/ r, | ||
| /tmp/codejail-*/** rw, | ||
|
|
||
| # Allow interactive terminal in devstack. | ||
| /dev/pts/* rw, | ||
|
|
||
| # Allow receiving a kill signal from the webapp when the execution | ||
| # runs beyond time limits. | ||
| signal (receive) set=(kill) peer=codejail_service, | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| Codejail service | ||
| ################ | ||
|
|
||
| The ``codejail`` devstack component (codejail-service) requires some additional configuration before it can be enabled. This page describes how to set it up and debug it. | ||
|
|
||
| Background | ||
| ********** | ||
|
|
||
| Both LMS and CMS can run Python code submitted by instructors and learners in order to implement custom Python-graded problems. By default this involves running the code on the same host as edxapp itself. Ordinarily this would be quite dangerous, but we use a sandboxing library called `codejail <https://github.com/openedx/codejail>`__ in order to confine the code execution in terms of disk and network access as well as memory, CPU, and other resource limits. Part of these restrictions are implemented via AppArmor, a utility available in some Linux distributions (including Debian and Ubuntu). | ||
|
|
||
| While AppArmor provides good protection, a sandbox escape could still be possible due to misconfiguration or bugs in AppArmor. For defense in depth, we're setting up a dedicated `codejail service <https://github.com/openedx/codejail-service>`__ that will perform code execution for edxapp and which will allow further isolation. | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The default edxapp codejail defaults to unsafe, direct execution of Python code, and this remains true in devstack. We don't even have a way to run on-host codejail securely in devstack. In constrast, the codejail service refuses to run if codejail has not been configured properly, and we've included a way to run it in devstack. | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Configuration | ||
| ************* | ||
|
|
||
| In order to run the codejail devstack component: | ||
|
|
||
| 1. Install AppArmor: ``sudo apt install apparmor`` | ||
robrap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 2. Add the codejail AppArmor profile to your OS, or update it: ``sudo apparmor_parser --replace -W codejail.profile`` | ||
| 3. Configure LMS and CMS to use the codejail-service by uncommenting ``# ENABLE_CODEJAIL_REST_SERVICE = True`` in ``py_configuration_files/{lms,cms}.py`` | ||
| 4. Run ``make codejail-up`` | ||
|
|
||
| The service does not need any provisioning, and does not have dependencies. | ||
|
|
||
| Development | ||
| *********** | ||
|
|
||
| Changes to the AppArmor profile must be coordinated with changes to the Dockerfile, as they need to agree on filesystem paths. | ||
|
|
||
| Any time you update the profile, you'll need to re-run the command to apply the profile. | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The profile file contains the directive ``profile codejail_service``. That defines the name of the profile when it is installed into the kernel. In order to change that name, you must first remove the profile **under the old name**, then install a new profile under the new name. To remove a profile, use the ``--remove`` action instead of the ``-replace`` action: : ``sudo apparmor_parser --remove -W codejail.profile`` | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| The profile name must also agree with the relevant ``security_opt`` line in devstack's ``docker-compose.yml``. | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Debugging | ||
| ********* | ||
|
|
||
| To check whether the profile has been applied, run ``sudo aa-status | grep codejail``. This won't tell you if the profile is out of date, but it will tell you if you have *some* version of it installed. | ||
|
|
||
| If you need to debug the confinement, either because it is restricting too much or too little, a good strategy is to run ``tail -F /var/log/kern.log | grep codejail`` and watch for ``DENIED`` lines. You should expect to see several appear during service startup, as the service is designed to probe the confinement as part of its initial healthcheck. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,3 +27,4 @@ Contents | |
| troubleshoot_general_tips | ||
| manual_upgrades | ||
| advanced_configuration | ||
| codejail | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,28 @@ | ||
| """Settings for devstack use.""" | ||
|
|
||
| from codejail_service.settings.local import * # pylint: disable=wildcard-import | ||
|
|
||
| ALLOWED_HOSTS = [ | ||
| # When called from outside of docker's network (dev's terminal) | ||
| 'localhost', | ||
| # When called from another container (lms, cms) | ||
| 'edx.devstack.codejail', | ||
| ] | ||
|
|
||
| CODEJAIL_ENABLED = True | ||
|
|
||
| CODE_JAIL = { | ||
| # These values are coordinated with the Dockerfile and AppArmor profile | ||
robrap marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| 'python_bin': '/sandbox/venv/bin/python', | ||
| 'user': 'sandbox', | ||
|
|
||
| # Configurable limits. | ||
| 'limits': { | ||
| # CPU-seconds | ||
| 'CPU': 3, | ||
| # 100 MiB memory | ||
| 'VMEM': 100 * 1024 * 1024, | ||
| # Clock seconds | ||
| 'REALTIME': 3, | ||
| }, | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.