Migration to a ServiceWorker for most tasks.
Implementation of basic PatchComplianceTask. First real iteration, basic/raw asf.
This commit is contained in:
132
OversightService/Services/PatchComplianceTask.cs
Normal file
132
OversightService/Services/PatchComplianceTask.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OversightService.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Scheduled task that collects Windows update history using osquery
|
||||
/// and sends it to the backend API
|
||||
/// </summary>
|
||||
public class PatchComplianceTask : ScheduledTask
|
||||
{
|
||||
private readonly AppConfig _config;
|
||||
private readonly ApiClient _apiClient;
|
||||
|
||||
public override string TaskName => "PatchCompliance";
|
||||
|
||||
public override TimeSpan Interval =>
|
||||
TimeSpan.FromHours(_config.PatchCompliance.CheckIntervalHours);
|
||||
|
||||
public PatchComplianceTask(AppConfig config, ApiClient apiClient)
|
||||
{
|
||||
_config = config;
|
||||
_apiClient = apiClient;
|
||||
|
||||
// Initialize LastRun from config if available
|
||||
LastRun = _config.PatchCompliance.LastCheckTime;
|
||||
}
|
||||
|
||||
public override bool ShouldRun()
|
||||
{
|
||||
// Don't run if disabled in config
|
||||
if (!_config.PatchCompliance.Enabled)
|
||||
return false;
|
||||
|
||||
return base.ShouldRun();
|
||||
}
|
||||
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Query windows_update_history from osquery
|
||||
var updates = OsqueryService.Query(@"
|
||||
SELECT
|
||||
date,
|
||||
title,
|
||||
update_id
|
||||
FROM windows_update_history
|
||||
ORDER BY date DESC;
|
||||
");
|
||||
|
||||
if (!updates.Any())
|
||||
{
|
||||
LogInfo("No Windows update history found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Transform to API-friendly format
|
||||
var patchData = updates.Select(u => new
|
||||
{
|
||||
date = u.GetValueOrDefault("date"),
|
||||
title = u.GetValueOrDefault("title"),
|
||||
updateId = u.GetValueOrDefault("update_id")
|
||||
}).ToList();
|
||||
|
||||
LogInfo($"Collected {patchData.Count} Windows updates.");
|
||||
|
||||
// Send to API
|
||||
await _apiClient.PostPatchComplianceAsync(patchData);
|
||||
|
||||
// Update config with last check time
|
||||
_config.PatchCompliance.LastCheckTime = DateTime.Now;
|
||||
SaveConfig();
|
||||
|
||||
LogInfo("Patch compliance data sent successfully.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogError($"PatchComplianceTask failed: {ex.Message}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
var configPath = System.IO.Path.Combine(AppContext.BaseDirectory, "config.json");
|
||||
var json = Newtonsoft.Json.JsonConvert.SerializeObject(_config, Newtonsoft.Json.Formatting.Indented);
|
||||
System.IO.File.WriteAllText(configPath, json);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogError($"Failed to save config: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogInfo(string message)
|
||||
{
|
||||
if (!_config.EnableLogging) return;
|
||||
|
||||
try
|
||||
{
|
||||
var logDir = System.IO.Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"PSG-Oversight"
|
||||
);
|
||||
System.IO.Directory.CreateDirectory(logDir);
|
||||
var logPath = System.IO.Path.Combine(logDir, "patch_compliance.log");
|
||||
System.IO.File.AppendAllText(logPath, $"[{DateTime.Now}] INFO: {message}\n");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void LogError(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
var logDir = System.IO.Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"PSG-Oversight"
|
||||
);
|
||||
System.IO.Directory.CreateDirectory(logDir);
|
||||
var logPath = System.IO.Path.Combine(logDir, "patch_compliance.log");
|
||||
System.IO.File.AppendAllText(logPath, $"[{DateTime.Now}] ERROR: {message}\n");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user