diff --git a/backend/src/controllers/monitoringAgent.controller.js b/backend/src/controllers/monitoringAgent.controller.js index fddaa62..6f2bc9e 100644 --- a/backend/src/controllers/monitoringAgent.controller.js +++ b/backend/src/controllers/monitoringAgent.controller.js @@ -12,6 +12,24 @@ const crypto = require('crypto'); // Downgrade-Bug für Agents ohne Patch-Gruppe oder ohne ?hostname-Parameter.) const FALLBACK_AGENT_VERSION = '2.8.0'; +// Vergleicht zwei "x.y.z"-Versionsstrings. >0 wenn a>b, <0 wenn a parseInt(n, 10) || 0); + const pb = String(b || '0').split('.').map(n => parseInt(n, 10) || 0); + for (let i = 0; i < Math.max(pa.length, pb.length); i++) { + const diff = (pa[i] || 0) - (pb[i] || 0); + if (diff !== 0) return diff; + } + return 0; +} + +// Nie eine ältere Version als die aktuell installierte vorschlagen/ausliefern — verhindert +// Downgrades durch fehlerhafte ENV-Konfiguration, falsch gesetzte Gruppen-Zielversionen o.ä. +function clampToNotOlder(targetVersion, currentVersion) { + if (!currentVersion) return targetVersion; + return compareVersions(targetVersion, currentVersion) < 0 ? currentVersion : targetVersion; +} + // POST /api/monitoring/enroll — Agent tauscht geteilten Bootstrap-Key gegen individuellen Per-Device-Key. // Idempotent: ein bereits enrollter Agent bekommt seinen bestehenden Key einfach erneut zurück. const enroll = asyncHandler(async (req, res) => { @@ -143,6 +161,8 @@ const checkin = asyncHandler(async (req, res) => { if (groupRow?.target_agent_version) targetVersion = groupRow.target_agent_version; } catch { /* kein Gruppe zugewiesen → global */ } + targetVersion = clampToNotOlder(targetVersion, req.body.agent_version); + const announcements = getForAgent(agent.id); res.json({ @@ -254,7 +274,7 @@ const downloadSetup = asyncHandler(async (req, res) => { if (hostname) { try { const db = getDatabase(); - const agent = db.prepare('SELECT id FROM monitoring_agents WHERE hostname = ?').get(hostname); + const agent = db.prepare('SELECT id, agent_version FROM monitoring_agents WHERE hostname = ?').get(hostname); const groupRow = agent && db.prepare(` SELECT pg.target_agent_version FROM patch_agent_groups pag @@ -264,6 +284,7 @@ const downloadSetup = asyncHandler(async (req, res) => { LIMIT 1 `).get(agent.id); if (groupRow?.target_agent_version) version = groupRow.target_agent_version; + version = clampToNotOlder(version, agent?.agent_version); } catch { /* kein Gruppe zugewiesen → global */ } }