fix(inputs.win_eventlog): Handle XML data fields' filtering the same way as event fields (#16008)

This commit is contained in:
Sven Rebhan 2024-10-17 16:30:13 +02:00 committed by GitHub
parent 0abd184087
commit aaae84b67b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 79 deletions

View File

@ -13,7 +13,6 @@ import (
"encoding/xml" "encoding/xml"
"errors" "errors"
"fmt" "fmt"
"path/filepath"
"reflect" "reflect"
"strings" "strings"
"syscall" "syscall"
@ -22,6 +21,7 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/filter"
"github.com/influxdata/telegraf/plugins/inputs" "github.com/influxdata/telegraf/plugins/inputs"
) )
@ -49,6 +49,9 @@ type WinEventLog struct {
subscription EvtHandle subscription EvtHandle
subscriptionFlag EvtSubscribeFlag subscriptionFlag EvtSubscribeFlag
bookmark EvtHandle bookmark EvtHandle
tagFilter filter.Filter
fieldFilter filter.Filter
fieldEmptyFilter filter.Filter
} }
const bufferSize = 1 << 14 const bufferSize = 1 << 14
@ -78,6 +81,18 @@ func (w *WinEventLog) Init() error {
} }
w.bookmark = bookmark w.bookmark = bookmark
if w.tagFilter, err = filter.Compile(w.EventTags); err != nil {
return fmt.Errorf("creating tag filter failed: %w", err)
}
if w.fieldFilter, err = filter.NewIncludeExcludeFilter(w.EventFields, w.ExcludeFields); err != nil {
return fmt.Errorf("creating field filter failed: %w", err)
}
if w.fieldEmptyFilter, err = filter.Compile(w.ExcludeEmpty); err != nil {
return fmt.Errorf("creating empty fields filter failed: %w", err)
}
return nil return nil
} }
@ -204,7 +219,6 @@ func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
} }
} }
} }
default:
} }
if should, where := w.shouldProcessField(fieldName); should { if should, where := w.shouldProcessField(fieldName); should {
if where == "tags" { if where == "tags" {
@ -249,7 +263,13 @@ func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
} }
uniqueXMLFields := UniqueFieldNames(xmlFields, fieldsUsage, w.Separator) uniqueXMLFields := UniqueFieldNames(xmlFields, fieldsUsage, w.Separator)
for _, xmlField := range uniqueXMLFields { for _, xmlField := range uniqueXMLFields {
if !w.shouldExclude(xmlField.Name) { should, where := w.shouldProcessField(xmlField.Name)
if !should {
continue
}
if where == "tags" {
tags[xmlField.Name] = xmlField.Value
} else {
fields[xmlField.Name] = xmlField.Value fields[xmlField.Name] = xmlField.Value
} }
} }
@ -262,48 +282,32 @@ func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
return nil return nil
} }
func (w *WinEventLog) shouldExclude(field string) (should bool) {
for _, excludePattern := range w.ExcludeFields {
// Check if field name matches excluded list
if matched, err := filepath.Match(excludePattern, field); matched && err == nil {
return true
}
}
return false
}
func (w *WinEventLog) shouldProcessField(field string) (should bool, list string) { func (w *WinEventLog) shouldProcessField(field string) (should bool, list string) {
for _, pattern := range w.EventTags { if w.tagFilter != nil && w.tagFilter.Match(field) {
if matched, err := filepath.Match(pattern, field); matched && err == nil { return true, "tags"
// Tags are not excluded
return true, "tags"
}
} }
for _, pattern := range w.EventFields { if w.fieldFilter.Match(field) {
if matched, err := filepath.Match(pattern, field); matched && err == nil { return true, "fields"
if w.shouldExclude(field) {
return false, "excluded"
}
return true, "fields"
}
} }
return false, "excluded" return false, "excluded"
} }
func (w *WinEventLog) shouldExcludeEmptyField(field string, fieldType string, fieldValue interface{}) (should bool) { func (w *WinEventLog) shouldExcludeEmptyField(field string, fieldType string, fieldValue interface{}) (should bool) {
for _, pattern := range w.ExcludeEmpty { if w.fieldEmptyFilter == nil || !w.fieldEmptyFilter.Match(field) {
if matched, err := filepath.Match(pattern, field); matched && err == nil { return false
switch fieldType {
case "string":
return len(fieldValue.(string)) < 1
case "int":
return fieldValue.(int) == 0
case "uint32":
return fieldValue.(uint32) == 0
}
}
} }
switch fieldType {
case "string":
return len(fieldValue.(string)) < 1
case "int":
return fieldValue.(int) == 0
case "uint32":
return fieldValue.(uint32) == 0
}
return false return false
} }
@ -568,7 +572,6 @@ func init() {
OnlyFirstLineOfMessage: true, OnlyFirstLineOfMessage: true,
TimeStampFromEvent: true, TimeStampFromEvent: true,
EventTags: []string{"Source", "EventID", "Level", "LevelText", "Keywords", "Channel", "Computer"}, EventTags: []string{"Source", "EventID", "Level", "LevelText", "Keywords", "Channel", "Computer"},
EventFields: []string{"*"},
ExcludeEmpty: []string{"Task", "Opcode", "*ActivityID", "UserID"}, ExcludeEmpty: []string{"Task", "Opcode", "*ActivityID", "UserID"},
} }
}) })

View File

@ -7,6 +7,8 @@ package win_eventlog
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
) )
func TestWinEventLog_shouldExcludeEmptyField(t *testing.T) { func TestWinEventLog_shouldExcludeEmptyField(t *testing.T) {
@ -16,59 +18,59 @@ func TestWinEventLog_shouldExcludeEmptyField(t *testing.T) {
fieldValue interface{} fieldValue interface{}
} }
tests := []struct { tests := []struct {
name string name string
w *WinEventLog w *WinEventLog
args args args args
wantShould bool expected bool
}{ }{
{ {
name: "Not in list", name: "Not in list",
args: args{field: "qq", fieldType: "string", fieldValue: ""}, args: args{field: "qq", fieldType: "string", fieldValue: ""},
wantShould: false, expected: false,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Empty string", name: "Empty string",
args: args{field: "test", fieldType: "string", fieldValue: ""}, args: args{field: "test", fieldType: "string", fieldValue: ""},
wantShould: true, expected: true,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Non-empty string", name: "Non-empty string",
args: args{field: "test", fieldType: "string", fieldValue: "qq"}, args: args{field: "test", fieldType: "string", fieldValue: "qq"},
wantShould: false, expected: false,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Zero int", name: "Zero int",
args: args{field: "test", fieldType: "int", fieldValue: int(0)}, args: args{field: "test", fieldType: "int", fieldValue: int(0)},
wantShould: true, expected: true,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Non-zero int", name: "Non-zero int",
args: args{field: "test", fieldType: "int", fieldValue: int(-1)}, args: args{field: "test", fieldType: "int", fieldValue: int(-1)},
wantShould: false, expected: false,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Zero uint32", name: "Zero uint32",
args: args{field: "test", fieldType: "uint32", fieldValue: uint32(0)}, args: args{field: "test", fieldType: "uint32", fieldValue: uint32(0)},
wantShould: true, expected: true,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
{ {
name: "Non-zero uint32", name: "Non-zero uint32",
args: args{field: "test", fieldType: "uint32", fieldValue: uint32(0xc0fefeed)}, args: args{field: "test", fieldType: "uint32", fieldValue: uint32(0xc0fefeed)},
wantShould: false, expected: false,
w: &WinEventLog{ExcludeEmpty: []string{"te*"}}, w: &WinEventLog{ExcludeEmpty: []string{"te*"}},
}, },
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if gotShould := tt.w.shouldExcludeEmptyField(tt.args.field, tt.args.fieldType, tt.args.fieldValue); gotShould != tt.wantShould { require.NoError(t, tt.w.Init())
t.Errorf("WinEventLog.shouldExcludeEmptyField() = %v, want %v", gotShould, tt.wantShould) actual := tt.w.shouldExcludeEmptyField(tt.args.field, tt.args.fieldType, tt.args.fieldValue)
} require.Equal(t, tt.expected, actual)
}) })
} }
} }
@ -125,13 +127,10 @@ func TestWinEventLog_shouldProcessField(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
gotShould, gotList := tt.w.shouldProcessField(tt.args.field) require.NoError(t, tt.w.Init())
if gotShould != tt.wantShould { should, list := tt.w.shouldProcessField(tt.args.field)
t.Errorf("WinEventLog.shouldProcessField() gotShould = %v, want %v", gotShould, tt.wantShould) require.Equal(t, tt.wantShould, should)
} require.Equal(t, tt.wantList, list)
if gotList != tt.wantList {
t.Errorf("WinEventLog.shouldProcessField() gotList = %v, want %v", gotList, tt.wantList)
}
}) })
} }
} }