Files
scripts-bash/servers/linux/monitoring/bin/monitoring.php
2026-03-18 08:51:50 +01:00

168 lines
5.3 KiB
PHP
Executable File

#!/usr/bin/env php
<?php
/**
* Monitoring Update Engine - PHP Version
* Copyright (C) 2026 Cédric Abonnel
*/
require_once __DIR__ . '/../lib/monitoring-lib.php';
// --- Configuration ---
// Note : La lib a déjà chargé $CONFIG['UPDATE_BASE_URL'] etc. depuis monitoring.local.conf.php
// On ne charge les fichiers spécifiques que s'ils apportent des règles de mise à jour uniques.
foreach (["/opt/monitoring/conf/autoupdate.conf.php", "/opt/monitoring/conf/autoupdate.local.conf.php"] as $conf) {
if (file_exists($conf)) {
$extra_conf = include $conf;
if (is_array($extra_conf)) {
$CONFIG = array_replace_recursive($CONFIG, $extra_conf);
}
}
}
// Variables par défaut (fallback si absent de la config globale)
$UPDATE_ENABLED = $CONFIG['UPDATE_ENABLED'] ?? true;
$UPDATE_TMP_DIR = $CONFIG['UPDATE_TMP_DIR'] ?? '/tmp/monitoring-update';
$UPDATE_TIMEOUT_TOTAL = $CONFIG['UPDATE_TIMEOUT_TOTAL'] ?? 15;
$UPDATE_MANIFEST_URL = $CONFIG['UPDATE_MANIFEST_URL'] ?? '';
$UPDATE_BASE_URL = $CONFIG['UPDATE_BASE_URL'] ?? '';
$UPDATE_ALLOW_DELETE = $CONFIG['UPDATE_ALLOW_DELETE'] ?? false;
$MONITORING_BASE_DIR = $MONITORING_BASE_DIR; // Provient de la lib
// --- Initialisation ---
lock_or_exit("monitoring-update");
if (!$UPDATE_ENABLED) {
log_notice("update_disabled", "Mise à jour désactivée");
exit(0);
}
if (!is_dir($UPDATE_TMP_DIR)) {
mkdir($UPDATE_TMP_DIR, 0755, true);
}
/**
* Télécharge et valide le manifeste
*/
function fetch_manifest($url) {
global $UPDATE_TIMEOUT_TOTAL;
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $UPDATE_TIMEOUT_TOTAL,
CURLOPT_FAILONERROR => true,
CURLOPT_FOLLOWLOCATION => true
]);
$content = curl_exec($ch);
if (curl_errno($ch)) {
log_error("manifest_download_failed", "Échec téléchargement manifeste", ["url" => $url, "err" => curl_error($ch)]);
return false;
}
curl_close($ch);
$manifest_entries = [];
$lines = explode("\n", trim($content));
foreach ($lines as $line) {
if (preg_match('/^([0-9a-fA-F]{64})\s+(644|755)\s+((bin|lib|conf)\/[A-Za-z0-9._\/-]+)$/', trim($line), $matches)) {
$manifest_entries[] = ['hash' => $matches[1], 'mode' => $matches[2], 'path' => $matches[3]];
}
}
return $manifest_entries;
}
/**
* Met à jour un fichier
*/
function update_one_file($entry) {
global $MONITORING_BASE_DIR, $UPDATE_BASE_URL, $UPDATE_TMP_DIR, $UPDATE_TIMEOUT_TOTAL;
$rel_path = $entry['path'];
$target_file = $MONITORING_BASE_DIR . '/' . $rel_path;
$remote_url = rtrim($UPDATE_BASE_URL, '/') . '/' . $rel_path;
$expected_hash = strtolower($entry['hash']);
if (file_exists($target_file) && hash_file('sha256', $target_file) === $expected_hash) {
return true;
}
$tmp_file = $UPDATE_TMP_DIR . '/' . basename($rel_path) . '.' . uniqid();
$ch = curl_init($remote_url);
$fp = fopen($tmp_file, 'wb');
curl_setopt_array($ch, [
CURLOPT_FILE => $fp,
CURLOPT_TIMEOUT => $UPDATE_TIMEOUT_TOTAL,
CURLOPT_FAILONERROR => true,
CURLOPT_FOLLOWLOCATION => true
]);
$success = curl_exec($ch);
curl_close($ch);
fclose($fp);
if (!$success || hash_file('sha256', $tmp_file) !== $expected_hash) {
log_error("update_failed", "Fichier invalide ou corrompu", ["file" => $rel_path]);
@unlink($tmp_file);
return false;
}
ensure_parent_dir($target_file);
chmod($tmp_file, octdec($entry['mode']));
safe_mv($tmp_file, $target_file); // Utilise la fonction safe_mv de ta lib
log_notice("file_updated", "Mise à jour appliquée", ["file" => $rel_path]);
return true;
}
/**
* Nettoyage
*/
function delete_extra_files($remote_files) {
global $UPDATE_ALLOW_DELETE, $MONITORING_BASE_DIR, $SCRIPT_PATH;
if (!$UPDATE_ALLOW_DELETE) return;
foreach (['bin', 'lib', 'conf'] as $dir) {
$full_path = $MONITORING_BASE_DIR . '/' . $dir;
if (!is_dir($full_path)) continue;
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($full_path, RecursiveDirectoryIterator::SKIP_DOTS));
foreach ($iterator as $file) {
$path = $file->getPathname();
$rel_path = substr($path, strlen($MONITORING_BASE_DIR) + 1);
// PROTECTIONS
if (in_array($rel_path, $remote_files)) continue;
if (str_contains($rel_path, '.local.')) continue; // Protection fichiers locaux
if ($path === $SCRIPT_PATH) continue; // Ne pas se suicider
if (@unlink($path)) {
log_notice("file_deleted", "Fichier obsolète supprimé", ["file" => $rel_path]);
}
}
}
}
// --- Main ---
$manifest = fetch_manifest($UPDATE_MANIFEST_URL);
if (!$manifest) exit(2);
$remote_paths = [];
$updated = 0; $failed = 0;
foreach ($manifest as $entry) {
$remote_paths[] = $entry['path'];
update_one_file($entry) ? $updated++ : $failed++;
}
delete_extra_files($remote_paths);
if ($failed > 0) {
log_warning("update_partial", "Mise à jour terminée avec erreurs", ["failed" => $failed]);
} else {
log_info("update_ok", "Mise à jour terminée avec succès");
}
exit_with_status();