mcdbus/docs/examples/mcdbus-proxy.sh
Ryan Malloy 5fa1eb36ef Hamilton remediation: validation, ToolError, elicitation, permission docs
Three-pillar fix from Hamilton review:

Code quality — validate_signature() for D-Bus spec compliance,
MCDBUS_TIMEOUT env var, replace 13 error-as-success returns with
ToolError, monotonic clock deadline on tree walks, sanitize D-Bus
error messages, fix resource connection leak via module-level
BusManager, hasattr guards in conftest.

Elicitation — ctx.elicit() confirmation for system bus call_method
and all set_property calls, graceful degradation when client lacks
elicitation support, MCDBUS_REQUIRE_ELICITATION for hard-fail mode.

Permission docs — four-layer guide (systemd sandboxing, dbus-broker
policy, polkit rules, xdg-dbus-proxy) with ready-to-deploy example
configs validated against xmllint, bash -n, and systemd-analyze.
2026-03-06 11:54:31 -07:00

92 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# mcdbus-proxy.sh -- run mcdbus through a filtered D-Bus proxy
#
# Uses xdg-dbus-proxy to create a restricted session bus socket.
# mcdbus connects to the proxy socket and can only see/talk to
# the services listed below. Everything else is invisible.
#
# Install xdg-dbus-proxy:
# Arch: pacman -S xdg-dbus-proxy
# Debian/Ubuntu: apt install xdg-dbus-proxy
# Fedora: dnf install xdg-dbus-proxy
#
# Usage:
# ./mcdbus-proxy.sh
#
# Or with a custom mcdbus command:
# MCDBUS_CMD="uv run mcdbus" ./mcdbus-proxy.sh
#
# To integrate with systemd:
# ExecStart=/usr/local/bin/mcdbus-proxy.sh
set -euo pipefail
MCDBUS_CMD="${MCDBUS_CMD:-mcdbus}"
# Bail out if xdg-dbus-proxy is not installed
if ! command -v xdg-dbus-proxy &>/dev/null; then
echo "error: xdg-dbus-proxy not found. Install it first." >&2
exit 1
fi
# Need a session bus to proxy
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
echo "error: DBUS_SESSION_BUS_ADDRESS is not set." >&2
exit 1
fi
# Create a temporary directory for the proxy socket
PROXY_DIR="$(mktemp -d /tmp/mcdbus-proxy.XXXXXX)"
PROXY_SOCKET="${PROXY_DIR}/bus"
cleanup() {
if [ -n "${PROXY_PID:-}" ]; then
kill "$PROXY_PID" 2>/dev/null || true
wait "$PROXY_PID" 2>/dev/null || true
fi
rm -rf "$PROXY_DIR"
}
trap cleanup EXIT INT TERM
# Start the proxy.
#
# --talk= Full bidirectional access (method calls, property writes, signals).
# --see= Read-only visibility (appears in ListNames, introspectable, but
# method calls are blocked).
#
# The bus daemon itself is always accessible through the proxy.
#
# Adjust these to match your deployment needs. The set below covers
# the services that mcdbus's built-in shortcut tools use.
xdg-dbus-proxy "$DBUS_SESSION_BUS_ADDRESS" "$PROXY_SOCKET" \
--filter \
--talk=org.freedesktop.Notifications \
--talk=org.mpris.MediaPlayer2 \
--see=org.freedesktop.UPower \
--see=org.freedesktop.NetworkManager \
--see=org.bluez \
--see=org.freedesktop.systemd1 \
--talk=org.kde.KWin \
&
PROXY_PID=$!
# Wait for the proxy socket to appear (up to 5 seconds)
for i in $(seq 1 50); do
if [ -e "$PROXY_SOCKET" ]; then
break
fi
sleep 0.1
done
if [ ! -e "$PROXY_SOCKET" ]; then
echo "error: proxy socket did not appear at $PROXY_SOCKET" >&2
exit 1
fi
# Point mcdbus at the proxy socket and exec
export DBUS_SESSION_BUS_ADDRESS="unix:path=${PROXY_SOCKET}"
exec $MCDBUS_CMD