feat(install): script d'installation agents complet

- Détection architecture (amd64, arm64, Raspberry Pi armv7)
- Téléchargement binaire depuis release Gitea
- Création config YAML dans /etc/sentinelmesh/
- Création et activation service systemd
- Enregistrement automatique auprès du backend
- Vérification des prérequis (root, curl, systemd)
- Support --server, --token, --agent-type, --hostname, --version

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 06:24:29 +02:00
parent 8a8641e9cd
commit 10cc6979c9
Regular → Executable
+189 -10
View File
@@ -1,31 +1,210 @@
#!/usr/bin/env bash
# Script d'installation des agents SentinelMesh
# Installation d'un agent SentinelMesh
# Usage : curl -fsSL http://<backend>:8080/install.sh | bash -s -- --server http://<backend>:8080 --token <token> --agent-type scan-network
set -euo pipefail
# --- Paramètres ---
SERVER=""
PORT="8080"
TOKEN=""
AGENT_TYPE=""
HOSTNAME_OVERRIDE=""
VERSION="latest"
GITEA_URL="https://git.maison43gil.com"
GITEA_REPO="gilles/SentinelMesh"
usage() {
echo "Usage: $0 --server <url> --token <token> --agent-type <scan-network|metric> [--port <port>] [--hostname <name>]"
cat <<EOF
Usage: $0 [OPTIONS]
Options obligatoires :
--server <url> URL du backend SentinelMesh (ex: http://192.168.1.10:8080)
--token <token> Token d'authentification
--agent-type <scan-network|metric> Type d'agent à installer
Options facultatives :
--port <port> Port du backend (défaut: 8080)
--hostname <name> Nom d'hôte (défaut: auto-détecté)
--version <tag> Version à installer (défaut: latest)
EOF
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--server) SERVER="$2"; shift 2 ;;
--port) PORT="$2"; shift 2 ;;
--token) TOKEN="$2"; shift 2 ;;
--agent-type) AGENT_TYPE="$2"; shift 2 ;;
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
*) usage ;;
--server) SERVER="$2"; shift 2 ;;
--port) PORT="$2"; shift 2 ;;
--token) TOKEN="$2"; shift 2 ;;
--agent-type) AGENT_TYPE="$2"; shift 2 ;;
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
--version) VERSION="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Option inconnue : $1"; usage ;;
esac
done
[[ -z "$SERVER" || -z "$TOKEN" || -z "$AGENT_TYPE" ]] && usage
[[ "$AGENT_TYPE" != "scan-network" && "$AGENT_TYPE" != "metric" ]] && {
echo "Erreur : --agent-type doit être 'scan-network' ou 'metric'"
exit 1
}
# TODO Phase 5 : téléchargement binaire, création config, enregistrement backend, service systemd
# --- Détection ---
HOSTNAME="${HOSTNAME_OVERRIDE:-$(hostname -f 2>/dev/null || cat /etc/hostname || echo "unknown")}"
AGENT_ID="$(echo "${AGENT_TYPE}-${HOSTNAME}" | tr '.' '-')"
echo "Installation agent-${AGENT_TYPE}${SERVER}:${PORT} (non implémenté — Phase 5)"
detect_arch() {
case "$(uname -m)" in
x86_64) echo "x86_64-unknown-linux-gnu" ;;
aarch64|arm64) echo "aarch64-unknown-linux-gnu" ;;
armv7l) echo "armv7-unknown-linux-gnueabihf" ;;
*) echo "Architecture non supportée : $(uname -m)" >&2; exit 1 ;;
esac
}
ARCH="$(detect_arch)"
# --- Chemins ---
BINARY_NAME="agent-${AGENT_TYPE}"
INSTALL_DIR="/usr/local/bin"
CONFIG_DIR="/etc/sentinelmesh"
SERVICE_NAME="sentinelmesh-${AGENT_TYPE}"
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
# Port API locale selon le type d'agent
[[ "$AGENT_TYPE" == "scan-network" ]] && API_PORT="9100" || API_PORT="9101"
# --- Vérifications ---
[[ "$EUID" -ne 0 ]] && { echo "Erreur : ce script doit être exécuté en root (sudo)."; exit 1; }
command -v curl &>/dev/null || { echo "Erreur : curl est requis."; exit 1; }
command -v systemctl &>/dev/null || { echo "Erreur : systemd est requis."; exit 1; }
echo "========================================"
echo " Installation SentinelMesh — ${BINARY_NAME}"
echo "========================================"
echo " Serveur : ${SERVER}"
echo " Agent ID : ${AGENT_ID}"
echo " Hostname : ${HOSTNAME}"
echo " Architecture: ${ARCH}"
echo " Version : ${VERSION}"
echo "========================================"
# --- Téléchargement ---
if [[ "$VERSION" == "latest" ]]; then
DOWNLOAD_URL="${GITEA_URL}/${GITEA_REPO}/releases/download/latest/${BINARY_NAME}-${ARCH}"
else
DOWNLOAD_URL="${GITEA_URL}/${GITEA_REPO}/releases/download/${VERSION}/${BINARY_NAME}-${ARCH}"
fi
echo "[1/5] Téléchargement du binaire…"
TMP_BIN="$(mktemp)"
if ! curl -fsSL -o "$TMP_BIN" "$DOWNLOAD_URL"; then
echo "Erreur : impossible de télécharger ${DOWNLOAD_URL}"
echo "Conseil : vérifiez que la version ${VERSION} est publiée sur Gitea."
rm -f "$TMP_BIN"
exit 1
fi
chmod +x "$TMP_BIN"
mv "$TMP_BIN" "${INSTALL_DIR}/${BINARY_NAME}"
echo "${INSTALL_DIR}/${BINARY_NAME}"
# --- Configuration ---
echo "[2/5] Création de la configuration…"
mkdir -p "$CONFIG_DIR"
cat > "${CONFIG_DIR}/${AGENT_TYPE}.yaml" <<YAML
backend:
url: ${SERVER}
token: ${TOKEN}
agent:
id: ${AGENT_ID}
hostname: ${HOSTNAME}
$(if [[ "$AGENT_TYPE" == "scan-network" ]]; then
cat <<SCAN
scan:
subnets:
- 10.0.0.0/22
interval_seconds: 60
ping_timeout_ms: 1000
service_timeout_ms: 300
concurrency: 50
ports: [22, 80, 443, 445, 2049, 1883, 2375, 8006, 8123, 3000, 9090, 9100]
api:
listen: "0.0.0.0:${API_PORT}"
SCAN
else
cat <<METRIC
intervals:
realtime_ms: 1000
medium_s: 1800
api:
listen: "0.0.0.0:${API_PORT}"
METRIC
fi)
YAML
chmod 600 "${CONFIG_DIR}/${AGENT_TYPE}.yaml"
echo "${CONFIG_DIR}/${AGENT_TYPE}.yaml"
# --- Service systemd ---
echo "[3/5] Création du service systemd…"
cat > "$SERVICE_FILE" <<SYSTEMD
[Unit]
Description=SentinelMesh agent-${AGENT_TYPE}
Documentation=https://git.maison43gil.com/gilles/SentinelMesh
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=${INSTALL_DIR}/${BINARY_NAME} ${CONFIG_DIR}/${AGENT_TYPE}.yaml
Restart=on-failure
RestartSec=10
User=root
StandardOutput=journal
StandardError=journal
SyslogIdentifier=${SERVICE_NAME}
$(if [[ "$AGENT_TYPE" == "scan-network" ]]; then
echo "# Accès réseau nécessaire pour les scans ICMP/ARP"
echo "AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN"
fi)
[Install]
WantedBy=multi-user.target
SYSTEMD
echo "${SERVICE_FILE}"
# --- Activation ---
echo "[4/5] Activation et démarrage du service…"
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
sleep 2
if systemctl is-active --quiet "$SERVICE_NAME"; then
echo " → Service ${SERVICE_NAME} démarré avec succès"
else
echo " ⚠ Le service ne s'est pas démarré correctement"
echo " Vérifier avec : journalctl -u ${SERVICE_NAME} -n 30"
fi
# --- Enregistrement backend ---
echo "[5/5] Enregistrement auprès du backend…"
LOCAL_IP="$(hostname -I | awk '{print $1}')"
curl -fsSL -X POST "${SERVER}/api/v1/agents" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"id\":\"${AGENT_ID}\",\"hostname\":\"${HOSTNAME}\",\"agent_type\":\"${AGENT_TYPE}\",\"ip\":\"${LOCAL_IP}\",\"version\":\"${VERSION}\"}" \
&>/dev/null && echo " → Agent enregistré" || echo " ⚠ Enregistrement échoué (l'agent réessaiera au démarrage)"
echo ""
echo "========================================"
echo " Installation terminée !"
echo ""
echo " Commandes utiles :"
echo " Statut : systemctl status ${SERVICE_NAME}"
echo " Logs : journalctl -u ${SERVICE_NAME} -f"
echo " Config : ${CONFIG_DIR}/${AGENT_TYPE}.yaml"
echo " API locale : http://localhost:${API_PORT}"
echo "========================================"