feat(go): advance validation sidecar toward production

This commit is contained in:
Luna 2026-07-22 01:52:19 -07:00
parent 6a06eba255
commit f85c2e831a
No known key found for this signature in database
92 changed files with 8881 additions and 91 deletions

View file

@ -0,0 +1,92 @@
// SPDX-License-Identifier: GPL-3.0-or-later
// Package correlation adds higher-confidence stories without hiding or
// replacing their raw alerts. It is transport- and persistence-independent.
package correlation
import "sort"
const SIDMultiStageIntrusion = 100080
type Incident struct {
FirstTimestamp float64 `json:"first_ts"`
LastTimestamp float64 `json:"last_ts"`
Signatures []string `json:"signatures"`
}
type Record struct {
SID int `json:"sid"`
Signature string `json:"signature"`
Classtype string `json:"classtype"`
Severity string `json:"severity"`
Summary string `json:"summary"`
WindowSeconds int `json:"window_seconds"`
MatchedSignatures []string `json:"matched_signatures"`
}
type Rule struct {
SID int
Signature string
Classtype string
Severity string
Summary string
RequiredAny []map[string]bool
MaxWindow int
}
var DefaultRules = []Rule{{
SID: SIDMultiStageIntrusion, Signature: "correlation.multi_stage_intrusion",
Classtype: "multi-stage-intrusion", Severity: "CRITICAL",
Summary: "Web/database service spawned a shell and the same incident showed " +
"suspicious egress or an unusual listener within the correlation window",
RequiredAny: []map[string]bool{
{"exec_rule.web-rce": true},
{"host_rule.suspicious-egress": true, "host_rule.suspicious-listener": true},
},
MaxWindow: 600,
}}
func Correlate(incident Incident, rules []Rule) []Record {
if rules == nil {
rules = DefaultRules
}
signatures := make(map[string]bool, len(incident.Signatures))
for _, signature := range incident.Signatures {
signatures[signature] = true
}
duration := incident.LastTimestamp - incident.FirstTimestamp
result := make([]Record, 0)
for _, rule := range rules {
if duration > float64(rule.MaxWindow) {
continue
}
matched := true
for _, choices := range rule.RequiredAny {
found := false
for choice := range choices {
if signatures[choice] {
found = true
break
}
}
if !found {
matched = false
break
}
}
if !matched {
continue
}
matchedSignatures := make([]string, 0, len(signatures))
for signature := range signatures {
matchedSignatures = append(matchedSignatures, signature)
}
sort.Strings(matchedSignatures)
result = append(result, Record{
SID: rule.SID, Signature: rule.Signature, Classtype: rule.Classtype,
Severity: rule.Severity, Summary: rule.Summary,
WindowSeconds: rule.MaxWindow, MatchedSignatures: matchedSignatures,
})
}
return result
}