feat: fleet ops, KEV scan, tunnels, beacon fallback, persistence
Extend owned-fleet control with scheduled tasks, audit log, file browser, HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
This commit is contained in:
56
server/internal/alerts/kev_notify.go
Normal file
56
server/internal/alerts/kev_notify.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package alerts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// kevExposurePayload mirrors agent KEVScanReport JSON.
|
||||
type kevExposurePayload struct {
|
||||
ExposedCount int `json:"exposed_count"`
|
||||
CriticalCount int `json:"critical_count"`
|
||||
LikelyCount int `json:"likely_count"`
|
||||
RiskScore int `json:"risk_score"`
|
||||
Summary string `json:"summary"`
|
||||
Findings []struct {
|
||||
CVE string `json:"cve"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Severity string `json:"severity"`
|
||||
Detail string `json:"detail"`
|
||||
} `json:"findings"`
|
||||
}
|
||||
|
||||
const EventKEVExposure = "kev_exposure"
|
||||
|
||||
// NotifyKEVFromSysCheck parses a full_sys_check message and sends Telegram if enabled.
|
||||
func NotifyKEVFromSysCheck(n *Notifier, agentName, message string) {
|
||||
if n == nil || strings.TrimSpace(message) == "" {
|
||||
return
|
||||
}
|
||||
var report struct {
|
||||
KEV *kevExposurePayload `json:"kev_exposure"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(message), &report); err != nil || report.KEV == nil {
|
||||
return
|
||||
}
|
||||
k := report.KEV
|
||||
if k.ExposedCount == 0 && k.CriticalCount == 0 {
|
||||
return
|
||||
}
|
||||
s := n.settings()
|
||||
if !s.Events.KEVExposure {
|
||||
return
|
||||
}
|
||||
body := agentName + ": " + k.Summary
|
||||
if body == agentName+": " {
|
||||
body = agentName + ": KEV exposure indicators — exposed=" + strconv.Itoa(k.ExposedCount) + " critical=" + strconv.Itoa(k.CriticalCount)
|
||||
}
|
||||
for _, f := range k.Findings {
|
||||
if f.Status == "exposed" && f.Severity == "critical" {
|
||||
body += "\n• " + f.CVE + " " + f.Name
|
||||
}
|
||||
}
|
||||
n.Emit(EventKEVExposure, "AetherForge KEV alert", body)
|
||||
}
|
||||
Reference in New Issue
Block a user