From f1c49d1b0dc90c943aab2c38ea49a62763eaf9ef Mon Sep 17 00:00:00 2001
From: Dan Kortschak <90160302+efd6@users.noreply.github.com>
Date: Thu, 31 Mar 2022 09:31:28 +1030
Subject: [PATCH 1/2] winlogbeat: fix event handling for Windows 2022 (#30942)
This fixes failures in event handling on Windows 2022[1] where parts of
events available from the Windows API are not reflected in the events
recovered by winlogbeat[2].
There is unfortunately quite a lot of movement in this change due to the
need to satisfy linter requirements. Beyond those changes, the substantive
changes here are:
1. Addition of new testing infrastructure to allow addition of evtx files
and comparison with there expected XML renderings, and adding some test
cases (shown below).
2. Fixing a buffer length parameter in the call to _EvtFormatMessage in
evtFormatMessage that was the result of a lack of clarity in the API
documentation for that syscall.
3. Fixing a var shadowing decl of the publisher handle EvtHandle in
FormatEventString.
4. Providing a call back for the legacy (non-experimental) API through
wineventlog.Message to allow it to obtain the event message in the case
that the RenderingInfo element is not available via the Windows API.
5. Ensure that keyword, opcode and level are obtained by the non-experimental
API by calling winevent.EnrichRawValuesWithNames in buildRecordFromXML.
This change also required making winevent.Event.OpcodeRaw a pointer to
allow an absent System>Opcode element to be distinquished from the zero,
but present element.
The change also enables testing on Windows 2022.
[1]https://github.com/elastic/beats/issues/30621
[2]https://github.com/elastic/beats/pull/30622#issuecomment-1055477970
New events in testing as rendered by the Event Viewer:
ec1: eventcreate /id 1000 /t error /l application /d "My custom error event for the application log"
-
-
1000
0
2
0
0
0x80000000000000
316
Application
vagrant
-
My custom error event for the application log
ec2: eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace"
-
-
999
0
2
0
0
0x80000000000000
317
Application
vagrant
-
Winword event 999 happened due to low diskspace
ec3: eventcreate /id 5 /t error /l system /d "Catastrophe!"
-
-
5
0
2
0
0
0x80000000000000
1413
System
vagrant
-
Catastrophe!
ec4: eventcreate /id 5 /t error /l system /so Backup /d "Backup failure"
-
-
5
0
2
0
0
0x80000000000000
1414
System
vagrant
-
Backup failure
Co-authored-by: Andrew Kroh
(cherry picked from commit 34bdc3d46852532c9348591e0411e5b763b49663)
# Conflicts:
# winlogbeat/beater/winlogbeat.go
# winlogbeat/eventlog/wineventlog.go
# winlogbeat/eventlog/wineventlog_experimental.go
# winlogbeat/sys/wineventlog/wineventlog_windows.go
# x-pack/winlogbeat/Jenkinsfile.yml
---
CHANGELOG.next.asciidoc | 2 +
winlogbeat/Jenkinsfile.yml | 5 +
winlogbeat/beater/winlogbeat.go | 4 +
winlogbeat/eventlog/wineventlog.go | 49 ++++-
.../eventlog/wineventlog_experimental.go | 42 +++-
winlogbeat/eventlog/wineventlog_test.go | 23 ++-
winlogbeat/sys/winevent/event.go | 30 ++-
winlogbeat/sys/winevent/event_test.go | 4 +-
winlogbeat/sys/wineventlog/format_message.go | 27 +--
winlogbeat/sys/wineventlog/query_test.go | 12 +-
winlogbeat/sys/wineventlog/renderer.go | 41 ++--
winlogbeat/sys/wineventlog/renderer_test.go | 9 +-
.../application-windows-error-reporting.xml | 18 ++
winlogbeat/sys/wineventlog/testdata/ec1.evtx | Bin 0 -> 69632 bytes
winlogbeat/sys/wineventlog/testdata/ec1.xml | 1 +
winlogbeat/sys/wineventlog/testdata/ec2.evtx | Bin 0 -> 69632 bytes
winlogbeat/sys/wineventlog/testdata/ec2.xml | 1 +
winlogbeat/sys/wineventlog/testdata/ec3.evtx | Bin 0 -> 69632 bytes
winlogbeat/sys/wineventlog/testdata/ec3.xml | 1 +
.../sys/wineventlog/testdata/ec3and4.evtx | Bin 0 -> 69632 bytes
.../sys/wineventlog/testdata/ec3and4.xml | 2 +
winlogbeat/sys/wineventlog/testdata/ec4.evtx | Bin 0 -> 69632 bytes
winlogbeat/sys/wineventlog/testdata/ec4.xml | 1 +
.../wineventlog/testdata/experimental.evtx | Bin 0 -> 69632 bytes
.../sys/wineventlog/testdata/experimental.xml | 5 +
.../sys/wineventlog/testdata/original.evtx | Bin 0 -> 69632 bytes
.../sys/wineventlog/testdata/original.xml | 5 +
.../sys/wineventlog/testdata/sysmon-9.01.xml | 32 +++
.../sys/wineventlog/wineventlog_windows.go | 70 +++++--
.../wineventlog/wineventlog_windows_test.go | 192 +++++++++++++-----
x-pack/winlogbeat/Jenkinsfile.yml | 10 +
31 files changed, 428 insertions(+), 158 deletions(-)
create mode 100644 winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec1.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec1.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec2.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec2.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3and4.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec3and4.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec4.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/ec4.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/experimental.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/experimental.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/original.evtx
create mode 100644 winlogbeat/sys/wineventlog/testdata/original.xml
create mode 100644 winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml
diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc
index d0275fb486e..83425f1dac3 100644
--- a/CHANGELOG.next.asciidoc
+++ b/CHANGELOG.next.asciidoc
@@ -68,6 +68,8 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...main[Check the HEAD dif
*Winlogbeat*
+- Fix evtx parsing failures. {issue}30621[30621] {pull}30942[30942]
+
*Functionbeat*
diff --git a/winlogbeat/Jenkinsfile.yml b/winlogbeat/Jenkinsfile.yml
index eece9aaa2c3..db43d1ed027 100644
--- a/winlogbeat/Jenkinsfile.yml
+++ b/winlogbeat/Jenkinsfile.yml
@@ -24,6 +24,11 @@ stages:
crosscompile:
make: "make -C winlogbeat crosscompile"
stage: mandatory
+ windows-2022:
+ mage: "mage build unitTest"
+ platforms: ## override default labels in this specific stage.
+ - "windows-2022"
+ stage: mandatory
windows-2019:
mage: "mage build unitTest"
platforms: ## override default labels in this specific stage.
diff --git a/winlogbeat/beater/winlogbeat.go b/winlogbeat/beater/winlogbeat.go
index ec7ebf90ef6..fe9e5ffe6bc 100644
--- a/winlogbeat/beater/winlogbeat.go
+++ b/winlogbeat/beater/winlogbeat.go
@@ -98,7 +98,11 @@ func (eb *Winlogbeat) init(b *beat.Beat) error {
if err != nil {
return fmt.Errorf("failed to create new event log: %w", err)
}
+<<<<<<< HEAD
eb.log.Debugf("Initialized EventLog]", eventLog.Name())
+=======
+ eb.log.Debugf("initialized WinEventLog[%s]", eventLog.Name())
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
logger, err := newEventLogger(b.Info, eventLog, config, eb.log)
if err != nil {
diff --git a/winlogbeat/eventlog/wineventlog.go b/winlogbeat/eventlog/wineventlog.go
index 7ec830f220a..9a9f52627fc 100644
--- a/winlogbeat/eventlog/wineventlog.go
+++ b/winlogbeat/eventlog/wineventlog.go
@@ -55,6 +55,15 @@ const (
eventLoggingAPIName = "eventlogging"
)
+func init() {
+ // Register wineventlog API if it is available.
+ available, _ := win.IsAvailable()
+ if available {
+ Register(winEventLogAPIName, 0, newWinEventLog, win.Channels)
+ Register(eventLoggingAPIName, 1, newEventLogging, win.Channels)
+ }
+}
+
type winEventLogConfig struct {
ConfigCommon `config:",inline"`
BatchReadSize int `config:"batch_read_size"` // Maximum number of events that Read will return.
@@ -160,6 +169,7 @@ type winEventLog struct {
lastRead checkpoint.EventLogState // Record number of the last read event.
render func(event win.EvtHandle, out io.Writer) error // Function for rendering the event to XML.
+ message func(event win.EvtHandle) (string, error) // Message fallback function.
renderBuf []byte // Buffer used for rendering event.
outputBuf *sys.ByteBuffer // Buffer for receiving XML
cache *messageFilesCache // Cached mapping of source name to event message file handles.
@@ -198,7 +208,11 @@ func (l *winEventLog) openChannel(bookmark win.EvtHandle) error {
if err != nil {
return nil
}
+<<<<<<< HEAD
defer windows.CloseHandle(signalEvent)
+=======
+ defer windows.CloseHandle(signalEvent) //nolint:errcheck // This is just a resource release.
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
var flags win.EvtSubscribeFlag
if bookmark > 0 {
@@ -273,11 +287,20 @@ func (l *winEventLog) Read() ([]Record, error) {
}()
detailf("%s EventHandles returned %d handles", l.logPrefix, len(handles))
+<<<<<<< HEAD
var records []Record
for _, h := range handles {
l.outputBuf.Reset()
err := l.render(h, l.outputBuf)
if bufErr, ok := err.(sys.InsufficientBufferError); ok {
+=======
+ var records []Record //nolint:prealloc // This linter gives bad advice and does not take into account conditionals in loops.
+ for _, h := range handles {
+ l.outputBuf.Reset()
+ err := l.render(h, l.outputBuf)
+ var bufErr sys.InsufficientBufferError
+ if errors.As(err, &bufErr) {
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
detailf("%s Increasing render buffer size to %d", l.logPrefix,
bufErr.RequiredSize)
l.renderBuf = make([]byte, bufErr.RequiredSize)
@@ -299,6 +322,12 @@ func (l *winEventLog) Read() ([]Record, error) {
if r.Offset.Bookmark, err = l.createBookmarkFromEvent(h); err != nil {
logp.Warn("%s failed creating bookmark: %v", l.logPrefix, err)
}
+ if r.Message == "" {
+ r.Message, err = l.message(h)
+ if err != nil {
+ logp.Err("%s error salvaging message: %v", l.logPrefix, err)
+ }
+ }
records = append(records, r)
l.lastRead = r.Offset
}
@@ -314,7 +343,11 @@ func (l *winEventLog) Close() error {
func (l *winEventLog) eventHandles(maxRead int) ([]win.EvtHandle, int, error) {
handles, err := win.EventHandles(l.subscription, maxRead)
+<<<<<<< HEAD
switch err {
+=======
+ switch err { //nolint:errorlint // This is an errno or nil.
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
case nil:
if l.maxRead > maxRead {
debugf("%s Recovered from RPC_S_INVALID_BOUND error (errno 1734) "+
@@ -366,13 +399,15 @@ func (l *winEventLog) buildRecordFromXML(x []byte, recoveredErr error) (Record,
e.RenderErr = append(e.RenderErr, recoveredErr.Error())
}
+ // Get basic string values for raw fields.
+ winevent.EnrichRawValuesWithNames(nil, &e)
if e.Level == "" {
// Fallback on LevelRaw if the Level is not set in the RenderingInfo.
e.Level = win.EventLevel(e.LevelRaw).String()
}
if logp.IsDebug(detailSelector) {
- detailf("%s XML=%s Event=%+v", l.logPrefix, string(x), e)
+ detailf("%s XML=%s Event=%+v", l.logPrefix, x, e)
}
r := Record{
@@ -474,6 +509,9 @@ func newWinEventLog(options *common.Config) (EventLog, error) {
return win.RenderEvent(event, c.EventLanguage, l.renderBuf, l.cache.get, out)
}
}
+ l.message = func(event win.EvtHandle) (string, error) {
+ return win.Message(event, l.renderBuf, l.cache.get)
+ }
return l, nil
}
@@ -488,12 +526,3 @@ func (l *winEventLog) createBookmarkFromEvent(evtHandle win.EvtHandle) (string,
win.Close(bmHandle)
return string(l.outputBuf.Bytes()), err
}
-
-func init() {
- // Register wineventlog API if it is available.
- available, _ := win.IsAvailable()
- if available {
- Register(winEventLogAPIName, 0, newWinEventLog, win.Channels)
- Register(eventLoggingAPIName, 1, newEventLogging, win.Channels)
- }
-}
diff --git a/winlogbeat/eventlog/wineventlog_experimental.go b/winlogbeat/eventlog/wineventlog_experimental.go
index 87eb4b32802..1871501bca2 100644
--- a/winlogbeat/eventlog/wineventlog_experimental.go
+++ b/winlogbeat/eventlog/wineventlog_experimental.go
@@ -21,6 +21,10 @@
package eventlog
import (
+<<<<<<< HEAD
+=======
+ "fmt"
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
"io"
"os"
"path/filepath"
@@ -42,6 +46,14 @@ const (
winEventLogExpAPIName = "wineventlog-experimental"
)
+func init() {
+ // Register wineventlog API if it is available.
+ available, _ := win.IsAvailable()
+ if available {
+ Register(winEventLogExpAPIName, 10, newWinEventLogExp, win.Channels)
+ }
+}
+
// winEventLogExp implements the EventLog interface for reading from the Windows
// Event Log API.
type winEventLogExp struct {
@@ -99,7 +111,11 @@ func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, erro
if err != nil {
return win.NilHandle, err
}
+<<<<<<< HEAD
defer windows.CloseHandle(signalEvent)
+=======
+ defer windows.CloseHandle(signalEvent) //nolint:errcheck // This is just a resource release.
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
var flags win.EvtSubscribeFlag
if bookmark > 0 {
@@ -116,6 +132,20 @@ func (l *winEventLogExp) openChannel(bookmark win.Bookmark) (win.EvtHandle, erro
l.query, // Query - nil means all events
win.EvtHandle(bookmark), // Bookmark - for resuming from a specific event
flags)
+<<<<<<< HEAD
+=======
+
+ switch err { //nolint:errorlint // This is an errno or nil.
+ case nil:
+ return h, nil
+ case win.ERROR_NOT_FOUND, win.ERROR_EVT_QUERY_RESULT_STALE, win.ERROR_EVT_QUERY_RESULT_INVALID_POSITION:
+ // The bookmarked event was not found, we retry the subscription from the start.
+ incrementMetric(readErrors, err)
+ return win.Subscribe(0, signalEvent, "", l.query, 0, win.EvtSubscribeStartAtOldestRecord)
+ default:
+ return 0, err
+ }
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
}
func (l *winEventLogExp) openFile(state checkpoint.EventLogState, bookmark win.Bookmark) (win.EvtHandle, error) {
@@ -198,6 +228,10 @@ func (l *winEventLogExp) processHandle(h win.EvtHandle) (*Record, error) {
evt.RenderErr = append(evt.RenderErr, err.Error())
}
+<<<<<<< HEAD
+=======
+ //nolint:godox // Bad linter! Keep to have a record of feature disparity between non-experimental vs experimental.
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
// TODO: Need to add XML when configured.
r := &Record{
@@ -305,11 +339,3 @@ func newWinEventLogExp(options *common.Config) (EventLog, error) {
return l, nil
}
-
-func init() {
- // Register wineventlog API if it is available.
- available, _ := win.IsAvailable()
- if available {
- Register(winEventLogExpAPIName, 10, newWinEventLogExp, win.Channels)
- }
-}
diff --git a/winlogbeat/eventlog/wineventlog_test.go b/winlogbeat/eventlog/wineventlog_test.go
index c5d92ce1873..da67c61b3e1 100644
--- a/winlogbeat/eventlog/wineventlog_test.go
+++ b/winlogbeat/eventlog/wineventlog_test.go
@@ -31,6 +31,7 @@ import (
"github.com/andrewkroh/sys/windows/svc/eventlog"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/winlogbeat/checkpoint"
@@ -187,13 +188,27 @@ func testWindowsEventLog(t *testing.T, api string) {
const messageSize = 256 // Originally 31800, such a large value resulted in an empty eventlog under Win10.
const totalEvents = 1000
for i := 0; i < totalEvents; i++ {
- safeWriteEvent(t, writer, eventlog.Info, uint32(i%1000), []string{strconv.Itoa(i) + " " + randomSentence(messageSize)})
+ safeWriteEvent(t, writer, eventlog.Info, uint32(i%1000)+1, []string{strconv.Itoa(i) + " " + randomSentence(messageSize)})
}
openLog := func(t testing.TB, config map[string]interface{}) EventLog {
return openLog(t, api, nil, config)
}
+ t.Run("has_message", func(t *testing.T) {
+ log := openLog(t, map[string]interface{}{"name": providerName, "batch_read_size": 1})
+ defer log.Close()
+
+ for i := 0; i < 10; i++ {
+ records, err := log.Read()
+ require.NotEmpty(t, records)
+ require.NoError(t, err)
+
+ r := records[0]
+ require.NotEmpty(t, r.Message, "message field is empty: errors:%v\nrecord:%#v", r.Event.RenderErr, r)
+ }
+ })
+
// Test reading from an event log using a custom XML query.
t.Run("custom_xml_query", func(t *testing.T) {
cfg := map[string]interface{}{
@@ -307,16 +322,18 @@ func createLog(t testing.TB, messageFiles ...string) (log *eventlog.Log, tearDow
}
if existed {
- wineventlog.EvtClearLog(wineventlog.NilHandle, name, "")
+ wineventlog.EvtClearLog(wineventlog.NilHandle, name, "") //nolint:errcheck // This is just a resource release.
}
log, err = eventlog.Open(source)
+ //nolint:errcheck // This is just a resource release.
if err != nil {
eventlog.RemoveSource(name, source)
eventlog.RemoveProvider(name)
t.Fatal(err)
}
+ //nolint:errcheck // This is just a resource release.
tearDown = func() {
log.Close()
wineventlog.EvtClearLog(wineventlog.NilHandle, name, "")
@@ -343,7 +360,7 @@ func safeWriteEvent(t testing.TB, log *eventlog.Log, etype uint16, eid uint32, m
// setLogSize set the maximum number of bytes that an event log can hold.
func setLogSize(t testing.TB, provider string, sizeBytes int) {
- output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput()
+ output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() //nolint:gosec // No possibility of command injection.
if err != nil {
t.Fatal("Failed to set log size", err, string(output))
}
diff --git a/winlogbeat/sys/winevent/event.go b/winlogbeat/sys/winevent/event.go
index 9c342e73f48..4054626ed8f 100644
--- a/winlogbeat/sys/winevent/event.go
+++ b/winlogbeat/sys/winevent/event.go
@@ -44,11 +44,6 @@ var (
const (
keywordAuditFailure = 0x10000000000000
keywordAuditSuccess = 0x20000000000000
-
- // keywordClassic indicates the log was published with the "classic" event
- // logging API.
- // https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.eventing.reader.standardeventkeywords?view=netframework-4.8
- keywordClassic = 0x80000000000000
)
// UnmarshalXML unmarshals the given XML into a new Event.
@@ -67,7 +62,7 @@ type Event struct {
Version Version `xml:"System>Version"`
LevelRaw uint8 `xml:"System>Level"`
TaskRaw uint16 `xml:"System>Task"`
- OpcodeRaw uint8 `xml:"System>Opcode"`
+ OpcodeRaw *uint8 `xml:"System>Opcode,omitempty"`
KeywordsRaw HexInt64 `xml:"System>Keywords"`
TimeCreated TimeCreated `xml:"System>TimeCreated"`
RecordID uint64 `xml:"System>EventRecordID"`
@@ -258,7 +253,10 @@ func (u *UserData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
u.Name = se.Name
u.Pairs = in.Pairs
- d.Skip()
+ err = d.Skip()
+ if err != nil {
+ return err
+ }
break
}
}
@@ -309,8 +307,7 @@ func (v *Version) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
version, err := strconv.ParseUint(s, 10, 8)
if err != nil {
- // Ignore invalid version values.
- return nil
+ return nil //nolint:nilerr // Ignore invalid version values.
}
*v = Version(version)
@@ -341,20 +338,19 @@ func (v *HexInt64) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
func EnrichRawValuesWithNames(publisherMeta *WinMeta, event *Event) {
// Keywords. Each bit in the value can represent a keyword.
rawKeyword := int64(event.KeywordsRaw)
- isClassic := keywordClassic&rawKeyword > 0
if len(event.Keywords) == 0 {
for mask, keyword := range defaultWinMeta.Keywords {
- if rawKeyword&mask > 0 {
+ if rawKeyword&mask != 0 {
event.Keywords = append(event.Keywords, keyword)
- rawKeyword -= mask
+ rawKeyword &^= mask
}
}
if publisherMeta != nil {
for mask, keyword := range publisherMeta.Keywords {
- if rawKeyword&mask > 0 {
+ if rawKeyword&mask != 0 {
event.Keywords = append(event.Keywords, keyword)
- rawKeyword -= mask
+ rawKeyword &^= mask
}
}
}
@@ -363,10 +359,10 @@ func EnrichRawValuesWithNames(publisherMeta *WinMeta, event *Event) {
var found bool
if event.Opcode == "" {
// Opcode (search in defaultWinMeta first).
- if !isClassic {
- event.Opcode, found = defaultWinMeta.Opcodes[event.OpcodeRaw]
+ if event.OpcodeRaw != nil {
+ event.Opcode, found = defaultWinMeta.Opcodes[*event.OpcodeRaw]
if !found && publisherMeta != nil {
- event.Opcode = publisherMeta.Opcodes[event.OpcodeRaw]
+ event.Opcode = publisherMeta.Opcodes[*event.OpcodeRaw]
}
}
}
diff --git a/winlogbeat/sys/winevent/event_test.go b/winlogbeat/sys/winevent/event_test.go
index b6d893957ed..62fc3a7d6b6 100644
--- a/winlogbeat/sys/winevent/event_test.go
+++ b/winlogbeat/sys/winevent/event_test.go
@@ -20,7 +20,6 @@ package winevent
import (
"encoding/json"
"encoding/xml"
- "fmt"
"strings"
"testing"
"time"
@@ -97,6 +96,7 @@ func TestXML(t *testing.T) {
EventIdentifier: EventIdentifier{ID: 91},
LevelRaw: 4,
TaskRaw: 9,
+ OpcodeRaw: new(uint8), // The value in the XML is 0.
KeywordsRaw: 0x8020000000000000,
TimeCreated: TimeCreated{allXMLTimeCreated},
RecordID: 100,
@@ -180,7 +180,7 @@ func TestXML(t *testing.T) {
if err != nil {
t.Error(err)
}
- fmt.Println(string(json))
+ t.Logf("%s", json)
}
}
}
diff --git a/winlogbeat/sys/wineventlog/format_message.go b/winlogbeat/sys/wineventlog/format_message.go
index d953c210b56..642eaa69965 100644
--- a/winlogbeat/sys/wineventlog/format_message.go
+++ b/winlogbeat/sys/wineventlog/format_message.go
@@ -21,9 +21,9 @@
package wineventlog
import (
+ "fmt"
"unsafe"
- "github.com/pkg/errors"
"golang.org/x/sys/windows"
"github.com/elastic/beats/v7/winlogbeat/sys"
@@ -80,8 +80,8 @@ func evtFormatMessage(metadataHandle EvtHandle, eventHandle EvtHandle, messageID
// Determine the buffer size needed (given in WCHARs).
var bufferUsed uint32
err := _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, 0, nil, &bufferUsed)
- if err != windows.ERROR_INSUFFICIENT_BUFFER {
- return "", errors.Wrap(err, "failed in EvtFormatMessage")
+ if err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno.
+ return "", fmt.Errorf("failed in EvtFormatMessage: %w", err)
}
// Get a buffer from the pool and adjust its length.
@@ -89,16 +89,17 @@ func evtFormatMessage(metadataHandle EvtHandle, eventHandle EvtHandle, messageID
defer bb.Free()
bb.Reserve(int(bufferUsed * 2))
- err = _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, uint32(bb.Len()/2), bb.PtrAt(0), &bufferUsed)
- if err != nil {
- switch err {
- // Ignore some errors so it can tolerate missing or mismatched parameter values.
- case windows.ERROR_EVT_UNRESOLVED_VALUE_INSERT:
- case windows.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT:
- case windows.ERROR_EVT_MAX_INSERTS_REACHED:
- default:
- return "", errors.Wrap(err, "failed in EvtFormatMessage")
- }
+ err = _EvtFormatMessage(metadataHandle, eventHandle, messageID, valuesCount, valuesPtr, messageFlag, uint32(bb.Len()), bb.PtrAt(0), &bufferUsed)
+ switch err { //nolint:errorlint // This is an errno or nil.
+ case nil: // OK
+
+ // Ignore some errors so it can tolerate missing or mismatched parameter values.
+ case windows.ERROR_EVT_UNRESOLVED_VALUE_INSERT,
+ windows.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT,
+ windows.ERROR_EVT_MAX_INSERTS_REACHED:
+
+ default:
+ return "", fmt.Errorf("failed in EvtFormatMessage: %w", err)
}
return sys.UTF16BytesToString(bb.Bytes())
diff --git a/winlogbeat/sys/wineventlog/query_test.go b/winlogbeat/sys/wineventlog/query_test.go
index f31f98ac6c9..8c3a5031f12 100644
--- a/winlogbeat/sys/wineventlog/query_test.go
+++ b/winlogbeat/sys/wineventlog/query_test.go
@@ -49,7 +49,7 @@ func TestIgnoreOlderQuery(t *testing.T) {
q, err := Query{Log: "Application", IgnoreOlder: time.Hour}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
@@ -64,7 +64,7 @@ func TestEventIDQuery(t *testing.T) {
q, err := Query{Log: "Application", EventID: "1, 1-100, -75"}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
@@ -78,7 +78,7 @@ func TestLevelQuery(t *testing.T) {
q, err := Query{Log: "Application", Level: "Verbose"}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
@@ -92,7 +92,7 @@ func TestProviderQuery(t *testing.T) {
q, err := Query{Log: "Application", Provider: []string{"mysrc"}}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
@@ -112,7 +112,7 @@ func TestCombinedQuery(t *testing.T) {
}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
@@ -126,6 +126,6 @@ func TestQueryNoParams(t *testing.T) {
q, err := Query{Log: "Application"}.Build()
if assert.NoError(t, err) {
assert.Equal(t, expected, q)
- fmt.Println(q)
+ t.Log(q)
}
}
diff --git a/winlogbeat/sys/wineventlog/renderer.go b/winlogbeat/sys/wineventlog/renderer.go
index 8a16567e7ad..310eab450f6 100644
--- a/winlogbeat/sys/wineventlog/renderer.go
+++ b/winlogbeat/sys/wineventlog/renderer.go
@@ -30,7 +30,6 @@ import (
"unsafe"
"github.com/cespare/xxhash/v2"
- "github.com/pkg/errors"
"go.uber.org/multierr"
"golang.org/x/sys/windows"
@@ -48,10 +47,10 @@ const (
// Renderer is used for converting event log handles into complete events.
type Renderer struct {
- // Cache of publisher metadata. Maps publisher names to stored metadata.
- metadataCache map[string]*PublisherMetadataStore
// Mutex to guard the metadataCache. The other members are immutable.
mutex sync.RWMutex
+ // Cache of publisher metadata. Maps publisher names to stored metadata.
+ metadataCache map[string]*PublisherMetadataStore
session EvtHandle // Session handle if working with remote log.
systemContext EvtHandle // Render context for system values.
@@ -63,12 +62,12 @@ type Renderer struct {
func NewRenderer(session EvtHandle, log *logp.Logger) (*Renderer, error) {
systemContext, err := _EvtCreateRenderContext(0, 0, EvtRenderContextSystem)
if err != nil {
- return nil, errors.Wrap(err, "failed in EvtCreateRenderContext for system context")
+ return nil, fmt.Errorf("failed in EvtCreateRenderContext for system context: %w", err)
}
userContext, err := _EvtCreateRenderContext(0, 0, EvtRenderContextUser)
if err != nil {
- return nil, errors.Wrap(err, "failed in EvtCreateRenderContext for user context")
+ return nil, fmt.Errorf("failed in EvtCreateRenderContext for user context: %w", err)
}
return &Renderer{
@@ -99,7 +98,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) {
event := &winevent.Event{}
if err := r.renderSystem(handle, event); err != nil {
- return nil, errors.Wrap(err, "failed to render system properties")
+ return nil, fmt.Errorf("failed to render system properties: %w", err)
}
// From this point on it will return both the event and any errors. It's
@@ -117,7 +116,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) {
eventData, fingerprint, err := r.renderUser(handle, event)
if err != nil {
- errs = append(errs, errors.Wrap(err, "failed to render event data"))
+ errs = append(errs, fmt.Errorf("failed to render event data: %w", err))
}
// Load cached event metadata or try to bootstrap it from the event's XML.
@@ -127,7 +126,7 @@ func (r *Renderer) Render(handle EvtHandle) (*winevent.Event, error) {
r.addEventData(eventMeta, eventData, event)
if event.Message, err = r.formatMessage(md, eventMeta, handle, eventData, uint16(event.EventIdentifier.ID)); err != nil {
- errs = append(errs, errors.Wrap(err, "failed to get the event message string"))
+ errs = append(errs, fmt.Errorf("failed to get the event message string: %w", err))
}
if len(errs) > 0 {
@@ -165,8 +164,8 @@ func (r *Renderer) getPublisherMetadata(publisher string) (*PublisherMetadataSto
// Return an empty store on error (can happen in cases where the
// log was forwarded and the provider doesn't exist on collector).
md = NewEmptyPublisherMetadataStore(publisher, r.log)
- err = errors.Wrapf(err, "failed to load publisher metadata for %v "+
- "(returning an empty metadata store)", publisher)
+ err = fmt.Errorf("failed to load publisher metadata for %v "+
+ "(returning an empty metadata store): %w", publisher, err)
}
r.metadataCache[publisher] = md
} else {
@@ -180,11 +179,11 @@ func (r *Renderer) getPublisherMetadata(publisher string) (*PublisherMetadataSto
func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error {
bb, propertyCount, err := r.render(r.systemContext, handle)
if err != nil {
- return errors.Wrap(err, "failed to get system values")
+ return fmt.Errorf("failed to get system values: %w", err)
}
defer bb.Free()
- for i := 0; i < int(propertyCount); i++ {
+ for i := 0; i < propertyCount; i++ {
property := EvtSystemPropertyID(i)
offset := i * int(sizeofEvtVariant)
evtVar := (*EvtVariant)(unsafe.Pointer(bb.PtrAt(offset)))
@@ -194,6 +193,7 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error {
continue
}
+ //nolint:errcheck // Bad linter!
switch property {
case EvtSystemProviderName:
event.Provider.Name = data.(string)
@@ -208,7 +208,10 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error {
case EvtSystemTask:
event.TaskRaw = data.(uint16)
case EvtSystemOpcode:
- event.OpcodeRaw = data.(uint8)
+ if event.OpcodeRaw == nil {
+ event.OpcodeRaw = new(uint8)
+ }
+ *event.OpcodeRaw = data.(uint8)
case EvtSystemKeywords:
event.KeywordsRaw = winevent.HexInt64(data.(hexInt64))
case EvtSystemTimeCreated:
@@ -247,7 +250,7 @@ func (r *Renderer) renderSystem(handle EvtHandle, event *winevent.Event) error {
func (r *Renderer) renderUser(handle EvtHandle, event *winevent.Event) (values []interface{}, fingerprint uint64, err error) {
bb, propertyCount, err := r.render(r.userContext, handle)
if err != nil {
- return nil, 0, errors.Wrap(err, "failed to get user values")
+ return nil, 0, fmt.Errorf("failed to get user values: %w", err)
}
defer bb.Free()
@@ -264,7 +267,7 @@ func (r *Renderer) renderUser(handle EvtHandle, event *winevent.Event) (values [
for i := 0; i < propertyCount; i++ {
offset := i * int(sizeofEvtVariant)
evtVar := (*EvtVariant)(unsafe.Pointer(bb.PtrAt(offset)))
- binary.Write(argumentHash, binary.LittleEndian, uint32(evtVar.Type))
+ binary.Write(argumentHash, binary.LittleEndian, uint32(evtVar.Type)) //nolint:errcheck // Hash writes never fail.
values[i], err = evtVar.Data(bb.Bytes())
if err != nil {
@@ -287,8 +290,8 @@ func (r *Renderer) render(context EvtHandle, eventHandle EvtHandle) (*sys.Pooled
var bufferUsed, propertyCount uint32
err := _EvtRender(context, eventHandle, EvtRenderEventValues, 0, nil, &bufferUsed, &propertyCount)
- if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER {
- return nil, 0, errors.Wrap(err, "failed in EvtRender")
+ if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil.
+ return nil, 0, fmt.Errorf("failed in EvtRender: %w", err)
}
if propertyCount == 0 {
@@ -301,7 +304,7 @@ func (r *Renderer) render(context EvtHandle, eventHandle EvtHandle) (*sys.Pooled
err = _EvtRender(context, eventHandle, EvtRenderEventValues, uint32(bb.Len()), bb.PtrAt(0), &bufferUsed, &propertyCount)
if err != nil {
bb.Free()
- return nil, 0, errors.Wrap(err, "failed in EvtRender")
+ return nil, 0, fmt.Errorf("failed in EvtRender: %w", err)
}
return bb, int(propertyCount), nil
@@ -390,7 +393,7 @@ func (r *Renderer) formatMessageFromTemplate(msgTmpl *template.Template, values
defer bb.Free()
if err := msgTmpl.Execute(bb, values); err != nil {
- return "", errors.Wrapf(err, "failed to execute template with data=%#v template=%v", values, msgTmpl.Root.String())
+ return "", fmt.Errorf("failed to execute template with data=%#v template=%v: %w", values, msgTmpl.Root.String(), err)
}
return string(bb.Bytes()), nil
diff --git a/winlogbeat/sys/wineventlog/renderer_test.go b/winlogbeat/sys/wineventlog/renderer_test.go
index ea0c179cd1e..a283bc0f057 100644
--- a/winlogbeat/sys/wineventlog/renderer_test.go
+++ b/winlogbeat/sys/wineventlog/renderer_test.go
@@ -41,7 +41,7 @@ import (
)
func TestRenderer(t *testing.T) {
- logp.TestingSetup()
+ logp.TestingSetup() //nolint:errcheck // Bad linter! Never returns a non-nil error when called without options.
t.Run(filepath.Base(sysmon9File), func(t *testing.T) {
log := openLog(t, sysmon9File)
@@ -86,7 +86,8 @@ func TestRenderer(t *testing.T) {
assert.Equal(t, e.Keywords, []string{"Audit Success"})
- assert.EqualValues(t, 0, e.OpcodeRaw)
+ assert.NotNil(t, 0, e.OpcodeRaw)
+ assert.EqualValues(t, 0, *e.OpcodeRaw)
assert.Equal(t, "Info", e.Opcode)
assert.EqualValues(t, 0, e.LevelRaw)
@@ -131,7 +132,7 @@ func TestRenderer(t *testing.T) {
assert.Equal(t, e.Keywords, []string{"Classic"})
- assert.EqualValues(t, 0, e.OpcodeRaw)
+ assert.EqualValues(t, (*uint8)(nil), e.OpcodeRaw)
assert.Equal(t, "", e.Opcode)
assert.EqualValues(t, 4, e.LevelRaw)
@@ -197,7 +198,7 @@ func renderAllEvents(t *testing.T, log EvtHandle, renderer *Renderer, ignoreMiss
// setLogSize set the maximum number of bytes that an event log can hold.
func setLogSize(t testing.TB, provider string, sizeBytes int) {
- output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput()
+ output, err := exec.Command("wevtutil.exe", "sl", "/ms:"+strconv.Itoa(sizeBytes), provider).CombinedOutput() //nolint:gosec // No possibility of command injection.
if err != nil {
t.Fatal("failed to set log size", err, string(output))
}
diff --git a/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml b/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml
new file mode 100644
index 00000000000..0e768eaeebd
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/application-windows-error-reporting.xml
@@ -0,0 +1,18 @@
+1001400x80000000000000420107Applicationvagrant0WindowsWcpOtherFailure3Not available010.0.17763.850:3inc\auto_hive.hWindows::Rtl::AutoHive::Unload358c00001210xaad0d4fb
+\\?\C:\Windows\Logs\CBS\CBS.log
+\\?\C:\Windows\Logs\CBS\CbsPersist_20200212163557.log
+\\?\C:\Windows\Logs\CBS\CbsPersist_20200211235949.log
+\\?\C:\Windows\Logs\CBS\CbsPersist_20200211033558.cab
+\\?\C:\Windows\Logs\CBS\CbsPersist_20200210020038.cab
+\\?\C:\Windows\Logs\CBS\CbsPersist_20200209082850.cab
+\\?\C:\Windows\servicing\Sessions\Sessions.xml
+\\?\C:\Windows\WinSxs\pending.xml
+\\?\C:\Windows\WinSxs\poqexec.log
+\\?\C:\Windows\Logs\Cbs\FilterList.log
+\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC5A1.tmp.WERInternalMetadata.xml
+\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC7D5.tmp.xml
+\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC7F3.tmp.csv
+\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERC9F8.tmp.txt
+\\?\C:\ProgramData\Microsoft\Windows\WER\Temp\WERCA08.tmp.mdmp
+\\?\C:\ProgramData\Microsoft\Windows\WER\ReportQueue\Critical_10.0.17763.850_3_b785171a54ee6e13bf912aeeb5bef5d9105e314b_00000000_cab_0c38cad1\memory.hdmp
+\\?\C:\Windows\Temp\WERCAD4.tmp.WERDataCollectionStatus.txt\\?\C:\ProgramData\Microsoft\Windows\WER\ReportQueue\Critical_10.0.17763.850_3_b785171a54ee6e13bf912aeeb5bef5d9105e314b_00000000_cab_0c38cad105e9de0ad-0fa4-4daa-aec1-8127dc88e6c71000
diff --git a/winlogbeat/sys/wineventlog/testdata/ec1.evtx b/winlogbeat/sys/wineventlog/testdata/ec1.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..3e498db3ae0f143210ac1798040776c2c29e444d
GIT binary patch
literal 69632
zcmeI$U5Hd=9LMqh%$%7$JF7F=CYgzi(F+Q`BnswBFs>_wnp##6-VE+;yE;1~yR*Kq
zL0XAY65jMiH&H=!(@h8xU3e2Afn7;fH$emuA!!tq7u)au%sDkK$r2KD@qLz=Ip;k8
z^Spfi&v}NO{`%0Ck@}!bFWKb6QGI4DXErA@J>;g(tG{1+@TMD~0R#|0009ILKmY**
z5I_I{1Q3`}puaxUH{957>3{b(`aJ3_=|_Q+vDw1+f4yhMhGz)ye#&z$zS$WzzhL%G
zm)YgK*|$+=joD|qzEM9z{M&MVhI>w{&&z6izWVfXHHrUF*VFQV$cGyO(uF7#$E*ut_&)srsL)M9MP3AYwE0NLyBCk
z^QNw^utTbA=yR2=)Zc0yt+cgzAN;HP@$1gAnW?F-m8w&D{li%#Nt#R_IX+ygD_t
zTjNSIdSx=UouT)G>T5tzW2(L1r<5+nt*=D(hz2{VN}o_q$L#wQKBzixK3C1zc127i
zi{+PES4ZT-wpn%edBeWiye#>uXuE7ex7XG8kY3)qtCb=vWJ@_KMC$D>T}T)C{O&G$
zA_*H2QbTpwQjbNE(z{3}>FOT1khg6L^fc8&kaXpFOv99g`P@U
zT>o;9Ivoj|oqPj|2|WG)`EuGYS-dWJ=}qD(*xX#EsD<+PHnJr*yF>d?jm3xTBWcTL
zOGPXCSdQzabT4@OYLE4WFi&GWBr;{)qqr^A=WQl)oMpYasMKqVBfC|hT881JRjco<_A9n|7Ta9!
zL$z^u#a0Y)3#~U?|EITdX0d&G`L3(8-v`1G*u@+evQgXv#~UN%4H=}&jn%|X4U
z>sj^cZqv`YL#_8EGf+9VgV5%#QhET~UaC%XwLRwqTp2+EB=t7OFq9S?wv2|H^NB
z>{wv&$nC1Fge>?D>3eP^fctJd7LL;aRkS~~ueHMNT~XWrv_vXeG)-mx`r_X|6a)}J
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
x009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|00D=FPz@KC<7RUeq
literal 0
HcmV?d00001
diff --git a/winlogbeat/sys/wineventlog/testdata/ec1.xml b/winlogbeat/sys/wineventlog/testdata/ec1.xml
new file mode 100644
index 00000000000..d1607a64835
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/ec1.xml
@@ -0,0 +1 @@
+100002000x80000000000000316ApplicationvagrantMy custom error event for the application log
diff --git a/winlogbeat/sys/wineventlog/testdata/ec2.evtx b/winlogbeat/sys/wineventlog/testdata/ec2.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..7b8eb85263de7a7fad8d9c69b8032f1a13b53796
GIT binary patch
literal 69632
zcmeI$Ux-v?7{~GF%$%7$JFBy9s~{#eMieW!E2f~C!MdYHFGibm6jpa&>lAc4ys{
zz0pjP2LQ3Fx{-+PEQrYdTy$k6L0ANp7u)YSbKYE+WC;nn_`b_IbKdhl
z=l%0}-}4STz15*@!_`5Xn{wHW6Z*_q-fU4cH{`bS-G5wv=(a1N0t661009ILKmY**
z5I_I{1Q3{4ptm~IbEtO2!hiR-`aIz^=|_PRiP_KhfA-S670(mk?OZtja@XvzMMbk$
zn#`^g%)W_dmzaH|`Tpr8!lyHicU}MLcNbTGJokb|;!)l0c1o8%Ku;emC|Iu@vq7s_UHNBq
z6c1;GAGQ{3%0{fJ!f_Q8qV;x2VRbud4_KG}#;sp>1{Kq%>rQ&}>sDmQ9FitJQ=
zRQJ1VQe`!LuC+D#Tc@ivwn68?zndSwDVK|8Wb$ng2JvN~#tEy;7hqvll<=Be3a^8w@)M9t*Mp)cSo11KZ
z7B;MQYbwi?TP%(>tt*rXt9sy4!FDLnr>B|*nFr-;xiYQU((Ij%ZC}cNBn`=VgOOE~
z@m25XofSpfr8)DNa20PZ@|p^Ek22w9Is9p2+f{sAQ`OM$VdTmMTM|opw=&OUHEufF
zqDF^P#vYA#P#y4D8Bk2h<1dacqX(x;H%(f2NIXSr%SR{_w*10b+K;J1@3PNJ
zLq1n7S;_lyS`URi;Ei8etS1fgepJ(*1lA`Nw{2tgQkSlktXnnK)p1`Sb&a%9Z@I}@
zi@p!|w6FiT&AjPGO+KbuJamV(=GB)GwGsA>3-2{+08?qlC(?!*)BCXZ|~2^&+vP=)0*;?dgq)gb!u50ifJ$Nj{pH+2G^P_PkSCqCJZ2(?Y7H{nn%v
zwC1`sa(ZR1FyMm?!HA2`X21*
z_0B|7>r*tLmgKm)mV+Y>O4DWtbjXwfeql9EmNl
z#M-$~CEB!mqzRzAwZIu=_$Pm9d?3`Nro(fBJ`flO1Gk*?U
zdj8JotH1uBha0=;`RRORS?gC_pG@f~kCLUonEo~BY3tKI{b4uV
znyUBdeon3WJL_MIz6zcjjkS~bE0dO%%})AjT~UaCyLno9p=evAT2siF7OKC9IqfO2
z|GIAn?PSX0k&O*3ys{NxhYnP1WBOM~SBEbK-{yTqS9DD1s-iB8>Ri=%GQB&j={ln0
zsM_`Ac_aDvj;ApHjT~nL5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
PKmY**5I_Kd|AW9^g%K21
literal 0
HcmV?d00001
diff --git a/winlogbeat/sys/wineventlog/testdata/ec2.xml b/winlogbeat/sys/wineventlog/testdata/ec2.xml
new file mode 100644
index 00000000000..5e2e8e38b7d
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/ec2.xml
@@ -0,0 +1 @@
+99902000x80000000000000317ApplicationvagrantWinword event 999 happened due to low diskspace
diff --git a/winlogbeat/sys/wineventlog/testdata/ec3.evtx b/winlogbeat/sys/wineventlog/testdata/ec3.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..fb0bdc95fceb5e06797de26bb17b28ae28138bcd
GIT binary patch
literal 69632
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
literal 0
HcmV?d00001
diff --git a/winlogbeat/sys/wineventlog/testdata/ec3.xml b/winlogbeat/sys/wineventlog/testdata/ec3.xml
new file mode 100644
index 00000000000..fdd0622ae59
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/ec3.xml
@@ -0,0 +1 @@
+502000x800000000000001413SystemvagrantCatastrophe!
diff --git a/winlogbeat/sys/wineventlog/testdata/ec3and4.evtx b/winlogbeat/sys/wineventlog/testdata/ec3and4.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..74e7cd1e2cf6b1c5b16a2553ed71cd0b62eb6b13
GIT binary patch
literal 69632
zcmeI$Uuf1<9LMqR^JmYVJ=16E)P{<=h)N+{l4P0DHYb)^YGz%8Fx=+mo;?${`G<8e
z6)Qrri-P`K6a_&<-Bctccokk{H%01IK^GNXWFbUR>+?O&?>ufpn;>-&?=!YNzjMC7
zbI$K|&iVdy9i^W2eWh-jS~5w+n0}{CSF=)6LvHx`=s(Hor-u}v|
zKVDpWF4d4q*^Ja(Ee|e@qx$EOxvO`6^x^o=vzlHybW~5`QLT-3Kp*`9y?i>O#yV`j
zbz9knb^WZqb9<7;Qw=qC&<3oe#vwJ-q*ht4!iH_H-DfNGHDtR~)2*0JeO|8LeX7}K
zgSr~D9z`zK^`Pok*a5Yb^?RkY=<9BMYO&S&*c?w=H4x{Ti!FQTx<-yFXIgj2mCh+9R6mfExXQa_a6%mzma#
zZB~7MvPCX;)=toQ$kxT~e2;lqdZA!jZA2ZGG-8jweN4A1W-XU4W-OOY)!Qwqh+Dg<
zuGV%WVSS=0t1Vruw`^96x>y%+Pj{WIu}uo}#VLg#^PsdX(#6bVV|I*YZF|7)4|P
zsY9Q#&!i%sE*7ldb2+A)Vg`8YmwIatVLp#im`P-PN^$G&Nse^kQo&l)~+hbTy
zTIsh~YYjQi0>134KA&wqbfqVMrfb|Z#~L!4%Yep+S>xo#b$WnKVTR!Kx)R*?yy?F`uCbkivSZDc6YJA+$Jo|b%sx8{C$WCpf
za+tT)*Z1|rqmtE4D;4Z1%@=V^IUmplv@Lw1m4l+&YDLp&yEU%&H*BumrW-x)dUY|7c=dMfWTd9oSSn8_9!tvPFR6{^h_zO`5N$Lh*=-sV}}
zX8Raw&4=&26++x1YYg>Q`|*V}s}G&zYU7y2q!_D?#YXLTFE#V@IC)HntzV^=#W|cqupoG?<*Fi;zxb-_l2jm@NW3;-vgbRg1-km<9m+ujPI)$^1AQ#Hi7K2er?OW
z=2`qEHTrR`^B~XGlk#yvwVscwdDkm^7o@c;A;)@!A4Fe(kWszDGio(=dWGlCYKEMn
z3O`(7NY8*V$9bgx1F4$77OKMYm){ZcQ#At>ldR$qo>fAG@1A1J4lxJJ_dc}3S3T=Z
zYV@;yjT7y?`iTxR^>bVN7f)#GRZeK!hMGqx&*%w5x&9NX#nRjI%88h`0hZ`Z+^KU^
z3R$W<={x@N^FToW0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~
z0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**
z5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0
z009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{
z1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009IL
zKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0*~0R#|0009ILKmY**5I_I{1Q0;r
H|0wV`q_}7!
literal 0
HcmV?d00001
diff --git a/winlogbeat/sys/wineventlog/testdata/ec3and4.xml b/winlogbeat/sys/wineventlog/testdata/ec3and4.xml
new file mode 100644
index 00000000000..5844cfbfe91
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/ec3and4.xml
@@ -0,0 +1,2 @@
+502000x800000000000001414SystemvagrantBackup failure
+502000x800000000000001413SystemvagrantCatastrophe!
diff --git a/winlogbeat/sys/wineventlog/testdata/ec4.evtx b/winlogbeat/sys/wineventlog/testdata/ec4.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..94547179581c7f96ae5e8ffdef658d4b09173fe6
GIT binary patch
literal 69632
zcmeI$OK4nG9LMqh%-osWOp-}sj7Tjt5nm0MgktegTgVf&t$kRl3lWAqnlzJ%G?OMF
zF4C5&NVINT=tj|{(4ANx(3NIa5fsy|TnLJE6Gc!9#^3+Wy_yC~kb)b(C(PrV^S|fu
zIp>~BroS{YFjgA2^(h?}Ea)?B8M95P^&vN$@BZ!T?i+4|1`t310R#|0009ILKmY**
z5I|r>-u;u
zZp*KKEB?MuvAt^Z{dMgmeT-@h|8=@sV`^{Lnrd9hy6^t#%GK9*EvFh&DXUK{-tyii
zkMiW-kG3y8^U1w`965BhXW_JF;!)krHlwdTK~EpoXRY5(*sztYqWnvG<&MRbpEhP~
z)+Vf^$|+T3Q#))_VHJDc9=1;XP1&GIh80uP_YQrIspPm#DmQ5(itJE+QstdCqq?#_
zw_BI~?$@_2drzCF?eMIA>4VoLa6#J!*q@udY6>aV0CdG9TK3
zsP_}T=d`K4I1M&~i>
zOPcdN=4spIydBh~MH!80zGG3JZdC{@mo8*17o_U!4izL@`_|eTI}(SDiKeW&bfM0I
zK#RInnPg87UCi2E1^VKYq9F62v~5wQA>Nq%^MM_X@W-Q&w0D@YR%Lw8dpfr@XZtld
zUk5kw?o!@T*6vg$xmAvR5!xPA&uO711veyU56xOjAm;{n%Y^z!PL1;))M^5=(ZHvpj;hQ1sE^}7W9q^cRmJ
zv@qvqsW0uBhe8RD#HUd3FyM;H3J>*<}2P!0RSOe>~}Xm-15a>)@q
zvNvZ>X;$85JhOUh&IE;KYYXgVg=+IfFYQ%5qpGjaS}e3C??bg=^a?E>#ci?XsQjPa
zzO*)f&Y9fev|!1hn3TMjRBFe2%C_k3+lG~we;>KHc-#DsKl>e5Jwa!dxAi7xyMOS<
ztE1%42@(PbAb502000x800000000000001414SystemvagrantBackup failure
diff --git a/winlogbeat/sys/wineventlog/testdata/experimental.evtx b/winlogbeat/sys/wineventlog/testdata/experimental.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..1fbfa0a461fbe44a73baa7f648c3d9e0270ac6cf
GIT binary patch
literal 69632
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
f4Cdm`{-(zDgZC`oiOEa404000x8000000000000020050WinlogbeatTestGovagrant4 college quality neutral feather article article trolley attract bargain college arrange recover feather arrange percent wriggle wriggle feather college highway feather neutral quality manager manager recover arrange article arrange manager quality bargain
+304000x8000000000000020049WinlogbeatTestGovagrant3 highway article bargain article college trolley percent college attract recover arrange attract manager highway trolley bargain recover trolley arrange manager bargain wriggle arrange manager trolley bargain recover highway bargain feather manager percent
+204000x8000000000000020048WinlogbeatTestGovagrant2 wriggle college highway wriggle quality manager college article neutral bargain arrange quality highway percent attract attract arrange manager wriggle neutral highway article feather recover highway highway hunting arrange article manager neutral attract
+104000x8000000000000020047WinlogbeatTestGovagrant1 feather bargain feather neutral bargain recover hunting quality attract neutral wriggle quality percent manager feather neutral attract neutral highway bargain bargain attract college article wriggle quality percent wriggle article recover hunting bargain
+004000x8000000000000020046WinlogbeatTestGovagrant0 wriggle neutral trolley hunting highway attract college percent highway recover arrange bargain percent arrange quality arrange manager quality trolley feather percent hunting highway quality neutral arrange recover quality recover article bargain wriggle
diff --git a/winlogbeat/sys/wineventlog/testdata/original.evtx b/winlogbeat/sys/wineventlog/testdata/original.evtx
new file mode 100644
index 0000000000000000000000000000000000000000..a973a51a4c34e1e3fae8c7c41bec8ac211825aaf
GIT binary patch
literal 69632
zcmeI*eXws;UB~ft&OP_s!{K@_mxnSkyilV-BOro8R5QqfA`fEX!%Pn|SGbp_%e}~h
zz%UJ1IyOz?OqLp2fk0VVh?a$7RMRw+3W$JQ@DT;fk_gMjKbmf9{mx#OyN~~WOegu239k$nt{~}tY%;}1FIQW&A@5~Rx_}gfz=GGW?(e~gEDaP_H8Gg
zzvH5iKi#jbcD=s({QsufeSq8c4dK@h2;tO6ulv9t<2{R#zx$p%=Z^Z4L*_&H;JOgL
zA4NPlSDy*tAL7q{Hr|F$`Z=J-0-kPej{?RDu6bwf?U7^Za#V{Mkk5IVq06KfAQz
zKzv-9lNhIOt-e1auDvMQ{9Ei~AD2fB&&Ah^Dve#X4?8S`pIitb*ZWmhY(4a}pW8LF
zab_m0pSj`sbMMF&()aJU^U^mz_1I5cvd?dxa_vWABx%(N`-L0gw<*B%^{Mr1!^z=o
zVQbhCE|24P#Xs{GR+FFJxHeoBE)Lt{yG0cxU|i5#h=>w*ZK%NnEE
znccgeinYph+j;hUczw7!TE2YZG2ZDqVfXG|j=FM1pT1@xoHgrNQ-8}3*zA53f7aanTzUE
zK`xpsnN1F7Vn`vRbCAAnJ!n3>HdZm!Cgmwvnn{+{hM$Ooe0(mvcOje>r>~C1+Zls6
zcM`_zhPB~j?O-r>Z_vZP~st*jyZ
zVqAC1Y1J`be0njQ5G|&vCuA;{Y^2(9WjiZk@mO5iNt&6
z{8jO%bJ5UI(NJoAsj$cISePX8;)qHTzjUCYsdX`3TdE_I8b_)?Qjq#{`nvJ(g;?ZN
ztSh44rNoBt!ZARiryEJ=s9G@TSlIoUlIBzn(Aika-?QEIMCuvK&
z)8W`WIdn_A&zso4WKy;SYqFB;HTS1;mkw%5#iemR#gMclZ%N-4>)NrT3p5@lUdz{JGxvx5afS#`NBm*6Y8NAMK}8R?oNk&4>G)Py17K
z&Z+8YzN~lRAb+LngLIv+D>mD+tLwpxdh
~I=ghpX0nvfK4e)DhfJtn8jE6)
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
a)VO}&&ZRpsdFg*wCv6JXdC3pZ>;D00lwa`x
literal 0
HcmV?d00001
diff --git a/winlogbeat/sys/wineventlog/testdata/original.xml b/winlogbeat/sys/wineventlog/testdata/original.xml
new file mode 100644
index 00000000000..40ce93c2a1b
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/original.xml
@@ -0,0 +1,5 @@
+404000x8000000000000020055WinlogbeatTestGovagrant4 college quality neutral feather article article trolley attract bargain college arrange recover feather arrange percent wriggle wriggle feather college highway feather neutral quality manager manager recover arrange article arrange manager quality bargain
+304000x8000000000000020054WinlogbeatTestGovagrant3 highway article bargain article college trolley percent college attract recover arrange attract manager highway trolley bargain recover trolley arrange manager bargain wriggle arrange manager trolley bargain recover highway bargain feather manager percent
+204000x8000000000000020053WinlogbeatTestGovagrant2 wriggle college highway wriggle quality manager college article neutral bargain arrange quality highway percent attract attract arrange manager wriggle neutral highway article feather recover highway highway hunting arrange article manager neutral attract
+104000x8000000000000020052WinlogbeatTestGovagrant1 feather bargain feather neutral bargain recover hunting quality attract neutral wriggle quality percent manager feather neutral attract neutral highway bargain bargain attract college article wriggle quality percent wriggle article recover hunting bargain
+004000x8000000000000020051WinlogbeatTestGovagrant0 wriggle neutral trolley hunting highway attract college percent highway recover arrange bargain percent arrange quality arrange manager quality trolley feather percent hunting highway quality neutral arrange recover quality recover article bargain wriggle
diff --git a/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml b/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml
new file mode 100644
index 00000000000..82a6ff6dca4
--- /dev/null
+++ b/winlogbeat/sys/wineventlog/testdata/sysmon-9.01.xml
@@ -0,0 +1,32 @@
+244200x800000000000000032Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\Storage\ext\gfdkimpbcpahaombhbimeihdjnejgicl\def\ee4a6e45-bffd-49f4-98ae-32aebcc890b5.tmp2019-03-18 16:52:05.3392019-03-18 16:57:52.417
+244200x800000000000000031Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\Storage\ext\nmmhkkegccagdldgiimedpiccmgmieda\def\ecb9c915-c4c2-4600-a920-f2bc302990a8.tmp2019-03-18 16:52:08.4962019-03-18 16:57:52.417
+534500x800000000000000030Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.433{42f11c3b-ccab-5c8f-0000-001064eb2700}2680C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
+244200x800000000000000029Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\37ed32e9-3c5f-4663-8457-c70743e9456d.tmp2019-03-18 16:51:54.9802019-03-18 16:57:52.417
+244200x800000000000000028Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\Default\1450fedf-ac4c-4e35-b371-ed5d3bbe4776.tmp2019-03-18 16:52:05.0282019-03-18 16:57:52.402
+244200x800000000000000027Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.417{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\162d4140-cfab-4d05-9c92-bca60515a622.tmp2019-03-18 16:52:04.9802019-03-18 16:57:52.402
+244200x800000000000000026Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.387{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Users\vagrant\AppData\Local\Google\Chrome\User Data\fe823684-c940-49f2-a940-14b02cbafba9.tmp2019-03-18 16:52:04.9802019-03-18 16:57:52.387
+534500x800000000000000025Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.364{42f11c3b-cccc-5c8f-0000-0010e8272900}3208C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
+534500x800000000000000024Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:52.350{42f11c3b-ccc6-5c8f-0000-001005082900}4832C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
+354300x800000000000000023Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:49.218{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse169.254.180.25137netbios-ns
+354300x800000000000000022Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:49.213{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse169.254.255.255137netbios-ns
+354300x800000000000000021Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.276{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse10.0.2.3137netbios-ns
+354300x800000000000000020Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.264{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse40.77.226.250137netbios-ns
+354300x800000000000000019Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea9fe:b419:0:0:f880:2301:e0:ffff55717truee000:fc:0:0:0:0:0:05355llmnr
+354300x800000000000000018Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruefe80:0:0:0:616f:32fa:b04f:b41955717trueff02:0:0:0:0:0:1:35355llmnr
+354300x800000000000000017Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.251{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudpfalsefalse169.254.255.255137netbios-nsfalse169.254.180.25137netbios-ns
+354300x800000000000000016Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse169.254.180.25137netbios-nsfalse169.254.255.255137netbios-ns
+354300x800000000000000015Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea00:20f:0:0:18a2:6e00:e0:ffff55542truee000:fc:4300:6800:7200:6f00:6d00:65005355llmnr
+354300x800000000000000014Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruefe80:0:0:0:e488:b85c:5262:ff86vagrant-2012-r2.local.crowbird.com55542trueff02:0:0:0:0:0:1:35355llmnr
+354300x800000000000000013Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudpfalsefalse10.0.2.255137netbios-nsfalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-ns
+354300x800000000000000012Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.250{42f11c3b-6e19-5c8c-0000-0010eb030000}4SystemNT AUTHORITY\SYSTEMudptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com137netbios-nsfalse10.0.2.255137netbios-ns
+354300x800000000000000011Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.214{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeVAGRANT-2012-R2\vagranttcptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com1139false40.77.226.250443https
+354300x800000000000000010Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.148{42f11c3b-ccaa-5c8f-0000-0010b4e22700}1600C:\Program Files (x86)\Google\Chrome\Application\chrome.exeVAGRANT-2012-R2\vagranttcptruefalse10.0.2.15vagrant-2012-r2.local.crowbird.com1138false40.77.226.250443https
+354300x80000000000000009Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:48.070{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudpfalsefalse10.0.2.15vagrant-2012-r2.local.crowbird.com62141false10.0.2.353domain
+354300x80000000000000008Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:47.847{42f11c3b-0bad-5c8c-0000-0010dfbc0000}924C:\Windows\System32\svchost.exeNT AUTHORITY\NETWORK SERVICEudptruetruea00:20f:0:0:18a2:6e00:e0:ffff62141truea00:203:3000:3000:3000:3000:3000:330053domain
+154100x80000000000000007Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:39.012{42f11c3b-ce03-5c8f-0000-0010e9462a00}4508C:\Windows\System32\wbem\WmiPrvSE.exe6.3.9600.16384 (winblue_rtm.130821-1623)WMI Provider HostMicrosoft® Windows® Operating SystemMicrosoft CorporationC:\Windows\system32\wbem\wmiprvse.exe -EmbeddingC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=5A4C0E82FF95C9FB762D46A696EF9F1B68001C21{42f11c3b-6e1b-5c8c-0000-00102f610000}560C:\Windows\System32\svchost.exeC:\Windows\system32\svchost.exe -k DcomLaunch
+534500x80000000000000006Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.981{42f11c3b-cdf4-5c8f-0000-0010071e2a00}4648C:\Users\vagrant\Downloads\Sysmon.exe
+534500x80000000000000005Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.981{42f11c3b-cdf4-5c8f-0000-0010e61e2a00}4616C:\Users\vagrant\AppData\Local\Temp\Sysmon.exe
+154100x80000000000000004Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.964{42f11c3b-ce01-5c8f-0000-00102c412a00}5028C:\Windows\System32\wbem\unsecapp.exe6.3.9600.16384 (winblue_rtm.130821-1623)Sink to receive asynchronous callbacks for WMI client applicationMicrosoft® Windows® Operating SystemMicrosoft CorporationC:\Windows\system32\wbem\unsecapp.exe -EmbeddingC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=6DF8163A6320B80B60733F9D62E2F39B4B16B678{42f11c3b-6e1b-5c8c-0000-00102f610000}560C:\Windows\System32\svchost.exeC:\Windows\system32\svchost.exe -k DcomLaunch
+154100x80000000000000003Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.949{42f11c3b-ce01-5c8f-0000-0010c73e2a00}4860C:\Windows\Sysmon.exe9.01System activity monitorSysinternals SysmonSysinternals - www.sysinternals.comC:\Windows\Sysmon.exeC:\Windows\system32\NT AUTHORITY\SYSTEM{42f11c3b-6e1a-5c8c-0000-0020e7030000}0x3e70SystemSHA1=AC93C3B38E57A2715572933DBCB2A1C2892DBC5E{42f11c3b-6e1a-5c8c-0000-0010f14d0000}488C:\Windows\System32\services.exeC:\Windows\system32\services.exe
+434400x80000000000000002Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:38.011Started9.014.20
+16341600x80000000000000001Microsoft-Windows-Sysmon/Operationalvagrant-2012-r22019-03-18 16:57:37.933C:\Users\vagrant\Downloads\"C:\Users\vagrant\Downloads\Sysmon.exe" -i -n
diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows.go b/winlogbeat/sys/wineventlog/wineventlog_windows.go
index fed3e42ccf1..3cad7d57548 100644
--- a/winlogbeat/sys/wineventlog/wineventlog_windows.go
+++ b/winlogbeat/sys/wineventlog/wineventlog_windows.go
@@ -28,10 +28,9 @@ import (
"sort"
"syscall"
- "github.com/elastic/beats/v7/libbeat/common"
-
"golang.org/x/sys/windows"
+ "github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/winlogbeat/sys"
)
@@ -74,7 +73,7 @@ func Channels() ([]string, error) {
if err != nil {
return nil, err
}
- defer _EvtClose(handle)
+ defer _EvtClose(handle) //nolint:errcheck // This is just a resource release.
var channels []string
cpBuffer := make([]uint16, 512)
@@ -83,7 +82,7 @@ loop:
var used uint32
err := _EvtNextChannelPath(handle, uint32(len(cpBuffer)), &cpBuffer[0], &used)
if err != nil {
- errno, ok := err.(syscall.Errno)
+ errno, ok := err.(syscall.Errno) //nolint:errorlint // This is an errno or nil.
if ok {
switch errno {
case ERROR_INSUFFICIENT_BUFFER:
@@ -203,7 +202,7 @@ func EventHandles(subscription EvtHandle, maxHandles int) ([]EvtHandle, error) {
// Munge ERROR_INVALID_OPERATION to ERROR_NO_MORE_ITEMS when no handles
// were read. This happens you call the method and there are no events
// to read (i.e. polling).
- if err == ERROR_INVALID_OPERATION && numRead == 0 {
+ if err == ERROR_INVALID_OPERATION && numRead == 0 { //nolint:errorlint // This is an errno or nil.
return nil, ERROR_NO_MORE_ITEMS
}
return nil, err
@@ -241,12 +240,11 @@ func RenderEvent(
// Only a single string is returned when rendering XML.
err = FormatEventString(EvtFormatMessageXml,
eventHandle, providerName, EvtHandle(publisherHandle), lang, renderBuf, out)
-
// Recover by rendering the XML without the RenderingInfo (message string).
if err != nil {
// Do not try to recover from InsufficientBufferErrors because these
// can be retried with a larger buffer.
- if _, ok := err.(sys.InsufficientBufferError); ok {
+ if errors.Is(err, sys.InsufficientBufferError{}) {
return err
}
@@ -256,6 +254,26 @@ func RenderEvent(
return err
}
+// Message reads the event data associated with the EvtHandle and renders
+// and returns the message only.
+func Message(h EvtHandle, buf []byte, pubHandleProvider func(string) sys.MessageFiles) (message string, err error) {
+ providerName, err := evtRenderProviderName(buf, h)
+ if err != nil {
+ return "", err
+ }
+
+ var pub EvtHandle
+ if pubHandleProvider != nil {
+ messageFiles := pubHandleProvider(providerName)
+ if messageFiles.Err == nil {
+ // There is only ever a single handle when using the Windows Event
+ // Log API.
+ pub = EvtHandle(messageFiles.Handles[0].Handle)
+ }
+ }
+ return getMessageStringFromHandle(&PublisherMetadata{Handle: pub}, h, nil)
+}
+
// RenderEventXML renders the event as XML. If the event is already rendered, as
// in a forwarded event whose content type is "RenderedText", then the XML will
// include the RenderingInfo (message). If the event is not rendered then the
@@ -315,7 +333,7 @@ func CreateBookmarkFromXML(bookmarkXML string) (EvtHandle, error) {
// CreateRenderContext creates a render context. Close must be called on
// returned EvtHandle when finished with the handle.
func CreateRenderContext(valuePaths []string, flag EvtRenderContextFlag) (EvtHandle, error) {
- var paths []uintptr
+ paths := make([]uintptr, 0, len(valuePaths))
for _, path := range valuePaths {
utf16, err := syscall.UTF16FromString(path)
if err != nil {
@@ -384,11 +402,12 @@ func FormatEventString(
// Open a publisher handle if one was not provided.
ph := publisherHandle
if ph == 0 {
- ph, err := OpenPublisherMetadata(0, publisher, lang)
+ var err error
+ ph, err = OpenPublisherMetadata(0, publisher, lang)
if err != nil {
return err
}
- defer _EvtClose(ph)
+ defer _EvtClose(ph) //nolint:errcheck // This is just a resource release.
}
// Create a buffer if one was not provided.
@@ -396,7 +415,7 @@ func FormatEventString(
if buffer == nil {
err := _EvtFormatMessage(ph, eventHandle, 0, 0, 0, messageFlag,
0, nil, &bufferUsed)
- if err != nil && err != ERROR_INSUFFICIENT_BUFFER {
+ if err != nil && err != ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil.
return err
}
@@ -408,8 +427,8 @@ func FormatEventString(
err := _EvtFormatMessage(ph, eventHandle, 0, 0, 0, messageFlag,
uint32(len(buffer)/2), &buffer[0], &bufferUsed)
bufferUsed *= 2
- if err == ERROR_INSUFFICIENT_BUFFER {
- return sys.InsufficientBufferError{err, int(bufferUsed)}
+ if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil.
+ return sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)}
}
if err != nil {
return err
@@ -426,7 +445,7 @@ func Publishers() ([]string, error) {
if err != nil {
return nil, fmt.Errorf("failed in EvtOpenPublisherEnum: %w", err)
}
- defer Close(publisherEnumerator)
+ defer Close(publisherEnumerator) //nolint:errcheck // This is just a resource release.
var (
publishers []string
@@ -437,7 +456,7 @@ func Publishers() ([]string, error) {
loop:
for {
if err = _EvtNextPublisherId(publisherEnumerator, uint32(len(buffer)), &buffer[0], &bufferUsed); err != nil {
- switch err {
+ switch err { //nolint:errorlint // This is an errno or nil.
case ERROR_NO_MORE_ITEMS:
break loop
case ERROR_INSUFFICIENT_BUFFER:
@@ -466,7 +485,7 @@ func offset(buffer []byte, reader io.Reader) (uint64, error) {
var err error
switch runtime.GOARCH {
default:
- return 0, fmt.Errorf("Unhandled architecture: %s", runtime.GOARCH)
+ return 0, fmt.Errorf("unhandled architecture: %s", runtime.GOARCH)
case "amd64":
err = binary.Read(reader, binary.LittleEndian, &dataPtr)
if err != nil {
@@ -488,9 +507,15 @@ func offset(buffer []byte, reader io.Reader) (uint64, error) {
bufferPtr := uint64(reflect.ValueOf(&buffer[0]).Pointer())
offset := dataPtr - bufferPtr
+<<<<<<< HEAD
if offset < 0 || offset > uint64(len(buffer)) {
return 0, fmt.Errorf("Invalid pointer %x. Cannot dereference an "+
"address outside of the buffer [%x:%x].", dataPtr, bufferPtr,
+=======
+ if offset > uint64(len(buffer)) {
+ return 0, fmt.Errorf("invalid pointer %x: cannot dereference an "+
+ "address outside of the buffer [%x:%x]", dataPtr, bufferPtr,
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
bufferPtr+uint64(len(buffer)))
}
@@ -503,7 +528,7 @@ func readString(buffer []byte, reader io.Reader) (string, error) {
offset, err := offset(buffer, reader)
if err != nil {
// Ignore NULL values.
- if err == ErrorEvtVarTypeNull {
+ if err == ErrorEvtVarTypeNull { //nolint:errorlint // This is never wrapped.
return "", nil
}
return "", err
@@ -517,11 +542,11 @@ func evtRenderProviderName(renderBuf []byte, eventHandle EvtHandle) (string, err
var bufferUsed, propertyCount uint32
err := _EvtRender(providerNameContext, eventHandle, EvtRenderEventValues,
uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount)
- if err == ERROR_INSUFFICIENT_BUFFER {
- return "", sys.InsufficientBufferError{err, int(bufferUsed)}
+ if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil.
+ return "", sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)}
}
if err != nil {
- return "", fmt.Errorf("evtRenderProviderName %v", err)
+ return "", fmt.Errorf("evtRenderProviderName: %w", err)
}
reader := bytes.NewReader(renderBuf)
@@ -532,14 +557,15 @@ func renderXML(eventHandle EvtHandle, flag EvtRenderFlag, renderBuf []byte, out
var bufferUsed, propertyCount uint32
err := _EvtRender(0, eventHandle, flag, uint32(len(renderBuf)),
&renderBuf[0], &bufferUsed, &propertyCount)
- if err == ERROR_INSUFFICIENT_BUFFER {
- return sys.InsufficientBufferError{err, int(bufferUsed)}
+ if err == ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // This is an errno or nil.
+ return sys.InsufficientBufferError{Cause: err, RequiredSize: int(bufferUsed)}
}
if err != nil {
return err
}
if int(bufferUsed) > len(renderBuf) {
+ //nolint:stylecheck // These are proper nouns.
return fmt.Errorf("Windows EvtRender reported that wrote %d bytes "+
"to the buffer, but the buffer can only hold %d bytes",
bufferUsed, len(renderBuf))
diff --git a/winlogbeat/sys/wineventlog/wineventlog_windows_test.go b/winlogbeat/sys/wineventlog/wineventlog_windows_test.go
index ff4fe566e9c..e6b494e3b24 100644
--- a/winlogbeat/sys/wineventlog/wineventlog_windows_test.go
+++ b/winlogbeat/sys/wineventlog/wineventlog_windows_test.go
@@ -19,79 +19,163 @@ package wineventlog
import (
"bytes"
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "io"
"os"
"path/filepath"
+ "reflect"
+ "strings"
"testing"
+ "github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert"
-)
-
-var sysmonEvtx string
-func init() {
- var err error
- sysmonEvtx, err = filepath.Abs("testdata/sysmon-9.01.evtx")
- if err != nil {
- panic(err)
- }
+ "github.com/elastic/beats/v7/winlogbeat/sys/winevent"
+)
- if _, err = os.Lstat(sysmonEvtx); err != nil {
- panic(err)
- }
-}
+var updateXML = flag.Bool("update", false, "update XML golden files from evtx files in testdata")
+
+func TestWinEventLog(t *testing.T) {
+ for _, test := range []struct {
+ path string
+ events int
+ }{
+ {path: "application-windows-error-reporting.evtx", events: 1},
+ {path: "sysmon-9.01.evtx", events: 32},
+ {path: "ec1.evtx", events: 1}, // eventcreate /id 1000 /t error /l application /d "My custom error event for the application log"
+ {path: "ec2.evtx", events: 1}, // eventcreate /id 999 /t error /l application /so WinWord /d "Winword event 999 happened due to low diskspace"
+ {path: "ec3.evtx", events: 1}, // eventcreate /id 5 /t error /l system /d "Catastrophe!"
+ {path: "ec4.evtx", events: 1}, // eventcreate /id 5 /t error /l system /so Backup /d "Backup failure"
+ {path: "ec3and4.evtx", events: 2}, // ec3 and ec3 exported as a single evtx.
+ {path: "original.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPI test.
+ {path: "experimental.evtx", events: 5}, // a capture from a short generation of the eventlog WindowsEventLogAPIExperimental test.
+ } {
+ t.Run(test.path, func(t *testing.T) {
+ evtx, err := filepath.Abs(filepath.Join("testdata", test.path))
+ if err != nil {
+ t.Fatal(err)
+ }
+ xmlPath := evtx[:len(evtx)-len("evtx")] + "xml"
-func TestEvtOpenLog(t *testing.T) {
- h, err := EvtOpenLog(0, sysmonEvtx, EvtOpenFilePath)
- if err != nil {
- t.Fatal(err)
- }
- defer Close(h)
-}
+ if _, err = os.Lstat(evtx); err != nil {
+ t.Fatal(err)
+ }
-func TestEvtQuery(t *testing.T) {
- h, err := EvtQuery(0, sysmonEvtx, "", EvtQueryFilePath)
- if err != nil {
- t.Fatal(err)
+ t.Run("EvtOpenLog", func(t *testing.T) {
+ h, err := EvtOpenLog(0, evtx, EvtOpenFilePath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Close(h) //nolint:errcheck // This is just a resource release.
+ })
+
+ t.Run("EvtQuery", func(t *testing.T) {
+ h, err := EvtQuery(0, evtx, "", EvtQueryFilePath)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Close(h) //nolint:errcheck // This is just a resource release.
+ })
+
+ t.Run("ReadEvtx", func(t *testing.T) {
+ // Open .evtx file.
+ h, err := EvtQuery(0, evtx, "", EvtQueryFilePath|EvtQueryReverseDirection)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer Close(h) //nolint:errcheck // This is just a resource release.
+
+ // Get handles to events.
+ buf := make([]byte, 32*1024)
+ var out io.Writer
+ if *updateXML {
+ f, err := os.Create(xmlPath)
+ if err != nil {
+ t.Fatalf("failed to create golden file: %v", err)
+ }
+ defer f.Close()
+ out = f
+ } else {
+ out = &bytes.Buffer{}
+ }
+ var count int
+ for {
+ handles, err := EventHandles(h, 8)
+ if err == ERROR_NO_MORE_ITEMS { //nolint:errorlint // This is never wrapped.
+ t.Log(err)
+ break
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Read events.
+ for _, h := range handles {
+ if err = RenderEventXML(h, buf, out); err != nil {
+ t.Fatal(err)
+ }
+ Close(h) //nolint:errcheck // This is just a resource release.
+ fmt.Fprintln(out)
+ count++
+ }
+ }
+ if !*updateXML {
+ f, err := os.Open(xmlPath)
+ if err != nil {
+ t.Fatalf("failed to read golden file: %v", err)
+ }
+ want, err := unmarshalXMLEvents(f)
+ if err != nil {
+ t.Fatalf("failed to unmarshal golden events: %v", err)
+ }
+ got, err := unmarshalXMLEvents(out.(*bytes.Buffer))
+ if err != nil {
+ t.Fatalf("failed to unmarshal obtained events: %v", err)
+ }
+ if !reflect.DeepEqual(want, got) {
+ t.Errorf("unexpected result for %s: got:- want:+\n%s", test.path, cmp.Diff(want, got))
+ }
+ }
+
+ if count != test.events {
+ t.Errorf("expected to read %d events but got %d from %s", test.events, count, test.path)
+ }
+ })
+ })
}
- defer Close(h)
}
-func TestReadEvtx(t *testing.T) {
- // Open .evtx file.
- h, err := EvtQuery(0, sysmonEvtx, "", EvtQueryFilePath|EvtQueryReverseDirection)
- if err != nil {
- t.Fatal(err)
- }
- defer Close(h)
-
- // Get handles to events.
- buf := make([]byte, 32*1024)
- out := new(bytes.Buffer)
- count := 0
+// unmarshalXMLEvents unmarshals a complete set of events from the XML data
+// in the provided io.Reader. GUID values are canonicalised to lowercase.
+func unmarshalXMLEvents(r io.Reader) ([]winevent.Event, error) {
+ var events []winevent.Event
+ decoder := xml.NewDecoder(r)
for {
- handles, err := EventHandles(h, 8)
- if err == ERROR_NO_MORE_ITEMS {
- t.Log(err)
- break
- }
+ var e winevent.Event
+ err := decoder.Decode(&e)
if err != nil {
- t.Fatal(err)
- }
-
- // Read events.
- for _, h := range handles {
- out.Reset()
- if err = RenderEventXML(h, buf, out); err != nil {
- t.Fatal(err)
+ if err != io.EOF { //nolint:errorlint // This is never wrapped.
+ return nil, err
}
- Close(h)
- count++
+ break
}
+ events = append(events, canonical(e))
}
+ return events, nil
+}
- if count != 32 {
- t.Fatal("expected to read 32 events but got", count, "from", sysmonEvtx)
+// canonical return e with its GUID values canonicalised to lower case.
+// Different versions of Windows render these values in different cases; ¯\_(ツ)_/¯
+func canonical(e winevent.Event) winevent.Event {
+ e.Provider.GUID = strings.ToLower(e.Provider.GUID)
+ for i, kv := range e.EventData.Pairs {
+ if strings.Contains(strings.ToLower(kv.Key), "guid") {
+ e.EventData.Pairs[i].Value = strings.ToLower(kv.Value)
+ }
}
+ return e
}
func TestChannels(t *testing.T) {
diff --git a/x-pack/winlogbeat/Jenkinsfile.yml b/x-pack/winlogbeat/Jenkinsfile.yml
index ed42313650e..aed7d37be4d 100644
--- a/x-pack/winlogbeat/Jenkinsfile.yml
+++ b/x-pack/winlogbeat/Jenkinsfile.yml
@@ -28,8 +28,18 @@ stages:
withModule: true
platforms: ## override default labels in this specific stage.
- "windows-2019"
+<<<<<<< HEAD
stage: extended
windows-2022:
+=======
+ stage: mandatory
+ windows-2022:
+ mage: "mage build unitTest"
+ platforms: ## override default labels in this specific stage.
+ - "windows-2022"
+ stage: mandatory
+ windows-2019:
+>>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
mage: "mage build unitTest"
platforms: ## override default labels in this specific stage.
- "windows-2022"
From 74177875eacce087acbc6a86c5633b0634d2c9f4 Mon Sep 17 00:00:00 2001
From: Dan Kortschak
Date: Thu, 31 Mar 2022 21:03:07 +1030
Subject: [PATCH 2/2] fix conflict
---
x-pack/winlogbeat/Jenkinsfile.yml | 5 -----
1 file changed, 5 deletions(-)
diff --git a/x-pack/winlogbeat/Jenkinsfile.yml b/x-pack/winlogbeat/Jenkinsfile.yml
index aed7d37be4d..b0dcd2e1943 100644
--- a/x-pack/winlogbeat/Jenkinsfile.yml
+++ b/x-pack/winlogbeat/Jenkinsfile.yml
@@ -28,10 +28,6 @@ stages:
withModule: true
platforms: ## override default labels in this specific stage.
- "windows-2019"
-<<<<<<< HEAD
- stage: extended
- windows-2022:
-=======
stage: mandatory
windows-2022:
mage: "mage build unitTest"
@@ -39,7 +35,6 @@ stages:
- "windows-2022"
stage: mandatory
windows-2019:
->>>>>>> 34bdc3d468 (winlogbeat: fix event handling for Windows 2022 (#30942))
mage: "mage build unitTest"
platforms: ## override default labels in this specific stage.
- "windows-2022"