migration vers monitoring
This commit is contained in:
214
servers/linux/monitoring/bin/monitoring-update.sh
Normal file
214
servers/linux/monitoring/bin/monitoring-update.sh
Normal file
@@ -0,0 +1,214 @@
|
||||
#!/bin/bash
|
||||
# Copyright (C) 2026 Cédric Abonnel
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
|
||||
set -u
|
||||
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
SCRIPT_PATH="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")"
|
||||
|
||||
# shellcheck source=/opt/monitoring/lib/monitoring-lib.sh
|
||||
. /opt/monitoring/lib/monitoring-lib.sh || exit 3
|
||||
|
||||
load_conf_if_exists "/opt/monitoring/conf/autoupdate.conf"
|
||||
load_conf_if_exists "/opt/monitoring/conf/autoupdate.local.conf"
|
||||
|
||||
lock_or_exit "monitoring-update"
|
||||
require_cmd curl sha256sum awk mktemp chmod dirname mv rm grep sed sort comm cut tr find
|
||||
|
||||
[ "${UPDATE_ENABLED:-true}" = "true" ] || {
|
||||
log_notice "update_disabled" "Mise à jour désactivée par configuration"
|
||||
exit 0
|
||||
}
|
||||
|
||||
mkdir -p "${UPDATE_TMP_DIR:-/tmp/monitoring-update}" || fail_internal "Impossible de créer le répertoire temporaire"
|
||||
|
||||
TMP_MANIFEST="$(mktemp "${UPDATE_TMP_DIR}/manifest.XXXXXX")" || fail_internal "mktemp a échoué"
|
||||
TMP_LOCAL_LIST="$(mktemp "${UPDATE_TMP_DIR}/local.XXXXXX")" || fail_internal "mktemp a échoué"
|
||||
TMP_REMOTE_LIST="$(mktemp "${UPDATE_TMP_DIR}/remote.XXXXXX")" || fail_internal "mktemp a échoué"
|
||||
|
||||
cleanup() {
|
||||
rm -f "$TMP_MANIFEST" "$TMP_LOCAL_LIST" "$TMP_REMOTE_LIST"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
fetch_manifest() {
|
||||
if ! curl -fsS \
|
||||
--connect-timeout "${UPDATE_TIMEOUT_CONNECT:-3}" \
|
||||
--max-time "${UPDATE_TIMEOUT_TOTAL:-15}" \
|
||||
"${UPDATE_MANIFEST_URL}" \
|
||||
-o "$TMP_MANIFEST"; then
|
||||
log_error "manifest_download_failed" \
|
||||
"Impossible de télécharger le manifeste" \
|
||||
"url=${UPDATE_MANIFEST_URL}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! awk '
|
||||
NF == 3 &&
|
||||
$1 ~ /^[0-9a-fA-F]{64}$/ &&
|
||||
$2 ~ /^(644|755)$/ &&
|
||||
$3 ~ /^(bin|lib|conf)\/[A-Za-z0-9._\/-]+$/ &&
|
||||
$3 !~ /\.\./
|
||||
' "$TMP_MANIFEST" >/dev/null; then
|
||||
log_error "manifest_invalid" \
|
||||
"Le manifeste distant est invalide" \
|
||||
"url=${UPDATE_MANIFEST_URL}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "manifest_downloaded" "Manifeste téléchargé" "url=${UPDATE_MANIFEST_URL}"
|
||||
return 0
|
||||
}
|
||||
|
||||
list_remote_files() {
|
||||
awk '{print $3}' "$TMP_MANIFEST" | sort -u > "$TMP_REMOTE_LIST"
|
||||
}
|
||||
|
||||
list_local_files() {
|
||||
find "${MONITORING_BASE_DIR}/bin" "${MONITORING_BASE_DIR}/lib" "${MONITORING_BASE_DIR}/conf" \
|
||||
-type f 2>/dev/null \
|
||||
| sed "s#^${MONITORING_BASE_DIR}/##" \
|
||||
| sort -u > "$TMP_LOCAL_LIST"
|
||||
}
|
||||
|
||||
apply_mode() {
|
||||
local mode="$1"
|
||||
local file="$2"
|
||||
|
||||
case "$mode" in
|
||||
755) chmod 755 "$file" ;;
|
||||
644) chmod 644 "$file" ;;
|
||||
*) fail_internal "Mode non supporté: $mode" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
update_one_file() {
|
||||
local expected_hash="$1"
|
||||
local mode="$2"
|
||||
local rel_path="$3"
|
||||
|
||||
local local_file="${MONITORING_BASE_DIR}/${rel_path}"
|
||||
local remote_file="${UPDATE_BASE_URL}/${rel_path}"
|
||||
local tmp_file local_hash downloaded_hash
|
||||
|
||||
tmp_file="$(mktemp "${UPDATE_TMP_DIR}/$(basename "$rel_path").XXXXXX")" || fail_internal "mktemp a échoué"
|
||||
|
||||
if [ -f "$local_file" ]; then
|
||||
local_hash="$(sha256sum "$local_file" | awk '{print $1}')"
|
||||
else
|
||||
local_hash=""
|
||||
fi
|
||||
|
||||
if [ "$local_hash" = "$expected_hash" ]; then
|
||||
log_debug "update_not_needed" "Fichier déjà à jour" "file=$rel_path"
|
||||
rm -f "$tmp_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! curl -fsS \
|
||||
--connect-timeout "${UPDATE_TIMEOUT_CONNECT:-3}" \
|
||||
--max-time "${UPDATE_TIMEOUT_TOTAL:-15}" \
|
||||
"$remote_file" \
|
||||
-o "$tmp_file"; then
|
||||
log_error "update_download_failed" \
|
||||
"Téléchargement impossible" \
|
||||
"file=$rel_path" "url=$remote_file"
|
||||
rm -f "$tmp_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
downloaded_hash="$(sha256sum "$tmp_file" | awk '{print $1}')"
|
||||
if [ "$downloaded_hash" != "$expected_hash" ]; then
|
||||
log_error "update_hash_mismatch" \
|
||||
"Hash téléchargé invalide" \
|
||||
"file=$rel_path" "expected=$expected_hash" "got=$downloaded_hash"
|
||||
rm -f "$tmp_file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
ensure_parent_dir "$local_file"
|
||||
apply_mode "$mode" "$tmp_file"
|
||||
safe_mv "$tmp_file" "$local_file"
|
||||
|
||||
if [ -z "$local_hash" ]; then
|
||||
log_notice "file_created" \
|
||||
"Fichier créé depuis le manifeste" \
|
||||
"file=$rel_path" "mode=$mode" "hash=$expected_hash"
|
||||
else
|
||||
log_notice "update_applied" \
|
||||
"Mise à jour appliquée" \
|
||||
"file=$rel_path" "mode=$mode" "old_hash=$local_hash" "new_hash=$expected_hash"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
delete_extra_local_files() {
|
||||
[ "${UPDATE_ALLOW_DELETE:-false}" = "true" ] || return 0
|
||||
|
||||
comm -23 "$TMP_LOCAL_LIST" "$TMP_REMOTE_LIST" | while IFS= read -r rel_path; do
|
||||
[ -n "$rel_path" ] || continue
|
||||
|
||||
case "$rel_path" in
|
||||
conf/alert-engine.local.conf|conf/autoupdate.local.conf|conf/monitoring.local.conf)
|
||||
log_notice "delete_skipped" \
|
||||
"Suppression ignorée pour fichier local protégé" \
|
||||
"file=$rel_path"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
|
||||
rm -f "${MONITORING_BASE_DIR}/${rel_path}" \
|
||||
&& log_notice "file_deleted" \
|
||||
"Fichier supprimé car absent du manifeste" \
|
||||
"file=$rel_path" \
|
||||
|| log_error "delete_failed" \
|
||||
"Impossible de supprimer le fichier local absent du manifeste" \
|
||||
"file=$rel_path"
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
local total=0 updated_or_checked=0 failed=0
|
||||
local hash mode path
|
||||
|
||||
fetch_manifest || exit 2
|
||||
list_remote_files
|
||||
list_local_files
|
||||
|
||||
while read -r hash mode path; do
|
||||
[ -n "${hash:-}" ] || continue
|
||||
total=$((total + 1))
|
||||
|
||||
if update_one_file "$hash" "$mode" "$path"; then
|
||||
updated_or_checked=$((updated_or_checked + 1))
|
||||
else
|
||||
failed=$((failed + 1))
|
||||
fi
|
||||
done < "$TMP_MANIFEST"
|
||||
|
||||
delete_extra_local_files
|
||||
|
||||
if [ "$failed" -gt 0 ]; then
|
||||
log_warning "update_finished_with_errors" \
|
||||
"Mise à jour terminée avec erreurs" \
|
||||
"total=$total" "updated_or_checked=$updated_or_checked" "failed=$failed"
|
||||
else
|
||||
log_info "update_finished" \
|
||||
"Mise à jour terminée" \
|
||||
"total=$total" "updated_or_checked=$updated_or_checked" "failed=0"
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
exit_with_status
|
||||
Reference in New Issue
Block a user