Vestibule/scripts/deprovision-kiosk.sh

238 lines
8.4 KiB
Bash
Executable File

#!/bin/sh
# deprovision-kiosk.sh — remove the Vestibule kiosk session from this
# machine (Linux). The inverse of provision-kiosk.sh, applied in reverse
# order:
#
# 1. The vestibule-kiosk systemd unit (stop, disable, delete)
# 2. /usr/local/bin/vestibule-kiosk-launch and /etc/vestibule
# 3. Vestibule's merged policies.json everywhere it was deployed —
# LibreWolf native/Flatpak, Firefox native (/etc/firefox), and the
# kiosk-home locations for Firefox Flatpak/snap. Each directory is
# reset to its pre-Vestibule baseline: the backed-up operator file
# is reinstalled where one exists, Vestibule's generated file is
# deleted where one does not.
# 4. The usher Native Messaging manifests from the kiosk user's home
# (all five locations: LibreWolf + Firefox, native + Flatpak + snap)
# 5. The sandbox-visible XPI copies (Flatpak/snap flavors)
# 6. Optionally: the kiosk account, /opt/vestibule, /usr/local/bin/usher
#
# The regular getty/console login is never modified, so removing the
# unit is all it takes to return the machine to a stock boot.
#
# Exit codes:
# 0 success
# 2 not root / no systemd
# 5 removal failure
#
# Usage:
# sudo ./deprovision-kiosk.sh # keep account + /opt
# sudo ./deprovision-kiosk.sh --remove-user --remove-opt --remove-usher
#
# POSIX sh — no bashisms.
set -eu
KIOSK_USER="vestibule-kiosk"
LW_FLATPAK_APP="io.gitlab.librewolf-community"
FF_FLATPAK_APP="org.mozilla.firefox"
OPT_ROOT="/opt/vestibule"
UNIT_DST="/etc/systemd/system/vestibule-kiosk.service"
LAUNCH_DST="/usr/local/bin/vestibule-kiosk-launch"
ENV_DIR="/etc/vestibule"
USHER_DST="/usr/local/bin/usher"
REMOVE_USER=0
REMOVE_OPT=0
REMOVE_USHER=0
ASSUME_YES=0
CHECK=0
usage() {
cat <<'EOF'
deprovision-kiosk.sh — remove the Vestibule kiosk session from this machine
Options:
--kiosk-user NAME Kiosk account name (default: vestibule-kiosk)
--remove-user Also delete the kiosk account and its home directory
--remove-opt Also delete /opt/vestibule (staged files, XPI, docs)
--remove-usher Also delete /usr/local/bin/usher
--yes Skip the confirmation prompt
--check Show what would be removed; change nothing
-h, --help This text
EOF
}
die() {
code="$1"; msg="$2"
echo ""
echo "ERROR: ${msg}" >&2
echo " exiting with code ${code}" >&2
exit "${code}"
}
info() { echo "$1"; }
ok() { echo " [ok] $1"; }
step() { echo ""; echo "==> $1"; }
while [ $# -gt 0 ]; do
case "$1" in
--kiosk-user) KIOSK_USER="$2"; shift 2 ;;
--remove-user) REMOVE_USER=1; shift ;;
--remove-opt) REMOVE_OPT=1; shift ;;
--remove-usher) REMOVE_USHER=1; shift ;;
--yes|-y) ASSUME_YES=1; shift ;;
--check) CHECK=1; shift ;;
-h|--help) usage; exit 0 ;;
*) usage >&2; die 5 "unknown option: $1" ;;
esac
done
if [ ! -d /run/systemd/system ]; then
die 2 "systemd is not the running init system"
fi
# ─── Discover current state ───────────────────────────────────────────
UNIT_ACTIVE=0
if systemctl is-active vestibule-kiosk.service >/dev/null 2>&1; then
UNIT_ACTIVE=1
fi
UNIT_ENABLED=0
if systemctl is-enabled vestibule-kiosk.service >/dev/null 2>&1; then
UNIT_ENABLED=1
fi
KIOSK_HOME=""
if id -u "${KIOSK_USER}" >/dev/null 2>&1; then
KIOSK_HOME=$(getent passwd "${KIOSK_USER}" | cut -d: -f6)
fi
step "Current state"
info "unit : $(if [ -f "${UNIT_DST}" ]; then echo present; else echo absent; fi) (active: ${UNIT_ACTIVE}, enabled: ${UNIT_ENABLED})"
info "launcher : $(if [ -x "${LAUNCH_DST}" ]; then echo present; else echo absent; fi)"
info "kiosk.env : $(if [ -f "${ENV_DIR}/kiosk.env" ]; then echo present; else echo absent; fi)"
info "kiosk account : $(if [ -n "${KIOSK_HOME}" ]; then echo "present (home: ${KIOSK_HOME})"; else echo absent; fi)"
info "opt root : $(if [ -d "${OPT_ROOT}" ]; then echo present; else echo absent; fi)"
if [ "${CHECK}" -eq 1 ]; then
info "(check only — no changes made)"
exit 0
fi
[ "$(id -u)" -eq 0 ] || die 2 "must run as root (sudo)"
if [ "${ASSUME_YES}" -eq 0 ]; then
echo ""
printf "Proceed with removal? [y/N] "
read -r answer
case "${answer}" in
y|Y|yes|YES) ;;
*) info "aborted"; exit 0 ;;
esac
fi
# ─── 1. systemd unit ──────────────────────────────────────────────────
step "Remove kiosk session"
if [ -f "${UNIT_DST}" ]; then
systemctl stop vestibule-kiosk.service 2>/dev/null || true
systemctl disable vestibule-kiosk.service 2>/dev/null || true
rm -f "${UNIT_DST}"
systemctl daemon-reload
ok "unit stopped, disabled, and removed"
else
info "unit already absent"
fi
# ─── 2. Launcher + env ────────────────────────────────────────────────
step "Remove launcher + session config"
if [ -x "${LAUNCH_DST}" ]; then
rm -f "${LAUNCH_DST}"
ok "removed ${LAUNCH_DST}"
fi
if [ -d "${ENV_DIR}" ]; then
rm -rf "${ENV_DIR}"
ok "removed ${ENV_DIR}"
fi
# ─── 3. Policies ──────────────────────────────────────────────────────
step "Reset browser policies to baseline"
reset_policy_dir() {
# Step-down, one decision per line:
# absent directory -> nothing to do
# baseline backup present -> reinstall it over Vestibule's merge
# Vestibule-generated file -> delete it (no pre-Vestibule baseline)
_dir="$1"
if [ ! -d "${_dir}" ]; then
return
fi
_dst="${_dir}/policies.json"
_bak="${_dst}.vestibule-bak"
if [ -f "${_bak}" ]; then
mv "${_bak}" "${_dst}"
ok "baseline policies.json reinstalled in ${_dir}"
elif [ -f "${_dst}" ] && grep -q "vestibule@vestibule\.kiosk" "${_dst}" 2>/dev/null; then
rm -f "${_dst}"
ok "Vestibule-generated policies.json deleted in ${_dir} (no baseline on record)"
fi
}
reset_policy_dir /usr/lib/librewolf/distribution
reset_policy_dir /usr/share/librewolf/distribution
reset_policy_dir /opt/librewolf/distribution
reset_policy_dir "/var/lib/flatpak/app/${LW_FLATPAK_APP}/current/active/files/librewolf/distribution"
reset_policy_dir /etc/firefox/policies
if [ -n "${KIOSK_HOME}" ]; then
reset_policy_dir "${KIOSK_HOME}/.var/app/${FF_FLATPAK_APP}/.mozilla/policies"
reset_policy_dir "${KIOSK_HOME}/snap/firefox/common/.mozilla/policies"
fi
# ─── 4. Native Messaging manifests ────────────────────────────────────
step "Remove Native Messaging manifests"
if [ -n "${KIOSK_HOME}" ]; then
rm -f "${KIOSK_HOME}/.librewolf/native-messaging-hosts/com.vestibule.usher.json"
rm -f "${KIOSK_HOME}/.mozilla/native-messaging-hosts/com.vestibule.usher.json"
rm -f "${KIOSK_HOME}/.var/app/${LW_FLATPAK_APP}/.librewolf/native-messaging-hosts/com.vestibule.usher.json"
rm -f "${KIOSK_HOME}/.var/app/${FF_FLATPAK_APP}/.mozilla/native-messaging-hosts/com.vestibule.usher.json"
rm -f "${KIOSK_HOME}/snap/firefox/common/.mozilla/native-messaging-hosts/com.vestibule.usher.json"
# XPI copies staged for sandbox-visible installs (flatpak/snap).
rm -f "${KIOSK_HOME}/.var/app/${LW_FLATPAK_APP}/vestibule.xpi"
rm -f "${KIOSK_HOME}/.var/app/${FF_FLATPAK_APP}/vestibule.xpi"
rm -f "${KIOSK_HOME}/snap/firefox/common/vestibule.xpi"
ok "manifests + sandbox XPI copies removed from ${KIOSK_HOME}"
else
info "kiosk account already absent — nothing to clean"
fi
# ─── 5. Optional removals ─────────────────────────────────────────────
if [ "${REMOVE_USHER}" -eq 1 ]; then
step "Remove usher binary"
if [ -f "${USHER_DST}" ]; then
rm -f "${USHER_DST}"
ok "removed ${USHER_DST}"
fi
fi
if [ "${REMOVE_OPT}" -eq 1 ]; then
step "Remove ${OPT_ROOT}"
if [ -d "${OPT_ROOT}" ]; then
rm -rf "${OPT_ROOT}"
ok "removed ${OPT_ROOT}"
fi
fi
if [ "${REMOVE_USER}" -eq 1 ]; then
step "Remove kiosk account"
if [ -n "${KIOSK_HOME}" ]; then
userdel -r "${KIOSK_USER}" || die 5 "userdel failed"
ok "removed account '${KIOSK_USER}' and its home"
else
info "account already absent"
fi
fi
step "Deprovisioning complete"
info "next boot returns to the normal login prompt"
exit 0