197 lines
9 KiB
Bash
Executable file
197 lines
9 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ACTION=install
|
|
case "${1:-}" in
|
|
uninstall|--uninstall|remove|--remove) ACTION=uninstall; shift ;;
|
|
purge|--purge) ACTION=purge; shift ;;
|
|
install|--install) ACTION=install; shift ;;
|
|
esac
|
|
|
|
TARGET_USER="${1:-}"
|
|
if [[ -z "$TARGET_USER" ]]; then
|
|
if [[ -n "${SUDO_USER:-}" && "$SUDO_USER" != "root" ]]; then TARGET_USER="$SUDO_USER"; else TARGET_USER="$(logname 2>/dev/null || true)"; fi
|
|
fi
|
|
if [[ -z "$TARGET_USER" || ! "$TARGET_USER" =~ ^[A-Za-z_][A-Za-z0-9_-]*[$]?$ ]] || ! id "$TARGET_USER" >/dev/null 2>&1; then
|
|
echo "Specify the desktop user: sudo bash scripts/install-webui-helpers.sh \"$USER\"" >&2
|
|
exit 2
|
|
fi
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
uninstall_webui_helpers() {
|
|
local user="$1" home="" user_unit=""
|
|
echo "Uninstalling BastionGuard WebUI helpers for user: $user"
|
|
|
|
systemctl disable --now bastionguard-webui-inotify.service 2>/dev/null || true
|
|
rm -f /etc/systemd/system/bastionguard-webui-inotify.service
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
systemctl reset-failed bastionguard-webui-inotify.service 2>/dev/null || true
|
|
|
|
home="$(getent passwd "$user" | cut -d: -f6)"
|
|
if [[ -n "$home" && -d "$home" ]]; then
|
|
user_unit="$home/.config/systemd/user/bastionguard-webui-inotify.service"
|
|
runuser -u "$user" -- systemctl --user disable --now bastionguard-webui-inotify.service 2>/dev/null || true
|
|
rm -f "$user_unit" "$user_unit.disabled-by-root-service" 2>/dev/null || true
|
|
fi
|
|
|
|
rm -f /usr/local/sbin/bastionguard-webui-systemctl
|
|
rm -f /usr/local/sbin/bastionguard-webui-admin
|
|
rm -f /usr/local/sbin/bastionguard-webui-wizard
|
|
rm -f /usr/local/libexec/bastionguard-webui-inotify-runner
|
|
rm -f /etc/sudoers.d/bastionguard-webui
|
|
|
|
rm -f "/run/bastionguard-webui-inotify-$user.sh" "/run/bastionguard-webui-inotify-$user.paths" "/run/bastionguard-webui-inotify-$user.pid" 2>/dev/null || true
|
|
rm -rf /run/bastionguard-webui 2>/dev/null || true
|
|
|
|
if [[ "$ACTION" == "purge" ]]; then
|
|
rm -rf /var/lib/bastionguard-webui
|
|
echo "Persistent data removed: /var/lib/bastionguard-webui"
|
|
else
|
|
echo "Persistent data kept: /var/lib/bastionguard-webui"
|
|
fi
|
|
echo "BastionGuard WebUI helpers uninstalled."
|
|
}
|
|
|
|
if [[ "$ACTION" == "uninstall" || "$ACTION" == "purge" ]]; then
|
|
uninstall_webui_helpers "$TARGET_USER"
|
|
exit 0
|
|
fi
|
|
|
|
# Font policy: the WebUI template uses a vendored Cantarell asset only.
|
|
# Expected path: webui/assets/fonts/Cantarell-VF.otf
|
|
if [[ ! -f "$SCRIPT_DIR/../assets/fonts/Cantarell-VF.otf" ]]; then
|
|
if [[ -x "$SCRIPT_DIR/vendor-cantarell-font.sh" ]]; then
|
|
bash "$SCRIPT_DIR/vendor-cantarell-font.sh" || echo "Warning: vendored Cantarell font missing: webui/assets/fonts/Cantarell-VF.otf" >&2
|
|
else
|
|
echo "Warning: vendored Cantarell font missing: webui/assets/fonts/Cantarell-VF.otf" >&2
|
|
fi
|
|
fi
|
|
install -o root -g root -m 0755 "$SCRIPT_DIR/bastionguard-webui-systemctl" /usr/local/sbin/bastionguard-webui-systemctl
|
|
install -o root -g root -m 0755 "$SCRIPT_DIR/bastionguard-webui-admin" /usr/local/sbin/bastionguard-webui-admin
|
|
install -o root -g root -m 0755 "$SCRIPT_DIR/bastionguard-webui-wizard" /usr/local/sbin/bastionguard-webui-wizard
|
|
install -d -o root -g root -m 0755 /usr/local/libexec
|
|
install -o root -g root -m 0755 "$SCRIPT_DIR/bastionguard-webui-inotify-runner" /usr/local/libexec/bastionguard-webui-inotify-runner
|
|
|
|
WEB_USERS=()
|
|
for u in www-data http apache nginx caddy; do
|
|
if id "$u" >/dev/null 2>&1; then WEB_USERS+=("$u"); fi
|
|
done
|
|
if [[ ${#WEB_USERS[@]} -eq 0 ]]; then
|
|
echo "No known web-server user found. Add sudoers manually for your PHP-FPM user." >&2
|
|
exit 3
|
|
fi
|
|
|
|
# Data dir persistente usata dalla WebUI per opzioni, cache e stato locale.
|
|
DATA_DIR=/var/lib/bastionguard-webui
|
|
mkdir -p "$DATA_DIR"
|
|
chown "${WEB_USERS[0]}:${WEB_USERS[0]}" "$DATA_DIR" 2>/dev/null || chown "${WEB_USERS[0]}" "$DATA_DIR" 2>/dev/null || true
|
|
chmod 0750 "$DATA_DIR" || true
|
|
|
|
# WebUI language/theme are session-only. Remove older persisted values if present.
|
|
if command -v python3 >/dev/null 2>&1 && [[ -f "$DATA_DIR/web_options.json" ]]; then
|
|
python3 - "$DATA_DIR/web_options.json" <<'PYWEBOPTS' || true
|
|
import json, os, sys
|
|
path = sys.argv[1]
|
|
try:
|
|
with open(path, 'r', encoding='utf-8') as fh:
|
|
data = json.load(fh)
|
|
if isinstance(data, dict):
|
|
changed = False
|
|
for key in ('language', 'theme'):
|
|
if key in data:
|
|
data.pop(key, None)
|
|
changed = True
|
|
if changed:
|
|
tmp = path + '.tmp'
|
|
with open(tmp, 'w', encoding='utf-8') as fh:
|
|
json.dump(data, fh, ensure_ascii=False, indent=2)
|
|
fh.write('\n')
|
|
os.replace(tmp, path)
|
|
except Exception:
|
|
pass
|
|
PYWEBOPTS
|
|
fi
|
|
|
|
# Persistent root/system service for the realtime WebPanel monitor.
|
|
# This replaces the old --user unit so the monitor can inspect root-owned paths
|
|
# allowed by the WebUI policy (/var/www, /srv, /tmp, /home, mounted media, ...).
|
|
TARGET_HOME="$(getent passwd "$TARGET_USER" | cut -d: -f6)"
|
|
SYSTEM_UNIT=/etc/systemd/system/bastionguard-webui-inotify.service
|
|
cat > "$SYSTEM_UNIT" <<EOFUNIT
|
|
[Unit]
|
|
Description=BastionGuard WebPanel realtime malware and ransomware monitor (root)
|
|
Documentation=file:///srv/http/webui/README.md
|
|
After=network.target clamav-daemon.service
|
|
Wants=clamav-daemon.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=/usr/local/sbin/bastionguard-webui-admin inotify-start-saved $TARGET_USER
|
|
ExecStartPost=/usr/local/sbin/bastionguard-webui-admin ransomware-realtime-start $TARGET_USER
|
|
ExecStop=/usr/local/sbin/bastionguard-webui-admin inotify-stop $TARGET_USER
|
|
TimeoutStartSec=60
|
|
TimeoutStopSec=30
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOFUNIT
|
|
chmod 0644 "$SYSTEM_UNIT"
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
|
|
# Disable the legacy per-user unit if an older WebUI package installed it.
|
|
if [[ -n "${TARGET_HOME:-}" && -d "$TARGET_HOME" ]]; then
|
|
USER_UNIT="$TARGET_HOME/.config/systemd/user/bastionguard-webui-inotify.service"
|
|
if [[ -f "$USER_UNIT" ]]; then
|
|
runuser -u "$TARGET_USER" -- systemctl --user disable --now bastionguard-webui-inotify.service 2>/dev/null || true
|
|
mv -f "$USER_UNIT" "$USER_UNIT.disabled-by-root-service" 2>/dev/null || true
|
|
fi
|
|
fi
|
|
|
|
# Remove legacy dynamic runtime scripts generated by older WebUI builds.
|
|
# The realtime worker is now a static root-owned helper under /usr/local/libexec.
|
|
rm -f "/run/bastionguard-webui-inotify-$TARGET_USER.sh" "/run/bastionguard-webui-inotify-$TARGET_USER.paths" 2>/dev/null || true
|
|
install -d -o root -g root -m 0755 /run/bastionguard-webui 2>/dev/null || true
|
|
|
|
SUDOERS="/etc/sudoers.d/bastionguard-webui"
|
|
TMP="$(mktemp)"
|
|
{
|
|
echo "# BastionGuard WebUI: controlled helpers for $TARGET_USER"
|
|
echo "Cmnd_Alias BASTIONGUARD_WEBUI_SYSTEMCTL = /usr/local/sbin/bastionguard-webui-systemctl user $TARGET_USER *"
|
|
echo "Cmnd_Alias BASTIONGUARD_WEBUI_ADMIN = /usr/local/sbin/bastionguard-webui-admin *"
|
|
echo "Cmnd_Alias BASTIONGUARD_WEBUI_INOTIFY = /usr/local/sbin/bastionguard-webui-admin inotify-start-saved $TARGET_USER, /usr/local/sbin/bastionguard-webui-admin inotify-stop $TARGET_USER, /usr/local/sbin/bastionguard-webui-admin inotify-status $TARGET_USER, /usr/local/sbin/bastionguard-webui-admin inotify-service-stop $TARGET_USER, /usr/local/sbin/bastionguard-webui-admin inotify-service-status $TARGET_USER, /usr/local/sbin/bastionguard-webui-admin ransomware-realtime-start $TARGET_USER"
|
|
echo "Cmnd_Alias BASTIONGUARD_WEBUI_WIZARD = /usr/local/sbin/bastionguard-webui-wizard *"
|
|
for u in "${WEB_USERS[@]}"; do
|
|
echo "$u ALL=(root) NOPASSWD: BASTIONGUARD_WEBUI_SYSTEMCTL, BASTIONGUARD_WEBUI_ADMIN, BASTIONGUARD_WEBUI_WIZARD"
|
|
done
|
|
echo "$TARGET_USER ALL=(root) NOPASSWD: BASTIONGUARD_WEBUI_INOTIFY"
|
|
} > "$TMP"
|
|
chmod 0440 "$TMP"
|
|
if command -v visudo >/dev/null 2>&1; then visudo -cf "$TMP" >/dev/null; fi
|
|
install -o root -g root -m 0440 "$TMP" "$SUDOERS"
|
|
rm -f "$TMP"
|
|
|
|
cat <<EOF
|
|
BastionGuard WebUI helpers installed.
|
|
Desktop user: $TARGET_USER
|
|
Authorized web users: ${WEB_USERS[*]}
|
|
|
|
Files:
|
|
/usr/local/sbin/bastionguard-webui-systemctl
|
|
/usr/local/sbin/bastionguard-webui-admin
|
|
/usr/local/sbin/bastionguard-webui-wizard
|
|
/usr/local/libexec/bastionguard-webui-inotify-runner
|
|
$SUDOERS
|
|
|
|
Optional runtime tools for realtime/Samba features: inotifywait from inotify-tools, smbclient from Samba. Ransomware realtime uses BastionGuard-ransomware-realtime.service when installed.
|
|
Persistent realtime service: sudo systemctl enable --now bastionguard-webui-inotify.service
|
|
|
|
Test:
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-admin ensure-configs $TARGET_USER
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-admin scan-path-b64 $(printf /tmp | base64 -w0)
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-admin inotify-status $TARGET_USER
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-admin samba-scan-b64 $(printf /tmp | base64 -w0) $TARGET_USER
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-admin journal system - 20 clamav-freshclam.service
|
|
sudo -u ${WEB_USERS[0]} sudo -n /usr/local/sbin/bastionguard-webui-wizard update-banks $TARGET_USER
|
|
EOF
|