dobu/functions.sh

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'
}