mirror of
https://gitlab.com/hacklab01/pivilion.git
synced 2026-08-06 16:08:22 +00:00
Harden installation and runtime diagnostics
This commit is contained in:
parent
34b4c4b036
commit
ed0b168ab6
14 changed files with 748 additions and 213 deletions
67
tests/run.sh
Executable file
67
tests/run.sh
Executable file
|
|
@ -0,0 +1,67 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
failures=0
|
||||
|
||||
run() {
|
||||
local label=$1
|
||||
shift
|
||||
if "$@"; then printf '[pass] %s\n' "$label"; else printf '[fail] %s\n' "$label" >&2; failures=$((failures + 1)); fi
|
||||
}
|
||||
|
||||
shell_syntax() {
|
||||
bash -n "$ROOT/install.sh" "$ROOT"/usr/local/lib/pivilion/*.sh "$ROOT"/usr/local/bin/* "$ROOT/etc/profile.d/pivilion-motd.sh"
|
||||
}
|
||||
|
||||
php_syntax() {
|
||||
command -v php >/dev/null 2>&1 || return 0
|
||||
while IFS= read -r file; do php -l "$file" >/dev/null || return 1; done < <(find "$ROOT/var" "$ROOT/home" -name '*.php' -type f)
|
||||
}
|
||||
|
||||
systemd_syntax() {
|
||||
local output
|
||||
command -v systemd-analyze >/dev/null 2>&1 || return 0
|
||||
output=$(systemd-analyze verify "$ROOT"/etc/systemd/system/*.service 2>&1) || true
|
||||
output=$(printf '%s\n' "$output" | grep -Ev 'SO_PASS(RIGHTS|CRED)|handoff timestamp|user lookup socket' || true)
|
||||
[ -z "$output" ]
|
||||
}
|
||||
|
||||
captive_rules() {
|
||||
grep -q 'R=302' "$ROOT/home/pi/pivilion/config/html/.htaccess" &&
|
||||
! grep -q 'R=301' "$ROOT/home/pi/pivilion/config/html/.htaccess" &&
|
||||
! grep -Eq 'dport[[:space:]]+443|redirect to :443' "$ROOT/usr/local/lib/pivilion/mode.sh"
|
||||
}
|
||||
|
||||
installer_safety() {
|
||||
grep -q -- '--dry-run' "$ROOT/install.sh" &&
|
||||
grep -q -- '--repair' "$ROOT/install.sh" &&
|
||||
grep -q 'backup_managed_files' "$ROOT/install.sh" &&
|
||||
grep -q 'rollback()' "$ROOT/install.sh" &&
|
||||
! grep -Eq 'disable( --now)? dnsmasq' "$ROOT/install.sh" &&
|
||||
! grep -q 'rm -f.*CAPTIVE\|rm -f.*\.htaccess' "$ROOT/usr/local/bin/onion"
|
||||
}
|
||||
|
||||
state_contract() {
|
||||
grep -q "printf 'desired_mode" "$ROOT/usr/local/lib/pivilion/common.sh" &&
|
||||
grep -q "printf 'active_mode" "$ROOT/usr/local/lib/pivilion/common.sh" &&
|
||||
grep -q "printf 'health" "$ROOT/usr/local/lib/pivilion/common.sh" &&
|
||||
grep -q 'degraded' "$ROOT/usr/local/lib/pivilion/mode.sh"
|
||||
}
|
||||
|
||||
shellcheck_scripts() {
|
||||
command -v shellcheck >/dev/null 2>&1 || return 0
|
||||
shellcheck "$ROOT/install.sh" "$ROOT"/usr/local/lib/pivilion/*.sh "$ROOT"/usr/local/bin/pivilion* "$ROOT/usr/local/bin/hotspot" "$ROOT/usr/local/bin/onion" "$ROOT/usr/local/bin/pikey"
|
||||
}
|
||||
|
||||
run "configuration and state fixtures" "$ROOT/tests/test-common.sh"
|
||||
run "shell syntax" shell_syntax
|
||||
run "PHP syntax" php_syntax
|
||||
run "systemd unit syntax" systemd_syntax
|
||||
run "temporary HTTP-only captive rules" captive_rules
|
||||
run "transactional installer safety contract" installer_safety
|
||||
run "truthful runtime state contract" state_contract
|
||||
run "ShellCheck (when installed)" shellcheck_scripts
|
||||
|
||||
[ "$failures" -eq 0 ] || { echo "$failures test group(s) failed." >&2; exit 1; }
|
||||
echo "All available tests passed."
|
||||
62
tests/test-common.sh
Executable file
62
tests/test-common.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
TMP=$(mktemp -d)
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
USER_NAME=$(id -un)
|
||||
|
||||
cat > "$TMP/primary.conf" <<EOF
|
||||
PIVILION_USER=$USER_NAME
|
||||
PIVILION_MODE=hotspot
|
||||
EOF
|
||||
cat > "$TMP/fallback.conf" <<EOF
|
||||
PIVILION_USER=$USER_NAME
|
||||
PIVILION_HOME=$HOME
|
||||
PIVILION_DIR=$TMP/pivilion
|
||||
PIVILION_WEBROOT=/var/www/html/pivilion
|
||||
PIVILION_MODE=onion
|
||||
PIVILION_HOTSPOT_SSID=fixture-portal
|
||||
EOF
|
||||
|
||||
export PIVILION_CONFIG_PATHS="$TMP/primary.conf $TMP/fallback.conf"
|
||||
export PIVILION_STATE_DIR="$TMP/run"
|
||||
export PIVILION_STATE_FILE="$TMP/run/status.tsv"
|
||||
source "$ROOT/usr/local/lib/pivilion/common.sh"
|
||||
pivilion_load_config
|
||||
|
||||
[ "$PIVILION_MODE" = hotspot ]
|
||||
[ "$PIVILION_HOTSPOT_SSID" = fixture-portal ]
|
||||
[ "$PIVILION_DIR" = "$TMP/pivilion" ]
|
||||
|
||||
install -d "$PIVILION_DIR" "$PIVILION_STATE_DIR"
|
||||
printf 'onion\n' > "$PIVILION_DIR/mode"
|
||||
[ "$(pivilion_current_mode)" = onion ]
|
||||
cat > "$PIVILION_STATE_FILE" <<EOF
|
||||
desired_mode onion
|
||||
active_mode hotspot
|
||||
backend networkmanager
|
||||
health degraded
|
||||
failure probe failed
|
||||
EOF
|
||||
[ "$(pivilion_state_value active_mode)" = hotspot ]
|
||||
[ "$(pivilion_state_value health)" = degraded ]
|
||||
[ "$(pivilion_state_value missing fallback)" = fallback ]
|
||||
|
||||
mkdir "$TMP/bin"
|
||||
cat > "$TMP/bin/nmcli" <<'EOF'
|
||||
#!/bin/sh
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$TMP/bin/systemctl" <<'EOF'
|
||||
#!/bin/sh
|
||||
[ "${MOCK_NM_ACTIVE:-0}" = 1 ]
|
||||
EOF
|
||||
chmod +x "$TMP/bin/nmcli" "$TMP/bin/systemctl"
|
||||
PATH="$TMP/bin:$PATH" MOCK_NM_ACTIVE=1 pivilion_uses_networkmanager
|
||||
if PATH="$TMP/bin:$PATH" MOCK_NM_ACTIVE=0 pivilion_uses_networkmanager; then exit 1; fi
|
||||
|
||||
sed 's/PIVILION_MODE=hotspot/PIVILION_MODE=invalid/' "$TMP/primary.conf" > "$TMP/invalid.conf"
|
||||
PIVILION_CONFIG_PATHS="$TMP/invalid.conf $TMP/fallback.conf"
|
||||
export PIVILION_CONFIG_PATHS
|
||||
if pivilion_load_config >/dev/null 2>&1; then exit 1; fi
|
||||
Loading…
Add table
Add a link
Reference in a new issue