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:
Regular → Executable
+189
-10
@@ -1,31 +1,210 @@
|
|||||||
#!/usr/bin/env bash
|
#!/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
|
set -euo pipefail
|
||||||
|
|
||||||
|
# --- Paramètres ---
|
||||||
SERVER=""
|
SERVER=""
|
||||||
PORT="8080"
|
PORT="8080"
|
||||||
TOKEN=""
|
TOKEN=""
|
||||||
AGENT_TYPE=""
|
AGENT_TYPE=""
|
||||||
HOSTNAME_OVERRIDE=""
|
HOSTNAME_OVERRIDE=""
|
||||||
|
VERSION="latest"
|
||||||
|
GITEA_URL="https://git.maison43gil.com"
|
||||||
|
GITEA_REPO="gilles/SentinelMesh"
|
||||||
|
|
||||||
usage() {
|
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
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--server) SERVER="$2"; shift 2 ;;
|
--server) SERVER="$2"; shift 2 ;;
|
||||||
--port) PORT="$2"; shift 2 ;;
|
--port) PORT="$2"; shift 2 ;;
|
||||||
--token) TOKEN="$2"; shift 2 ;;
|
--token) TOKEN="$2"; shift 2 ;;
|
||||||
--agent-type) AGENT_TYPE="$2"; shift 2 ;;
|
--agent-type) AGENT_TYPE="$2"; shift 2 ;;
|
||||||
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
|
--hostname) HOSTNAME_OVERRIDE="$2"; shift 2 ;;
|
||||||
*) usage ;;
|
--version) VERSION="$2"; shift 2 ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) echo "Option inconnue : $1"; usage ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
[[ -z "$SERVER" || -z "$TOKEN" || -z "$AGENT_TYPE" ]] && usage
|
[[ -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 "========================================"
|
||||||
|
|||||||
Reference in New Issue
Block a user