The tree adds the installer, service and test paths admitted by this source commit. Nothing else changes about what may cross. Source-Sha: 3e4a3aa4ce092e9e3f51bc78daf3ddc14d9638f8 Policy-Sha: 3e4a3aa4ce092e9e3f51bc78daf3ddc14d9638f8 Tree-Digest: 89d6fce3828a0e0de0c8eeb41ee6750f4462217e2a04b5190297134d7f4a50c3
187 lines
7.7 KiB
Shell
187 lines
7.7 KiB
Shell
#!/bin/sh
|
|
# RedFlag Debian postinst.
|
|
#
|
|
# Idempotent by construction: every step either verifies existing state or
|
|
# creates it. Existing configuration, keys and fleet credentials are never
|
|
# overwritten, and a fleet-enrolled host is never converted to standalone —
|
|
# standalone provisioning is skipped entirely when fleet material is present.
|
|
set -e
|
|
|
|
AGENT_USER=redflag-agent
|
|
LOCAL_GROUP=redflag-local
|
|
PKG_BIN_DIR=/usr/bin
|
|
RUN_BIN_DIR=/usr/local/bin
|
|
CONFIG_DIR=/etc/redflag
|
|
AGENT_CONFIG_DIR=$CONFIG_DIR/agent
|
|
AGENT_CONFIG=$AGENT_CONFIG_DIR/config.json
|
|
SERVER_KEY_DIR=$CONFIG_DIR/server
|
|
BASE_DIR=/var/lib/redflag
|
|
AGENT_HOME=$BASE_DIR/agent
|
|
LOG_DIR=/var/log/redflag/agent
|
|
PROVISION=/usr/lib/redflag/provision-standalone-authority.sh
|
|
VERSION="@VERSION@"
|
|
|
|
log() { echo "[INFO] [deb] [postinst] $*"; }
|
|
warn() { echo "[WARN] [deb] [postinst] $*" >&2; }
|
|
|
|
case "$1" in
|
|
configure) ;;
|
|
abort-upgrade|abort-remove|abort-deconfigure) exit 0 ;;
|
|
*) exit 0 ;;
|
|
esac
|
|
|
|
# Also guard reconfiguration and recovery after an interrupted installation.
|
|
for b in redflag-agent redflag-helper redflag-desktop; do
|
|
path="$RUN_BIN_DIR/$b"
|
|
if [ -L "$path" ]; then
|
|
[ "$(readlink "$path")" = "$PKG_BIN_DIR/$b" ] && continue
|
|
elif [ ! -e "$path" ]; then
|
|
continue
|
|
fi
|
|
warn "$path is not the package runtime link; explicit migration is required"
|
|
exit 1
|
|
done
|
|
|
|
# ---- user, groups -----------------------------------------------------------
|
|
if ! getent group "$LOCAL_GROUP" >/dev/null 2>&1; then
|
|
addgroup --system "$LOCAL_GROUP"
|
|
fi
|
|
if ! id "$AGENT_USER" >/dev/null 2>&1; then
|
|
adduser --system --group --home "$AGENT_HOME" --no-create-home \
|
|
--shell /usr/sbin/nologin "$AGENT_USER"
|
|
fi
|
|
if ! id -nG "$AGENT_USER" | tr ' ' '\n' | grep -qx "$LOCAL_GROUP"; then
|
|
usermod -aG "$LOCAL_GROUP" "$AGENT_USER"
|
|
fi
|
|
# Container scanner reaches the docker socket by group membership, not sudo.
|
|
if getent group docker >/dev/null 2>&1; then
|
|
if ! id -nG "$AGENT_USER" | tr ' ' '\n' | grep -qx docker; then
|
|
usermod -aG docker "$AGENT_USER"
|
|
fi
|
|
fi
|
|
|
|
# ---- runtime paths ----------------------------------------------------------
|
|
# Re-asserted on every configure: upgrades from script installs carry
|
|
# agent:agent 0700 dirs that block redflag-local traversal to the local API
|
|
# socket, leaving Desktop installed but unable to connect.
|
|
install -d -m 0755 "$CONFIG_DIR" "$AGENT_CONFIG_DIR" "$SERVER_KEY_DIR"
|
|
# BASE_DIR is root-owned: rename permission comes from the parent directory, so
|
|
# an agent-owned BASE_DIR lets the agent swap the root-only helper staging dir
|
|
# for a symlink. Group execute still lets the agent reach its own subtree.
|
|
install -d -m 0710 -o root -g "$LOCAL_GROUP" "$BASE_DIR"
|
|
install -d -m 0710 -o "$AGENT_USER" -g "$LOCAL_GROUP" "$AGENT_HOME"
|
|
install -d -m 0750 -o "$AGENT_USER" -g "$LOCAL_GROUP" "$AGENT_HOME/localapi"
|
|
install -d -m 0750 -o "$AGENT_USER" -g "$AGENT_USER" \
|
|
"$AGENT_HOME/cache" "$AGENT_HOME/state" "$AGENT_HOME/results"
|
|
install -d -m 0700 -o "$AGENT_USER" -g "$AGENT_USER" "$AGENT_HOME/tokens"
|
|
install -d -m 0700 -o root -g root "$BASE_DIR/helper"
|
|
install -d -m 0750 -o "$AGENT_USER" -g "$AGENT_USER" "$LOG_DIR"
|
|
chown "$AGENT_USER":"$AGENT_USER" "$AGENT_CONFIG_DIR" "$SERVER_KEY_DIR"
|
|
|
|
# ---- runtime symlinks -------------------------------------------------------
|
|
# The agent, helper and their sudoers/service contracts all reference
|
|
# /usr/local/bin (agent/internal/constants/paths.go). Debian policy keeps
|
|
# package files out of /usr/local, so ship in /usr/bin and link. The preflight
|
|
# above refuses foreign paths; the package-managed helper refuses self-update.
|
|
for b in redflag-agent redflag-helper redflag-desktop; do
|
|
if [ -L "$RUN_BIN_DIR/$b" ] || [ ! -e "$RUN_BIN_DIR/$b" ]; then
|
|
install -d -m 0755 "$RUN_BIN_DIR"
|
|
ln -sfn "$PKG_BIN_DIR/$b" "$RUN_BIN_DIR/$b"
|
|
else
|
|
warn "$RUN_BIN_DIR/$b changed during configuration — refusing runtime takeover"
|
|
exit 1
|
|
fi
|
|
done
|
|
if command -v setcap >/dev/null 2>&1; then
|
|
setcap cap_sys_ptrace=eip "$PKG_BIN_DIR/redflag-agent" || \
|
|
warn "setcap failed — display/process discovery may be limited"
|
|
fi
|
|
|
|
# ---- configuration ----------------------------------------------------------
|
|
# Not a dpkg conffile: it holds credentials and is rewritten by the agent.
|
|
if [ -f "$AGENT_CONFIG" ]; then
|
|
log "existing configuration preserved at $AGENT_CONFIG"
|
|
else
|
|
log "fresh install — writing standalone configuration"
|
|
umask 077
|
|
cat > "$AGENT_CONFIG" <<EOF
|
|
{
|
|
"version": 5,
|
|
"agent_version": "${VERSION}",
|
|
"agent_id": "",
|
|
"token": "",
|
|
"refresh_token": "",
|
|
"registration_token": "",
|
|
"machine_id": "",
|
|
"check_in_interval": 300,
|
|
"server_url": "",
|
|
"network": {"timeout": 30000000000, "retry_count": 3, "retry_delay": 5000000000, "max_idle_conn": 10},
|
|
"proxy": {"enabled": false},
|
|
"tls": {"enabled": false, "insecure_skip_verify": false},
|
|
"logging": {"level": "info", "max_size": 100, "max_backups": 3, "max_age": 28},
|
|
"subsystems": {
|
|
"system": {"enabled": true, "timeout": 10000000000},
|
|
"filesystem": {"enabled": true, "timeout": 10000000000},
|
|
"network": {"enabled": true, "timeout": 30000000000},
|
|
"processes": {"enabled": true, "timeout": 30000000000},
|
|
"updates": {"enabled": true, "timeout": 30000000000},
|
|
"storage": {"enabled": true, "timeout": 10000000000}
|
|
},
|
|
"security": {"ed25519_verification": true, "nonce_validation": true, "machine_id_binding": true}
|
|
}
|
|
EOF
|
|
fi
|
|
chown "$AGENT_USER":"$AGENT_USER" "$AGENT_CONFIG"
|
|
chmod 0600 "$AGENT_CONFIG"
|
|
|
|
# ---- fleet detection --------------------------------------------------------
|
|
# Any of token / refresh_token / registration_token means this host answers to a
|
|
# server. Config.IsStandalone() is false for partial enrollment too, so the
|
|
# provisioning script would refuse — we refuse first and say why.
|
|
fleet_material() {
|
|
grep -Eq '"(token|refresh_token|registration_token)"[[:space:]]*:[[:space:]]*"[^"]+"' "$AGENT_CONFIG" 2>/dev/null
|
|
}
|
|
|
|
if fleet_material; then
|
|
log "fleet enrollment material present — standalone authority NOT provisioned"
|
|
log "this host keeps its fleet credentials; standalone-to-fleet conversion is not implemented in either direction"
|
|
elif [ -x "$PROVISION" ]; then
|
|
# The script is the single source of authority provisioning (key init,
|
|
# exchange dirs, mint sudoers). It is idempotent and refuses to overwrite an
|
|
# existing local authority.
|
|
if REDFLAG_BIN_DIR="$RUN_BIN_DIR" \
|
|
REDFLAG_CONFIG_DIR="$CONFIG_DIR" \
|
|
REDFLAG_STATE_DIR="$BASE_DIR" \
|
|
"$PROVISION"; then
|
|
log "standalone authority provisioned"
|
|
else
|
|
warn "standalone authority provisioning failed — agent installed, local approval unavailable"
|
|
warn "re-run once resolved: sudo REDFLAG_BIN_DIR=$RUN_BIN_DIR $PROVISION"
|
|
exit 1
|
|
fi
|
|
else
|
|
warn "$PROVISION missing or not executable — standalone authority not provisioned"
|
|
exit 1
|
|
fi
|
|
|
|
# ---- desktop access ---------------------------------------------------------
|
|
# The installing operator needs redflag-local to reach the agent's local API
|
|
# socket. Takes effect on next login.
|
|
if [ -n "${SUDO_USER:-}" ] && [ "$SUDO_USER" != root ]; then
|
|
if ! id -nG "$SUDO_USER" 2>/dev/null | tr ' ' '\n' | grep -qx "$LOCAL_GROUP"; then
|
|
usermod -aG "$LOCAL_GROUP" "$SUDO_USER"
|
|
log "added $SUDO_USER to $LOCAL_GROUP (Desktop socket access — re-login required)"
|
|
fi
|
|
fi
|
|
|
|
# ---- service ----------------------------------------------------------------
|
|
if [ -d /run/systemd/system ]; then
|
|
systemctl daemon-reload
|
|
systemctl enable redflag-agent.service
|
|
if ! systemctl restart redflag-agent.service; then
|
|
warn "redflag-agent did not start — check: journalctl -u redflag-agent"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
exit 0
|