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
|
EXEEXT=.exe
|
||||||
endif
|
endif
|
||||||
|
|
||||||
next_version := $(shell cat build_version.txt)
|
next_version := $(file < build_version.txt)
|
||||||
tag := $(shell git describe --exact-match --tags 2>/dev/null)
|
tag := $(shell git describe --exact-match --tags 2>/dev/null)
|
||||||
|
|
||||||
branch := $(shell git rev-parse --abbrev-ref HEAD)
|
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:
|
// More info on schema, if there will be need to add more:
|
||||||
// https://docs.microsoft.com/en-us/windows/win32/wes/eventschema-elements
|
// https://docs.microsoft.com/en-us/windows/win32/wes/eventschema-elements
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Source Provider `xml:"System>Provider"`
|
Source Provider `xml:"System>Provider"`
|
||||||
EventID int `xml:"System>EventID"`
|
EventID int `xml:"System>EventID"`
|
||||||
Version int `xml:"System>Version"`
|
Version int `xml:"System>Version"`
|
||||||
Level int `xml:"System>Level"`
|
Level int `xml:"System>Level"`
|
||||||
Task int `xml:"System>Task"`
|
Task int `xml:"System>Task"`
|
||||||
Opcode int `xml:"System>Opcode"`
|
Opcode int `xml:"System>Opcode"`
|
||||||
Keywords string `xml:"System>Keywords"`
|
Keywords string `xml:"System>Keywords"`
|
||||||
TimeCreated TimeCreated `xml:"System>TimeCreated"`
|
TimeCreated TimeCreated `xml:"System>TimeCreated"`
|
||||||
EventRecordID int `xml:"System>EventRecordID"`
|
EventRecordID int `xml:"System>EventRecordID"`
|
||||||
Correlation Correlation `xml:"System>Correlation"`
|
Correlation Correlation `xml:"System>Correlation"`
|
||||||
Execution Execution `xml:"System>Execution"`
|
Execution Execution `xml:"System>Execution"`
|
||||||
Channel string `xml:"System>Channel"`
|
Channel string `xml:"System>Channel"`
|
||||||
Computer string `xml:"System>Computer"`
|
Computer string `xml:"System>Computer"`
|
||||||
Security Security `xml:"System>Security"`
|
Security Security `xml:"System>Security"`
|
||||||
UserData UserData `xml:"UserData"`
|
UserData UserData `xml:"UserData"`
|
||||||
EventData EventData `xml:"EventData"`
|
EventData EventData `xml:"EventData"`
|
||||||
Message string
|
RenderingInfo *RenderingInfo `xml:"RenderingInfo"`
|
||||||
LevelText string
|
|
||||||
TaskText string
|
Message string
|
||||||
OpcodeText string
|
LevelText string
|
||||||
|
TaskText string
|
||||||
|
OpcodeText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserData Application-provided XML data
|
// UserData Application-provided XML data
|
||||||
|
|
@ -69,3 +71,15 @@ type Security struct {
|
||||||
type TimeCreated struct {
|
type TimeCreated struct {
|
||||||
SystemTime string `xml:"SystemTime,attr"`
|
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 bufferSize = 1 << 14
|
||||||
|
|
||||||
var description = "Input plugin to collect Windows Event Log messages"
|
|
||||||
|
|
||||||
func (*WinEventLog) SampleConfig() string {
|
func (*WinEventLog) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
}
|
}
|
||||||
|
|
@ -61,7 +59,7 @@ func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
|
||||||
if w.subscription == 0 {
|
if w.subscription == 0 {
|
||||||
w.subscription, err = w.evtSubscribe(w.EventlogName, w.Query)
|
w.subscription, err = w.evtSubscribe(w.EventlogName, w.Query)
|
||||||
if err != nil {
|
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)
|
w.Log.Debug("Subscription handle id:", w.subscription)
|
||||||
|
|
@ -74,7 +72,7 @@ loop:
|
||||||
case err == ERROR_NO_MORE_ITEMS:
|
case err == ERROR_NO_MORE_ITEMS:
|
||||||
break loop
|
break loop
|
||||||
case err != nil:
|
case err != nil:
|
||||||
w.Log.Error("Error getting events:", err.Error())
|
w.Log.Errorf("Error getting events: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +303,6 @@ func (w *WinEventLog) fetchEvents(subsHandle EvtHandle) ([]Event, error) {
|
||||||
if eventHandle != 0 {
|
if eventHandle != 0 {
|
||||||
event, err := w.renderEvent(eventHandle)
|
event, err := w.renderEvent(eventHandle)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// w.Log.Debugf("Got event: %v", event)
|
|
||||||
events = append(events, event)
|
events = append(events, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -333,6 +330,7 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return event, err
|
return event, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = xml.Unmarshal([]byte(eventXML), &event)
|
err = xml.Unmarshal([]byte(eventXML), &event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// We can return event without most text values,
|
// We can return event without most text values,
|
||||||
|
|
@ -341,6 +339,19 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
||||||
return event, nil
|
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)
|
publisherHandle, err := openPublisherMetadata(0, event.Source.Name, w.Locale)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return event, nil
|
return event, nil
|
||||||
|
|
@ -376,6 +387,32 @@ func (w *WinEventLog) renderEvent(eventHandle EvtHandle) (Event, error) {
|
||||||
return event, nil
|
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(
|
func formatEventString(
|
||||||
messageFlag EvtFormatMessageFlag,
|
messageFlag EvtFormatMessageFlag,
|
||||||
eventHandle EvtHandle,
|
eventHandle EvtHandle,
|
||||||
|
|
@ -388,6 +425,11 @@ func formatEventString(
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle empty elements
|
||||||
|
if bufferUsed < 1 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
bufferUsed *= 2
|
bufferUsed *= 2
|
||||||
buffer := make([]byte, bufferUsed)
|
buffer := make([]byte, bufferUsed)
|
||||||
bufferUsed = 0
|
bufferUsed = 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue