-
Notifications
You must be signed in to change notification settings - Fork 2
Development: Add a custom apparmor profile to run the bubblewrap tool for unprivileged namespace creation
#162
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
base: main
Are you sure you want to change the base?
Conversation
… to run for docker containers
WalkthroughAdds an AppArmor profile Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Operator
participant Ansible
participant TargetHost
participant AppArmor as "AppArmor Kernel/Parser"
Operator->>Ansible: run role artemis: docker_deploy_artemis
Ansible->>TargetHost: apt install apparmor, apparmor-utils
Ansible->>TargetHost: copy apparmor_profile_bubblewrap -> /etc/apparmor.d/
note right of TargetHost: copy task notifies "Reload apparmor profile"
Ansible->>TargetHost: continue remaining deploy tasks
rect rgba(200,230,255,0.6)
Ansible->>TargetHost: handler: Reload apparmor profile
TargetHost->>AppArmor: apparmor_parser -r /etc/apparmor.d/apparmor_profile_bubblewrap
AppArmor-->>TargetHost: profile loaded/reloaded
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
roles/artemis/handlers/main.yml (1)
4-7: Use fully qualified collection name for command module.For consistency with other tasks in the codebase and to align with Ansible best practices, consider using
ansible.builtin.commandinstead of the barecommandmodule.Apply this diff:
- name: Reload apparmor profile become: true - command: apparmor_parser -r /etc/apparmor.d/apparmor_profile_bubblewrap + ansible.builtin.command: apparmor_parser -r /etc/apparmor.d/apparmor_profile_bubblewrap listen: Reload apparmor profile
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
roles/artemis/files/apparmor_profile_bubblewrap(1 hunks)roles/artemis/handlers/main.yml(1 hunks)roles/artemis/tasks/docker_deploy_artemis.yml(1 hunks)
🔇 Additional comments (6)
roles/artemis/tasks/docker_deploy_artemis.yml (1)
2-8: LGTM!The task correctly installs the required AppArmor utilities with appropriate privilege escalation. The package names are correct for Ubuntu/Debian systems.
roles/artemis/files/apparmor_profile_bubblewrap (5)
1-26: LGTM!The profile header, capabilities, networking, signals, and ptrace rules are well-structured and appropriate for container isolation. The inclusion of
sys_admincapability (line 19) is correctly documented as needed for mount mediation.
28-28: Verify if file access can be more restrictive.The
file,rule grants broad file access to all files without restrictions. While this provides maximum flexibility for build containers, consider whether this could be constrained to specific paths (e.g.,/home/**,/tmp/**,/workspace/**) to reduce the attack surface.If the current broad access is intentional and required for Bubblewrap's flexibility, document this decision in a comment above line 28.
30-34: LGTM!The namespace and mount mediation rules correctly include the
usernsrule, which is the key requirement from the PR objectives to enable unprivileged user namespaces for Bubblewrap on Ubuntu 23.10/24.04+.
36-66: LGTM!The mount rules are comprehensive and well-documented. They correctly handle:
- Staging and finalization of mounts during Bubblewrap setup
- Various filesystem types (proc, tmpfs, devpts, mqueue, sysfs)
- Bind and recursive bind mounts
- Mount propagation options
- Move and remount operations
The inline comments effectively explain the purpose of each rule.
67-73: LGTM!The denial rules appropriately restrict access to sensitive kernel interfaces (
/sys/**,/proc/sysrq-trigger,/proc/kcore), following Docker's default security posture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
roles/artemis/handlers/main.yml (1)
4-7: Use absolute path (and quiet flag) for apparmor_parser to avoid PATH issues under sudo.Safer on Ubuntu: use /sbin or /usr/sbin and suppress warnings.
- command: apparmor_parser -r /etc/apparmor.d/apparmor_profile_bubblewrap + command: /sbin/apparmor_parser -q -r /etc/apparmor.d/apparmor_profile_bubblewrapPlease verify which path exists on your targets (/sbin vs /usr/sbin).
roles/artemis/tasks/docker_deploy_artemis.yml (1)
2-11: Gate apt-specific task to apt-based systems.Prevents failures on non-Debian hosts.
- name: Ensure AppArmor utilities are present become: true apt: name: - apparmor - apparmor-utils state: present update_cache: true cache_valid_time: 3600 + when: ansible_pkg_mgr == "apt" + tags: [apparmor]
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
roles/artemis/handlers/main.yml(1 hunks)roles/artemis/tasks/docker_deploy_artemis.yml(1 hunks)
🔇 Additional comments (1)
roles/artemis/tasks/docker_deploy_artemis.yml (1)
12-20: LGTM; confirm Docker uses the profile’s declared name.Copy/permissions/notify look correct. Ensure the profile name used with
--security-opt apparmor=...matches the name declared inside the profile (not just the filename).
MarkusPaulsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good. The main cut into the security layer seems to be the allowance of unprivileged user namespaces, with seems justifiable for the purpose it serves (allows Phobos to operate correctly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
roles/artemis/tasks/docker_deploy_artemis.yml (2)
2-11: Gate apt task to Debian-family and ensure AppArmor service is active when enabled.Avoid running apt on non-Debian systems and ensure AppArmor is started/enabled when opting in.
Apply this diff to the apt task:
- name: Ensure AppArmor utilities are present become: true apt: name: - apparmor - apparmor-utils state: present update_cache: true cache_valid_time: 3600 + when: + - artemis_enable_bwrap_apparmor_profile | default(false) + - ansible_facts.os_family == 'Debian'Add this task (nearby) to enable the service:
- name: Ensure AppArmor service is enabled and running become: true when: - artemis_enable_bwrap_apparmor_profile | default(false) - ansible_facts.os_family == 'Debian' ansible.builtin.service: name: apparmor state: started enabled: true
12-20: Privilege escalation is correct; align mode and FQCN for consistency.Good addition of become: true. Use "0644" consistently and prefer FQCN.
Apply this diff:
- copy: + ansible.builtin.copy: @@ - mode: "644" + mode: "0644"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
roles/artemis/tasks/docker_deploy_artemis.yml(1 hunks)
🔇 Additional comments (1)
roles/artemis/tasks/docker_deploy_artemis.yml (1)
12-20: AppArmor reload handler and profile name are correct Handler “Reload apparmor profile” in roles/artemis/handlers/main.yml invokesapparmor_parseron/etc/apparmor.d/apparmor_profile_bubblewrap, and the profile is defined asdocker-bwrapwith no alternate names detected.
| - name: Ensure AppArmor utilities are present | ||
| become: true | ||
| apt: | ||
| name: | ||
| - apparmor | ||
| - apparmor-utils | ||
| state: present | ||
| update_cache: true | ||
| cache_valid_time: 3600 | ||
|
|
||
| - name: Install AppArmor profile for bwrap-enabled build containers | ||
| become: true | ||
| copy: | ||
| src: apparmor_profile_bubblewrap | ||
| dest: /etc/apparmor.d/apparmor_profile_bubblewrap | ||
| owner: root | ||
| group: root | ||
| mode: "644" | ||
| notify: Reload apparmor profile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make AppArmor integration opt-in (as per PR intent).
These tasks run unconditionally. To keep the profile optional, gate both with a feature flag defaulting to false.
Apply this diff:
- name: Ensure AppArmor utilities are present
become: true
apt:
name:
- apparmor
- apparmor-utils
state: present
update_cache: true
cache_valid_time: 3600
+ when: artemis_enable_bwrap_apparmor_profile | default(false)
- name: Install AppArmor profile for bwrap-enabled build containers
become: true
copy:
src: apparmor_profile_bubblewrap
dest: /etc/apparmor.d/apparmor_profile_bubblewrap
owner: root
group: root
- mode: "644"
+ mode: "0644"
notify: Reload apparmor profile
+ when: artemis_enable_bwrap_apparmor_profile | default(false)And define the variable in role defaults:
# roles/artemis/defaults/main.yml
artemis_enable_bwrap_apparmor_profile: false🤖 Prompt for AI Agents
In roles/artemis/tasks/docker_deploy_artemis.yml around lines 2-20 the AppArmor
install and copy tasks run unconditionally; make them opt-in by adding a
conditional check using a boolean feature flag
(artemis_enable_bwrap_apparmor_profile) so both tasks only run when that
variable is true, and add the variable with default false in
roles/artemis/defaults/main.yml; ensure the tasks include the same when
condition and that the default variable is documented/defined as false in the
role defaults.
Add optional AppArmor profile to enable unprivileged user namespaces for Bubblewrap (bwrap)
This PR adds an optional AppArmor profile and the necessary Ansible tasks to install and load it on Artemis build agent hosts.
The profile enables the controlled use of unprivileged user namespaces (used by Bubblewrap, where Apparmor restricts such namespaces by default on Ubuntu 2024.04+.
This change lays the groundwork to isolate programming exercise builds inside Docker containers, by utilizing Bubblewrap to further restrict access through untrusted student code.
It does not activate or use the profile by default, and therefore introduces no behavioral or security change until Artemis containers explicitly request it.
Background
Ubuntu 23.10 + 24.04 introduced “restricted unprivileged user namespaces.”
Processes can only create useful user namespaces (with capabilities) if their AppArmor profile includes the rule
userns.To support Bubblewrap isolation, we need a host-side profile that grants this rule and can be attached per container via Docker’s --security-opt apparmor={apparmor_profile}.
Testing
sudo aa-status | grep docker-allow-bwrapdocker run --rm --security-opt apparmor=apparmor_profile_bubblewrap ubuntu:24.04 \ bash -lc 'unshare -Ur true && echo OK'Future
Future changes to Artemis (specifically
BuildJobContainerServicein the Artemis Codebase) will use this profile when starting build containers that rely on Bubblewrap/Phobos.This PR prepares the infrastructure for that work.
Summary by CodeRabbit
New Features
Chores