diff --git a/deploy/files/etc/sudoers.d/left4me b/deploy/files/etc/sudoers.d/left4me index 02cccc6..5aa94eb 100644 --- a/deploy/files/etc/sudoers.d/left4me +++ b/deploy/files/etc/sudoers.d/left4me @@ -2,3 +2,4 @@ Defaults:left4me !requiretty left4me ALL=(root) NOPASSWD: /usr/local/libexec/left4me/left4me-systemctl * left4me ALL=(root) NOPASSWD: /usr/local/libexec/left4me/left4me-journalctl * left4me ALL=(root) NOPASSWD: /usr/local/libexec/left4me/left4me-overlay mount *, /usr/local/libexec/left4me/left4me-overlay umount * +left4me ALL=(root) NOPASSWD: /usr/local/libexec/left4me/left4me-script-sandbox diff --git a/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox b/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox new file mode 100755 index 0000000..625f026 --- /dev/null +++ b/deploy/files/usr/local/libexec/left4me/left4me-script-sandbox @@ -0,0 +1,55 @@ +#!/bin/bash +# Privileged sandbox launcher for left4me script overlays. +# +# Invoked via sudo by the web user with two arguments: +# numeric overlay id; bind-mounts /var/lib/left4me/overlays/ +# read-write at /overlay inside the sandbox. +# absolute path to a bash file already written by the web app; +# bind-mounted read-only at /script.sh inside the sandbox. +# +# The script runs under bubblewrap inside a transient systemd scope so we get +# cgroup-v2 limits (memory / tasks / cpu) and a wallclock kill via +# RuntimeMaxSec. The sandbox drops to the unprivileged l4d2-sandbox UID; +# host filesystems are exposed read-only except /overlay (rw) and tmpfs +# /tmp + /run. Network namespace is *not* unshared — scripts must reach the +# public internet to download workshop / l4d2center / cedapug content. +set -euo pipefail + +[[ $# -eq 2 ]] || { echo "usage: $0