This commit is contained in:
zxr
2026-04-27 19:26:57 +08:00
parent 01c807b953
commit 694893eea3
26 changed files with 1901 additions and 15 deletions

View File

@@ -24,6 +24,27 @@ type Engine struct {
syslogRules []models.SyslogRule
trapRules []models.TrapRule
shields []models.TrapShield
resourceByIP map[string]resourceRef
resourceByHN map[string]resourceRef
}
type resourceRef struct {
ResourceType string
ResourceID string
ResourceName string
}
func resourceTypePriority(resourceType string) int {
switch strings.ToLower(strings.TrimSpace(resourceType)) {
case "server":
return 3
case "collector":
return 2
case "device":
return 1
default:
return 0
}
}
var Global = &Engine{}
@@ -33,6 +54,7 @@ func (e *Engine) Refresh() error {
var syslog []models.SyslogRule
var trap []models.TrapRule
var shield []models.TrapShield
var mappings []models.ResourceMapping
if err := impl.DBService.Where("enabled = ?", true).Find(&dict).Error; err != nil {
return err
@@ -54,12 +76,51 @@ func (e *Engine) Refresh() error {
if err := impl.DBService.Where("enabled = ?", true).Find(&shield).Error; err != nil {
return err
}
if err := impl.DBService.Where("is_deleted = ?", false).Order("updated_at desc, id desc").Find(&mappings).Error; err != nil {
return err
}
ipMap := make(map[string]resourceRef)
hnMap := make(map[string]resourceRef)
for _, m := range mappings {
ref := resourceRef{
ResourceType: m.ResourceType,
ResourceID: m.ResourceID,
ResourceName: m.ResourceName,
}
var ips []string
if err := json.Unmarshal([]byte(m.IPsJSON), &ips); err == nil {
for _, ip := range ips {
key := strings.TrimSpace(ip)
if key == "" {
continue
}
if cur, exists := ipMap[key]; !exists || resourceTypePriority(ref.ResourceType) > resourceTypePriority(cur.ResourceType) {
ipMap[key] = ref
}
}
}
var hostnames []string
if err := json.Unmarshal([]byte(m.HostnamesJSON), &hostnames); err == nil {
for _, hn := range hostnames {
key := strings.ToLower(strings.TrimSpace(hn))
if key == "" {
continue
}
if cur, exists := hnMap[key]; !exists || resourceTypePriority(ref.ResourceType) > resourceTypePriority(cur.ResourceType) {
hnMap[key] = ref
}
}
}
}
e.mu.Lock()
e.trapDict = dict
e.syslogRules = syslog
e.trapRules = trap
e.shields = shield
e.resourceByIP = ipMap
e.resourceByHN = hnMap
e.mu.Unlock()
return nil
}
@@ -99,14 +160,21 @@ func (e *Engine) HandleSyslog(addr *net.UDPAddr, payload []byte) {
detailBytes, _ := json.Marshal(detailObj)
summary := formatSyslogSummary(parsed)
sev := syslogPriorityToSeverity(parsed.Priority)
ref, method := e.resolveResource(addr.IP.String(), device)
ev := models.LogEvent{
SourceKind: "syslog",
RemoteAddr: addr.String(),
SourceIP: addr.IP.String(),
RawPayload: string(payload),
NormalizedSummary: summary,
NormalizedDetail: string(detailBytes),
DeviceName: device,
ResourceType: ref.ResourceType,
ResourceID: ref.ResourceID,
ResourceName: ref.ResourceName,
MatchMethod: method,
DispatchStatus: "not_applicable",
SeverityCode: sev,
}
@@ -166,8 +234,8 @@ func (e *Engine) HandleSyslog(addr *net.UDPAddr, payload []byte) {
PolicyID: matched.PolicyID,
RawData: rawBytes,
}
if err := forwardAlert(body); err == nil {
_ = impl.DBService.Model(&ev).Update("alert_sent", true).Error
if err := enqueueAlert(ev.ID, body); err == nil {
_ = impl.DBService.Model(&ev).Update("dispatch_status", "pending").Error
}
}
@@ -204,10 +272,7 @@ func trapShielded(e *Engine, addr *net.UDPAddr, trapOID string, pkt *gosnmp.Snmp
if !s.Enabled {
continue
}
if strings.TrimSpace(s.SourceIPCIDR) == "" {
continue
}
if !ipMatchesCIDR(ip, s.SourceIPCIDR) {
if cidr := strings.TrimSpace(s.SourceIPCIDR); cidr != "" && !ipMatchesCIDR(ip, cidr) {
continue
}
if p := strings.TrimSpace(s.OIDPrefix); p != "" && !strings.HasPrefix(normOID(trapOID), normOID(p)) {
@@ -265,14 +330,21 @@ func (e *Engine) HandleTrap(addr *net.UDPAddr, pkt *gosnmp.SnmpPacket) {
}
}
detailBytes, _ := json.Marshal(detailObj)
ref, method := e.resolveResource(addr.IP.String(), addr.IP.String())
ev := models.LogEvent{
SourceKind: "snmp_trap",
RemoteAddr: addr.String(),
SourceIP: addr.IP.String(),
RawPayload: fp,
NormalizedSummary: readable,
NormalizedDetail: string(detailBytes),
DeviceName: addr.IP.String(),
ResourceType: ref.ResourceType,
ResourceID: ref.ResourceID,
ResourceName: ref.ResourceName,
MatchMethod: method,
DispatchStatus: "not_applicable",
SeverityCode: sev,
TrapOID: trapOID,
}
@@ -360,8 +432,8 @@ func (e *Engine) HandleTrap(addr *net.UDPAddr, pkt *gosnmp.SnmpPacket) {
PolicyID: matched.PolicyID,
RawData: rawBytes,
}
if err := forwardAlert(body); err == nil {
_ = impl.DBService.Model(&ev).Update("alert_sent", true).Error
if err := enqueueAlert(ev.ID, body); err == nil {
_ = impl.DBService.Model(&ev).Update("dispatch_status", "pending").Error
}
}
@@ -440,3 +512,18 @@ func firstNonEmpty(a, b string) string {
}
return b
}
func (e *Engine) resolveResource(sourceIP, hostname string) (resourceRef, string) {
e.mu.RLock()
ipMap := e.resourceByIP
hnMap := e.resourceByHN
e.mu.RUnlock()
if ref, ok := ipMap[strings.TrimSpace(sourceIP)]; ok {
return ref, "ip"
}
if ref, ok := hnMap[strings.ToLower(strings.TrimSpace(hostname))]; ok {
return ref, "hostname"
}
return resourceRef{}, "none"
}