160 lines
5.2 KiB
Bash
160 lines
5.2 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -e
|
|
|
|
script_path="$(dirname "$(realpath "$0")")"
|
|
|
|
DOBU_TMP=/tmp/dobu
|
|
|
|
. "$script_path/config-default.sh"
|
|
[ -f "$script_path/config.sh" ] && . "$script_path/config.sh"
|
|
|
|
# This function exists so that we can update the seccomp profile used
|
|
update_podman_security_args() {
|
|
local seccomp_profile="$1"
|
|
[ -z "$seccomp_profile" ] && seccomp_profile="seccomp.json"
|
|
# Default security-related arguments ALWAYS passed to podman
|
|
# Install a seccomp filter that disallows sub-namespaces which could lead to exploits
|
|
# and use the keep-id mode of userns, such that the user 1100 is mapped to the
|
|
# current host user, and the root user inside the namespace is mapped to an unrelated
|
|
# large uid on the host.
|
|
podman_security_args=(
|
|
--security-opt
|
|
seccomp="$script_path/assets/$seccomp_profile"
|
|
--userns=keep-id:uid=1100,gid=1100
|
|
)
|
|
}
|
|
|
|
update_podman_security_args
|
|
|
|
assert_prerequisites() {
|
|
command -v podman >/dev/null 2>&1 || die "Podman is required"
|
|
command -v jq >/dev/null 2>&1 || die "jq is required"
|
|
[ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ] || die "Dobu must be run under a compliant Wayland compositor"
|
|
}
|
|
|
|
die() {
|
|
echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu][error] $1" >&2
|
|
exit 1
|
|
}
|
|
|
|
log() {
|
|
echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu] $1"
|
|
}
|
|
|
|
is_in_array() {
|
|
local e match="$1"
|
|
shift
|
|
for e; do [[ "$e" == "$match" ]] && return 0; done
|
|
return 1
|
|
}
|
|
|
|
relative_path_to_image_name() {
|
|
local context_path="$script_path/$1"
|
|
|
|
[ -d "$context_path" ] || die "$context_path does not exist"
|
|
|
|
local relative_path="$(realpath --relative-to="$script_path" "$context_path")"
|
|
|
|
if [[ "$relative_path" =~ \.\. ]]; then
|
|
die "Image path must be a subdirectory of the dobu project"
|
|
fi
|
|
|
|
local image_name="dobu/${relative_path/\//-}"
|
|
echo "$image_name"
|
|
}
|
|
|
|
assert_image_exists() {
|
|
podman inspect "$1" > /dev/null 2>&1 || die "Image $1 does not exist; please build the image first"
|
|
}
|
|
|
|
container_exists() {
|
|
podman container exists $1 > /dev/null 2>&1
|
|
}
|
|
|
|
get_image_label() {
|
|
assert_image_exists "$1"
|
|
podman inspect "$1" | jq -r ".[0].Labels.\"$2\""
|
|
}
|
|
|
|
remove_stale_container() {
|
|
container_exists "$1" || return 0
|
|
local is_running="$(podman inspect "$1" | jq -r '.[0].State.Running')"
|
|
if [ "$is_running" == "false" ]; then
|
|
podman rm -f "$1"
|
|
fi
|
|
}
|
|
|
|
# Note: this works with __containers__, not images
|
|
container_entrypoint() {
|
|
podman inspect $1 | jq -r '.[0].Config.Entrypoint'
|
|
}
|
|
|
|
ensure_compositor_sandbox() {
|
|
local app_name="$1"
|
|
local sandbox_name=dobu-deps-compositor-sandbox-$app_name
|
|
local sandbox_tmp="$DOBU_TMP/$app_name"
|
|
assert_image_exists dobu/deps-compositor-sandbox
|
|
remove_stale_container $sandbox_name
|
|
if container_exists $sandbox_name; then
|
|
existing_config_sha="$(sha1sum "$sandbox_tmp/wl-mitm-config.toml" | awk '{ print $1; }')"
|
|
new_config_sha="$(sha1sum "$script_path/assets/wl-mitm-config.toml" | awk '{ print $1; }')"
|
|
[ -S "$sandbox_tmp/X11-unix/X1" ] && [ -S "$sandbox_tmp/xdg_runtime/wayland-10" ] && [ "$existing_config_sha" == "$new_config_sha" ] && return
|
|
log "Killing non-functional compositor-sandbox container"
|
|
podman kill $sandbox_name
|
|
podman rm -f $sandbox_name
|
|
fi
|
|
|
|
rm -rf "$sandbox_tmp/xdg_runtime" || true
|
|
rm -rf "$sandbox_tmp/X11-unix" || true
|
|
mkdir -p "$sandbox_tmp/xdg_runtime"
|
|
mkdir -p "$sandbox_tmp/X11-unix"
|
|
cp "$script_path/assets/wl-mitm-config.toml" "$sandbox_tmp/wl-mitm-config.toml"
|
|
|
|
local comp_extra_args=""
|
|
local dbus_src=""
|
|
|
|
if [ ! -z "$DBUS_SESSION_BUS_ADDRESS" ]; then
|
|
dbus_src="$(echo "$DBUS_SESSION_BUS_ADDRESS" | cut -d"=" -f2)"
|
|
if [ -S "$dbus_src" ]; then
|
|
log "Found dbus address $dbus_src, passing to wl-mitm for notify_cmd usage"
|
|
comp_extra_args="$extra_args -v $dbus_src:/tmp/dbus -e DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus"
|
|
fi
|
|
fi
|
|
|
|
log "Starting compositor-sandbox (wl-mitm for Wayland and X Sommelier for X11)..."
|
|
|
|
podman run --rm -d "${podman_security_args[@]}" --name $sandbox_name \
|
|
-v "$sandbox_tmp/xdg_runtime":/xdg_runtime \
|
|
`# wl-mitm config` \
|
|
-v "$sandbox_tmp/wl-mitm-config.toml":/tmp/wl-mitm-config.toml \
|
|
`# Pass through host wayland display for Sommelier always as wayland-0` \
|
|
-v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY":/xdg_runtime/wayland-0 \
|
|
`# X11-unix uses hard-coded path` \
|
|
-v "$sandbox_tmp/X11-unix":/tmp/.X11-unix \
|
|
`# DRM render nodes` \
|
|
-v /dev/dri:/dev/dri \
|
|
$comp_extra_args dobu/deps-compositor-sandbox
|
|
while [ ! -S "$sandbox_tmp/xdg_runtime/wayland-10" ] || [ ! -S "$sandbox_tmp/X11-unix/X1" ]; do
|
|
sleep 0.5
|
|
done
|
|
}
|
|
|
|
get_archlinux_pkg_ver() {
|
|
curl https://archlinux.org/packages/$1/json/ 2>/dev/null | jq -r '. | .pkgver + "-" + .pkgrel'
|
|
}
|
|
|
|
get_aur_pkg_ver() {
|
|
curl "https://aur.archlinux.org/rpc/v5/info?arg[]=$1" 2>/dev/null | jq -r '.results[0].Version'
|
|
}
|
|
|
|
# Note: this does not specify which version of Ubuntu to use, because we don't actually care
|
|
# this version can and will only used to invalidate Docker cache, and we only need a vague
|
|
# idea of whether this package has been updated upstream.
|
|
get_ubuntu_pkg_ver() {
|
|
curl "https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=$1&exact_match=true" | jq -r '.entries[0].source_package_version'
|
|
}
|
|
|
|
get_github_pkg_ver() {
|
|
curl "https://api.github.com/repos/$1/tags" | jq -r '.[0].name'
|
|
}
|