BastionGuard/tests/test_systemd_policy.sh

58 lines
2.7 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
MANAGER="$ROOT/data/init/common/bastionguard-service"
# No root privileges and no live systemd required: invalid units must be
# rejected before the backend invokes systemctl/rc-service.
for unit in ssh.service NetworkManager.service systemd-logind.service BastionGuard-evil.service \
"nginx.service;touch /tmp/bastionguard-bad"; do
set +e
msg="$(sh "$MANAGER" --system restart "$unit" 2>&1)"
rc=$?
set -e
[[ $rc -eq 64 ]] || { echo "Unexpected system unit rejection status $rc for $unit" >&2; exit 1; }
done
# A valid unit must pass the permission check, even when service management
# cannot be executed in the container (non-systemd rootfs).
set +e
sh "$MANAGER" --system reload dnsmasq.service >/dev/null 2>&1
rc=$?
set -e
[[ $rc -ne 64 ]] || { echo 'dnsmasq rejected unexpectedly' >&2; exit 1; }
# Guard user-mode command rejects invalid CLI options.
set +e
sh "$MANAGER" --user restart --bad-option >/dev/null 2>&1
rc=$?
set -e
[[ $rc -ne 0 ]] || { echo 'user unit accepted invalid options' >&2; exit 1; }
# Mock an ordinary desktop session: its restart must only address user units.
FAKE_DIR="$(mktemp -d /tmp/bastionguard-systemctl-test-XXXXXX)"
trap 'rm -rf "$FAKE_DIR"' EXIT
cat > "$FAKE_DIR/systemctl" <<'SH'
#!/bin/sh
printf '%s\n' "$*" >> "$BG_SYSTEMCTL_LOG"
exit 0
SH
chmod +x "$FAKE_DIR/systemctl"
BG_SYSTEMCTL_LOG="$FAKE_DIR/calls" PATH="$FAKE_DIR:$PATH" \
bash "$ROOT/data/scripts/BastionGuard-restart-user-services.sh" --user resume
[[ -s "$FAKE_DIR/calls" ]] || { echo 'user-mode restart produced no calls' >&2; exit 1; }
if grep -Ev '^--user ' "$FAKE_DIR/calls" >/dev/null; then
echo 'user-mode restart invoked a system-level systemctl command' >&2; exit 1
fi
if grep -Eq 'phishing-scanner|usbd|ransomware-realtime\.service|user-session-watch' "$FAKE_DIR/calls"; then
echo 'user-mode restart touched a system or self-watcher unit' >&2; exit 1
fi
if grep -RE '(^|[^A-Za-z0-9_])popen[[:space:]]*\(' "$ROOT/src" --include='*.cpp' --include='*.hpp'; then
echo 'unsafe popen call remains in C++ source' >&2; exit 1
fi
# Sanity-check unit files without treating missing installed binaries as a
# packaging syntax error.
if command -v systemd-analyze >/dev/null 2>&1; then
output="$(systemd-analyze verify "$ROOT/data/service/BastionGuard-ransomware-scanner.service" \
"$ROOT/data/service/BastionGuard-phishing-scanner.service" 2>&1 || true)"
if grep -Eqi 'has a bad unit file setting|Unknown lvalue|Missing .* section|Unbalanced quoting' <<<"$output"; then
echo "$output" >&2; exit 1
fi
fi
echo 'service manager systemd allowlist and unit syntax: OK'