feat(go): advance validation sidecar toward production
This commit is contained in:
parent
6a06eba255
commit
f85c2e831a
92 changed files with 8881 additions and 91 deletions
141
go-agent/internal/events/catalog.go
Normal file
141
go-agent/internal/events/catalog.go
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RuleCatalog returns the stable operator-facing metadata currently exposed by
|
||||
// Python ruleops.list_rules. Conditions remain data, so auditors can inspect
|
||||
// what the binary will match without reading Go source or loading eBPF.
|
||||
func RuleCatalog(execRules ExecRuleEngine) []map[string]any {
|
||||
builtinExec := map[int]bool{100001: true, 100002: true, 100003: true, 100004: true}
|
||||
records := make([]map[string]any, 0,
|
||||
len(execRules.Rules)+len(DefaultSyscallRuleEngine().Rules)+len(DefaultHostRuleEngine().Rules))
|
||||
for _, rule := range execRules.Rules {
|
||||
origin := "configured"
|
||||
if builtinExec[rule.SID] {
|
||||
origin = "builtin"
|
||||
}
|
||||
conditions := map[string]any{}
|
||||
if len(rule.PathPrefixes) > 0 {
|
||||
conditions["path_prefixes"] = append([]string(nil), rule.PathPrefixes...)
|
||||
}
|
||||
if len(rule.ExecComms) > 0 {
|
||||
conditions["exec_comm"] = sortedStringKeys(rule.ExecComms)
|
||||
}
|
||||
if len(rule.ParentComms) > 0 {
|
||||
conditions["parent_comm"] = sortedStringKeys(rule.ParentComms)
|
||||
}
|
||||
if rule.ArgvRegex != "" {
|
||||
conditions["argv_regex"] = rule.ArgvRegex
|
||||
}
|
||||
if len(rule.ParentExclude) > 0 {
|
||||
conditions["parent_exclude"] = sortedStringKeys(rule.ParentExclude)
|
||||
}
|
||||
records = append(records, map[string]any{
|
||||
"sid": rule.SID, "event": "exec", "origin": origin,
|
||||
"severity": rule.Severity, "classtype": rule.Classtype,
|
||||
"signature": "exec_rule." + rule.Classtype,
|
||||
"msg": rule.Message, "conditions": conditions,
|
||||
})
|
||||
}
|
||||
for _, rule := range DefaultSyscallRuleEngine().Rules {
|
||||
records = append(records, map[string]any{
|
||||
"sid": rule.SID, "event": "syscall", "origin": "builtin",
|
||||
"severity": rule.Severity, "classtype": rule.Classtype,
|
||||
"signature": "syscall_rule." + rule.Classtype,
|
||||
"msg": rule.Message,
|
||||
"conditions": map[string]any{
|
||||
"syscalls": sortedStringKeys(rule.Syscalls),
|
||||
"predicate": "built-in predicate",
|
||||
},
|
||||
})
|
||||
}
|
||||
for _, rule := range DefaultHostRuleEngine().Rules {
|
||||
conditions := map[string]any{"events": sortedStringKeys(rule.Events)}
|
||||
if len(rule.Comms) > 0 {
|
||||
conditions["comm"] = sortedStringKeys(rule.Comms)
|
||||
}
|
||||
if len(rule.ParentComms) > 0 {
|
||||
conditions["parent_comm"] = sortedStringKeys(rule.ParentComms)
|
||||
}
|
||||
if rule.PeerPublic != nil {
|
||||
conditions["peer_public"] = *rule.PeerPublic
|
||||
}
|
||||
if len(rule.PeerPorts) > 0 {
|
||||
conditions["peer_ports"] = sortedIntKeys(rule.PeerPorts)
|
||||
}
|
||||
if len(rule.PeerPortExclude) > 0 {
|
||||
conditions["peer_port_exclude"] = sortedIntKeys(rule.PeerPortExclude)
|
||||
}
|
||||
if len(rule.LocalPorts) > 0 {
|
||||
conditions["local_ports"] = sortedIntKeys(rule.LocalPorts)
|
||||
}
|
||||
if len(rule.LocalPortExclude) > 0 {
|
||||
conditions["local_port_exclude"] = sortedIntKeys(rule.LocalPortExclude)
|
||||
}
|
||||
if len(rule.PathPrefixes) > 0 {
|
||||
conditions["path_prefixes"] = append([]string(nil), rule.PathPrefixes...)
|
||||
}
|
||||
if len(rule.TargetUIDs) > 0 {
|
||||
conditions["target_uids"] = sortedIntKeys(rule.TargetUIDs)
|
||||
}
|
||||
if len(rule.TargetGIDs) > 0 {
|
||||
conditions["target_gids"] = sortedIntKeys(rule.TargetGIDs)
|
||||
}
|
||||
if len(rule.CapabilitiesAny) > 0 {
|
||||
conditions["capabilities_any"] = sortedStringKeys(rule.CapabilitiesAny)
|
||||
}
|
||||
if len(rule.ModuleNames) > 0 {
|
||||
conditions["module_names"] = sortedStringKeys(rule.ModuleNames)
|
||||
}
|
||||
if rule.ArgvRegex != "" {
|
||||
conditions["argv_regex"] = rule.ArgvRegex
|
||||
}
|
||||
eventTypes := sortedStringKeys(rule.Events)
|
||||
records = append(records, map[string]any{
|
||||
"sid": rule.SID, "event": strings.Join(eventTypes, ","), "origin": "builtin",
|
||||
"severity": rule.Severity, "classtype": rule.Classtype,
|
||||
"signature": "host_rule." + rule.Classtype,
|
||||
"msg": rule.Message, "conditions": conditions,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(records, func(i, j int) bool {
|
||||
leftSID, rightSID := records[i]["sid"].(int), records[j]["sid"].(int)
|
||||
if leftSID != rightSID {
|
||||
return leftSID < rightSID
|
||||
}
|
||||
return records[i]["event"].(string) < records[j]["event"].(string)
|
||||
})
|
||||
return records
|
||||
}
|
||||
|
||||
func FindRule(records []map[string]any, sid int) map[string]any {
|
||||
for _, record := range records {
|
||||
if record["sid"].(int) == sid {
|
||||
return record
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortedStringKeys(values map[string]bool) []string {
|
||||
result := make([]string, 0, len(values))
|
||||
for value := range values {
|
||||
result = append(result, value)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
func sortedIntKeys(values map[int]bool) []int {
|
||||
result := make([]int, 0, len(values))
|
||||
for value := range values {
|
||||
result = append(result, value)
|
||||
}
|
||||
sort.Ints(result)
|
||||
return result
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue