fix(inputs.win_eventlog): Handle remote events more robustly. (#12375)
This commit is contained in:
parent
d476018705
commit
7b5b342432
2
Makefile
2
Makefile
|
|
@ -2,7 +2,7 @@ ifneq (,$(filter $(OS),Windows_NT Windows))
|
|||
EXEEXT=.exe
|
||||
endif
|
||||
|
||||
next_version := $(shell cat build_version.txt)
|
||||
next_version := $(file < build_version.txt)
|
||||
tag := $(shell git describe --exact-match --tags 2>/dev/null)
|
||||
|
||||
branch := $(shell git rev-parse --abbrev-ref HEAD)
|
||||
|
|
|
|||
|
|
@ -10,26 +10,28 @@ package win_eventlog
|
|||
// More info on schema, if there will be need to add more:
|
||||
// https://docs.microsoft.com/en-us/windows/win32/wes/eventschema-elements
|
||||
type Event struct {
|
||||
Source Provider `xml:"System>Provider"`
|
||||
EventID int `xml:"System>EventID"`
|
||||
Version int `xml:"System>Version"`
|
||||
Level int `xml:"System>Level"`
|
||||
Task int `xml:"System>Task"`
|
||||
Opcode int `xml:"System>Opcode"`
|
||||
Keywords string `xml:"System>Keywords"`
|
||||
TimeCreated TimeCreated `xml:"System>TimeCreated"`
|
||||
EventRecordID int `xml:"System>EventRecordID"`
|
||||
Correlation Correlation `xml:"System>Correlation"`
|
||||
Execution Execution `xml:"System>Execution"`
|
||||
Channel string `xml:"System>Channel"`
|
||||
Computer string `xml:"System>Computer"`
|
||||
Security Security `xml:"System>Security"`
|
||||
UserData UserData `xml:"UserData"`
|
||||
EventData EventData `xml:"EventData"`
|
||||
Message string
|
||||
LevelText string
|
||||
TaskText string
|
||||
OpcodeText string
|
||||
Source Provider `xml:"System>Provider"`
|
||||
EventID int `xml:"System>EventID"`
|
||||
Version int `xml:"System>Version"`
|
||||
Level int `xml:"System>Level"`
|
||||
Task int `xml:"System>Task"`
|
||||
Opcode int `xml:"System>Opcode"`
|
||||
Keywords string `xml:"System>Keywords"`
|
||||
TimeCreated TimeCreated `xml:"System>TimeCreated"`
|
||||
EventRecordID int `xml:"System>EventRecordID"`
|
||||
Correlation Correlation `xml:"System>Correlation"`
|
||||
Execution Execution `xml:"System>Execution"`
|
||||
Channel string `xml:"System>Channel"`
|
||||
Computer string `xml:"System>Computer"`
|
||||
Security Security `xml:"System>Security"`
|
||||
UserData UserData `xml:"UserData"`
|
||||
EventData EventData `xml:"EventData"`
|
||||
RenderingInfo *RenderingInfo `xml:"RenderingInfo"`
|
||||
|
||||
Message string
|
||||
LevelText string
|
||||
TaskText string
|
||||
OpcodeText string
|
||||
}
|
||||
|
||||
// UserData Application-provided XML data
|
||||
|
|
@ -69,3 +71,15 @@ type Security struct {
|
|||
type TimeCreated struct {
|
||||
SystemTime string `xml:"SystemTime,attr"`
|
||||
}
|
||||
|
||||
// RenderingInfo is provided for events forwarded by Windows Event Collector
|
||||
// see https://learn.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtformatmessage#parameters
|
||||
type RenderingInfo struct {
|
||||
Message string `xml:"Message"`
|
||||
Level string `xml:"Level"`
|
||||
Task string `xml:"Task"`
|
||||
Opcode string `xml:"Opcode"`
|
||||
Channel string `xml:"Channel"`
|
||||
Provider string `xml:"Provider"`
|
||||
Keywords []string `xml:"Keywords>Keyword"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ type WinEventLog struct {
|
|||
|
||||
var bufferSize = 1 << 14
|
||||
|
||||
var description = "Input plugin to collect Windows Event Log messages"
|
||||
|
||||
func (*WinEventLog) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
|
@ -61,7 +59,7 @@ func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
|
|||
if w.subscription == 0 {
|
||||
w.subscription, err = w.evtSubscribe(w.EventlogName, w.Query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Windows Event Log subscription error: %v", err.Error())
|
||||
return fmt.Errorf("subscription of Windows Event Log failed: %w", err)
|
||||
}
|
||||
}
|
||||
w.Log.Debug("Subscription handle id:", w.subscription)
|
||||
|
|
@ -74,7 +72,7 @@ loop:
|
|||
case err == ERROR_NO_MORE_ITEMS:
|
||||
break loop
|
||||
case err != nil:
|
||||
w.Log.Error("Error getting events:", err.Error())
|
||||
w.Log.Errorf("Error getting events: %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -305,7 +303,6 @@ func (w *WinEventLog) fetchEvents(subsHandle EvtHandle) ([]Event, error) {
|
|||
if eventHandle != 0 {
|
||||
event, err := w.renderEvent(eventHandle)
|
||||
if err == nil {
|
||||
// w.Log.Debugf("Got event: %v", event)
|
||||
events = append(events, event)
|
||||
}
|
||||
}
|
||||
|
|
@ -333,6 +330,7 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
|||
if err != nil {
|
||||
return event, err
|
||||
}
|
||||
|
||||
err = xml.Unmarshal([]byte(eventXML), &event)
|
||||
if err != nil {
|
||||
// We can return event without most text values,
|
||||
|
|
@ -341,6 +339,19 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
|||
return event, nil
|
||||
}
|
||||
|
||||
// Do resolve local messages the usual way, while using built-in information for events forwarded by WEC.
|
||||
// This is a safety measure as the underlying Windows-internal EvtFormatMessage might segfault in cases
|
||||
// where the publisher (i.e. the remote machine which forwared the event) is unavailable e.g. due to
|
||||
// a reboot. See https://github.com/influxdata/telegraf/issues/12328 for the full story.
|
||||
if event.RenderingInfo == nil {
|
||||
return w.renderLocalMessage(event, eventHandle)
|
||||
}
|
||||
|
||||
// We got 'RenderInfo' elements, so try to apply them in the following function
|
||||
return w.renderRemoteMessage(event)
|
||||
}
|
||||
|
||||
func (w *WinEventLog) renderLocalMessage(event Event, eventHandle EvtHandle) (Event, error) {
|
||||
publisherHandle, err := openPublisherMetadata(0, event.Source.Name, w.Locale)
|
||||
if err != nil {
|
||||
return event, nil
|
||||
|
|
@ -376,6 +387,32 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
|||
return event, nil
|
||||
}
|
||||
|
||||
func (w *WinEventLog) renderRemoteMessage(event Event) (Event, error) {
|
||||
// Populating text values from RenderingInfo part of the XML
|
||||
if len(event.RenderingInfo.Keywords) > 0 {
|
||||
event.Keywords = strings.Join(event.RenderingInfo.Keywords, ",")
|
||||
}
|
||||
if event.RenderingInfo.Message != "" {
|
||||
message := event.RenderingInfo.Message
|
||||
if w.OnlyFirstLineOfMessage {
|
||||
scanner := bufio.NewScanner(strings.NewReader(message))
|
||||
scanner.Scan()
|
||||
message = scanner.Text()
|
||||
}
|
||||
event.Message = message
|
||||
}
|
||||
if event.RenderingInfo.Level != "" {
|
||||
event.LevelText = event.RenderingInfo.Level
|
||||
}
|
||||
if event.RenderingInfo.Task != "" {
|
||||
event.TaskText = event.RenderingInfo.Task
|
||||
}
|
||||
if event.RenderingInfo.Opcode != "" {
|
||||
event.OpcodeText = event.RenderingInfo.Opcode
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func formatEventString(
|
||||
messageFlag EvtFormatMessageFlag,
|
||||
eventHandle EvtHandle,
|
||||
|
|
@ -388,6 +425,11 @@ func formatEventString(
|
|||
return "", err
|
||||
}
|
||||
|
||||
// Handle empty elements
|
||||
if bufferUsed < 1 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
bufferUsed *= 2
|
||||
buffer := make([]byte, bufferUsed)
|
||||
bufferUsed = 0
|
||||
|
|
|
|||
Loading…
Reference in New Issue