BastionGuard/data/scripts/BastionGuard-restart-user-services.sh
specialworld83 f0f913a209 Release 2.0
2026-07-15 10:52:22 +02:00

195 lines
7.4 KiB
Bash
Executable file

#!/usr/bin/env bash
# ============================================================================
# BastionGuard - Riavvio dei servizi --user per TUTTI gli utenti
# ----------------------------------------------------------------------------
# Pensato per essere chiamato dal pacchetto Debian (postinst, triggers,
# o un dpkg trigger su /usr/lib/systemd/user/) dopo un upgrade dei binari
# o delle unit user-level di BastionGuard.
#
# Lo script gira SEMPRE come root e:
# 1. Fa "systemctl --global daemon-reload" così le unit installate in
# /usr/lib/systemd/user/ vengono ripescate dai futuri manager utente.
# 2. Trova TUTTI gli utenti con un user-manager systemd attivo:
# - sessioni attive (loginctl list-users)
# - utenti lingering (loginctl show-user --property=Linger)
# - utenti con /run/user/<uid> esistente
# 3. Per ognuno fa:
# - daemon-reload sul SUO bus (--global non aggiorna i manager già vivi)
# - try-restart di tutte le unit BastionGuard-*.service realmente
# installate per quell'utente
# 4. Salta utenti di sistema (UID < 1000) e utenti senza /run/user/<uid>.
#
# Exit code: sempre 0 (non blocca dpkg --configure).
#
# Posizione: /usr/share/BastionGuard/data/scripts/
# Esempio di chiamata da debian/postinst:
#
# if [ "$1" = "configure" ] || [ "$1" = "triggered" ]; then
# /usr/share/BastionGuard/data/scripts/BastionGuard-restart-user-services.sh || true
# fi
# ============================================================================
set -u
# ----------------------------------------------------------------------------
# Lista delle unit --user di BastionGuard.
# Tieni allineato con i .service spediti in /usr/lib/systemd/user/.
# ----------------------------------------------------------------------------
ALL_SERVICES=(
"BastionGuard-cef.service"
"BastionGuard-mailproxy.service"
"BastionGuard-pacd.service"
"BastionGuard-phishing-scanner.service"
"BastionGuard-phishing-updater.service"
"BastionGuard-privacyd.service"
"BastionGuard-ransomware-alert.service"
"BastionGuard-ransomware-realtime-alert.service"
"BastionGuard-ransomware-realtime.service"
"BastionGuard-ransomware-scanner.service"
"BastionGuard-usbd.service"
"BastionGuard-useragent.service"
)
# ----------------------------------------------------------------------------
# Logging (stderr, prefissato, no colori per non sporcare apt)
# ----------------------------------------------------------------------------
log() { printf '[BastionGuard] %s\n' "$*" >&2; }
warn() { printf '[BastionGuard] WARN: %s\n' "$*" >&2; }
err() { printf '[BastionGuard] ERR : %s\n' "$*" >&2; }
# ----------------------------------------------------------------------------
# Prerequisiti
# ----------------------------------------------------------------------------
if ! command -v systemctl >/dev/null 2>&1; then
log "systemctl non presente, salto il riavvio dei servizi user."
exit 0
fi
# In chroot/container /run/systemd/system non esiste: niente da fare.
if [[ ! -d /run/systemd/system ]]; then
log "systemd non in esecuzione (chroot/container?), salto."
exit 0
fi
if [[ "$EUID" -ne 0 ]]; then
err "Questo script va eseguito come root (chiamato dal package manager)."
exit 0
fi
# UID minimo "umano". Standard è 1000 su Debian/Ubuntu/Fedora/openSUSE/Arch,
# ma rispettiamo /etc/login.defs se diverso.
UID_MIN=1000
if [[ -r /etc/login.defs ]]; then
_u="$(awk '/^[[:space:]]*UID_MIN/ {print $2; exit}' /etc/login.defs 2>/dev/null || true)"
[[ "$_u" =~ ^[0-9]+$ ]] && UID_MIN="$_u"
fi
# ----------------------------------------------------------------------------
# Step 1: daemon-reload globale (futuri manager utente).
# ----------------------------------------------------------------------------
log "systemctl daemon-reload"
systemctl daemon-reload >/dev/null 2>&1 || \
warn "daemon-reload fallito (best-effort)"
# ----------------------------------------------------------------------------
# Step 2: enumerazione utenti con user-manager attivo.
# ----------------------------------------------------------------------------
declare -A USERS_SET=()
if command -v loginctl >/dev/null 2>&1; then
# Tutti gli utenti noti a logind
while IFS= read -r _user; do
[[ -z "$_user" ]] && continue
USERS_SET["$_user"]=1
done < <(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}')
fi
# Utenti con /run/user/<uid>: cattura sia logged-in sia lingering.
for d in /run/user/*; do
[[ -d "$d" ]] || continue
uid="$(basename "$d")"
[[ "$uid" =~ ^[0-9]+$ ]] || continue
[[ "$uid" -lt $UID_MIN ]] && continue
user="$(getent passwd "$uid" | cut -d: -f1)"
[[ -n "$user" ]] && USERS_SET["$user"]=1
done
if [[ ${#USERS_SET[@]} -eq 0 ]]; then
log "Nessun utente con sessione/linger attivo: niente da riavviare."
exit 0
fi
# ----------------------------------------------------------------------------
# run_as_user <user> <systemctl args...>
#
# Esegue "systemctl --user <args>" nel contesto del manager utente di <user>.
# Stesso pattern di src/Backend.cpp (runuser ... systemctl --user) e
# src/wizard/wizard_setup.cpp (export XDG_RUNTIME_DIR/DBUS_SESSION_BUS_ADDRESS).
# ----------------------------------------------------------------------------
run_as_user() {
local user="$1"; shift
local uid
uid="$(id -u "$user" 2>/dev/null)" || return 2
[[ "$uid" -lt $UID_MIN ]] && return 3
[[ -d "/run/user/$uid" ]] || return 4
runuser -u "$user" -- env \
XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user "$@"
}
# ----------------------------------------------------------------------------
# Step 3: per ogni utente, daemon-reload + try-restart delle unit installate.
# ----------------------------------------------------------------------------
total_users=0
ok_users=0
for user in "${!USERS_SET[@]}"; do
uid="$(id -u "$user" 2>/dev/null || true)"
if [[ -z "$uid" || "$uid" -lt $UID_MIN ]]; then
continue
fi
if [[ ! -d "/run/user/$uid" ]]; then
warn "Utente '$user' (uid=$uid) senza /run/user/$uid, salto."
continue
fi
total_users=$((total_users + 1))
log "→ Utente '$user' (uid=$uid)"
# daemon-reload del manager utente vivo
run_as_user "$user" daemon-reload >/dev/null 2>&1 || \
warn " daemon-reload utente fallito"
user_fail=0
user_done=0
for svc in "${ALL_SERVICES[@]}"; do
# L'unit è installata per questo utente?
if ! run_as_user "$user" list-unit-files "$svc" >/dev/null 2>&1; then
continue
fi
# try-restart: riavvia solo se è già in esecuzione. Più sicuro in
# postinst: non riaccende servizi che l'utente aveva fermato.
# Cambia in "restart" se vuoi forzare l'avvio.
if run_as_user "$user" try-restart "$svc" >/dev/null 2>&1; then
log " ✔ try-restart $svc"
user_done=$((user_done + 1))
else
warn " ✘ try-restart $svc fallito"
user_fail=$((user_fail + 1))
fi
done
if [[ $user_fail -eq 0 ]]; then
ok_users=$((ok_users + 1))
log " utente '$user': $user_done unit riavviate."
else
log " utente '$user': $user_done OK, $user_fail errori."
fi
done
log "Riepilogo: $ok_users/$total_users utenti gestiti senza errori."
exit 0