diff --git a/apps/api/src/agent-scripts/install.sh b/apps/api/src/agent-scripts/install.sh index 8627164..9324e02 100644 --- a/apps/api/src/agent-scripts/install.sh +++ b/apps/api/src/agent-scripts/install.sh @@ -7,13 +7,103 @@ if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then exit 1 fi -for cmd in curl bash; do - command -v "$cmd" >/dev/null 2>&1 || { echo "missing $cmd" >&2; exit 1; } -done +need_cmd() { command -v "$1" >/dev/null 2>&1; } -if ! command -v jq >/dev/null 2>&1 && ! command -v python3 >/dev/null 2>&1; then - if command -v apt-get >/dev/null 2>&1; then - apt-get update -qq && apt-get install -y -qq jq || true +pkg_install() { + # $@ = package names (distro-specific callers pass the right names) + if need_cmd apt-get; then + export DEBIAN_FRONTEND=noninteractive + apt-get update -qq + apt-get install -y -qq "$@" + elif need_cmd dnf; then + dnf install -y -q "$@" + elif need_cmd yum; then + yum install -y -q "$@" + elif need_cmd apk; then + apk add --no-cache "$@" + else + echo "evofw install: no supported package manager (apt/dnf/yum/apk)" >&2 + return 1 + fi +} + +ensure_pkg() { + # $1 = command to check; remaining = package name(s) to install if missing + local bin=$1 + shift + if need_cmd "$bin"; then + return 0 + fi + echo "evofw install: installing $* (need $bin)..." + pkg_install "$@" || { + echo "evofw install: failed to install $* — install manually and retry" >&2 + return 1 + } + need_cmd "$bin" +} + +# curl is required to fetch this script in the first place, but re-check for pipe/bash edge cases. +ensure_pkg curl curl || exit 1 +need_cmd bash || { echo "missing bash" >&2; exit 1; } + +# JSON parse for enroll; python3 is an acceptable fallback in sync script. +if ! need_cmd jq && ! need_cmd python3; then + ensure_pkg jq jq || ensure_pkg python3 python3 || { + echo "evofw install: need jq or python3" >&2 + exit 1 + } +fi + +# Firewall tools: never reinstall/replace if already present. +if need_cmd nft; then + echo "evofw install: nft already present — skip firewall packages" +elif need_cmd iptables; then + echo "evofw install: iptables already present — skip nftables/iptables install" + if ! need_cmd ipset; then + echo "evofw install: installing ipset (optional companion for iptables)..." + pkg_install ipset 2>/dev/null || true + fi +else + echo "evofw install: no nft/iptables — installing firewall backend..." + if need_cmd apt-get; then + pkg_install nftables || pkg_install iptables || true + elif need_cmd dnf || need_cmd yum; then + pkg_install nftables || pkg_install iptables || true + elif need_cmd apk; then + pkg_install nftables || pkg_install iptables || true + fi + if need_cmd iptables && ! need_cmd nft && ! need_cmd ipset; then + pkg_install ipset 2>/dev/null || true + fi +fi + +HAS_SYSTEMD=0 +if need_cmd systemctl && [[ -d /run/systemd/system ]]; then + HAS_SYSTEMD=1 +fi + +# Cron only when systemd timer is unavailable. +if [[ "$HAS_SYSTEMD" -ne 1 ]]; then + if ! need_cmd crontab; then + echo "evofw install: no systemd — installing cron..." + if need_cmd apt-get; then + pkg_install cron || pkg_install cronie || true + elif need_cmd dnf || need_cmd yum; then + pkg_install cronie || true + elif need_cmd apk; then + pkg_install cronie || pkg_install dcron || true + fi + fi + if ! need_cmd crontab; then + echo "evofw install: crontab missing and could not be installed (need systemd or cron)" >&2 + exit 1 + fi + # Ensure cron daemon is running when we fall back to crontab. + if need_cmd systemctl; then + systemctl enable --now cron 2>/dev/null || \ + systemctl enable --now crond 2>/dev/null || true + elif need_cmd service; then + service cron start 2>/dev/null || service crond start 2>/dev/null || true fi fi @@ -113,7 +203,7 @@ sed -i "s/^KERNEL_BACKEND=.*/KERNEL_BACKEND=${BACKEND}/" "$CONF_FILE" 2>/dev/nul echo "KERNEL_BACKEND=${BACKEND}" >>"$CONF_FILE" INTERVAL="${EVOFW_SYNC_INTERVAL:-1min}" -if command -v systemctl >/dev/null 2>&1; then +if [[ "$HAS_SYSTEMD" -eq 1 ]]; then cat >/etc/systemd/system/evofw-firewall.service <<'UNIT' [Unit] Description=EvoFirewall sync @@ -143,9 +233,9 @@ UNIT # First run now (pending → log "pending approval"; after Approve → empty policy is OK). systemctl start evofw-firewall.service || true else - (crontab -l 2>/dev/null | grep -v evofw-firewall; echo "*/1 * * * * $SYNC_SCRIPT") | crontab - + (crontab -l 2>/dev/null | grep -v evofw-firewall || true; echo "*/1 * * * * $SYNC_SCRIPT") | crontab - "$SYNC_SCRIPT" || true fi echo "Installed. Client id=${CLIENT_ID}. Approve in EvoFirewall UI (rules optional — can assign later)." -echo "If Still offline after Approve, run: $SYNC_SCRIPT" +echo "If still offline after Approve, run: $SYNC_SCRIPT" diff --git a/docs/agents.md b/docs/agents.md index 65df0d7..b3af694 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -36,6 +36,8 @@ curl -fsSL https:///v1/agent/install.sh | \ Файлы: `/etc/evofw/agent.conf`, `/usr/local/sbin/evofw-firewall.sh`, timer `evofw-firewall.timer` (default 1min). +Install сам ставит зависимости через apt/dnf/yum/apk: `curl`, `jq` (или `python3`), `nftables`/`iptables`(+`ipset`). Планировщик: **systemd timer** если есть `/run/systemd/system`, иначе ставит `cron`/`cronie` и пишет crontab. + Backend auto-detect: nft → ipset → iptables. Whitelist: nft chain policy drop + allow set. Blacklist: policy accept + deny set.