diff --git a/.github/workflows/test-artifacts.yml b/.github/workflows/test-artifacts.yml index ab7a033f7a..819e055e22 100644 --- a/.github/workflows/test-artifacts.yml +++ b/.github/workflows/test-artifacts.yml @@ -1319,4 +1319,4 @@ jobs: else cd terraform/eks/addon/gpu fi - terraform destroy -auto-approve \ No newline at end of file + terraform destroy -auto-approve diff --git a/cmd/config-translator/translator_test.go b/cmd/config-translator/translator_test.go index b276fc4632..1b24e4fa5b 100644 --- a/cmd/config-translator/translator_test.go +++ b/cmd/config-translator/translator_test.go @@ -103,6 +103,7 @@ func TestLogWindowsEventConfig(t *testing.T) { checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventName.json", false, expectedErrorMap) expectedErrorMap1 := map[string]int{} expectedErrorMap1["required"] = 2 + expectedErrorMap1["number_any_of"] = 1 checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventNameAndLevel.json", false, expectedErrorMap1) expectedErrorMap2 := map[string]int{} expectedErrorMap2["invalid_type"] = 1 @@ -110,6 +111,18 @@ func TestLogWindowsEventConfig(t *testing.T) { expectedErrorMap3 := map[string]int{} expectedErrorMap3["enum"] = 1 checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventFormatType.json", false, expectedErrorMap3) + + //New tests for event_ids feature + checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventFormatType.json", false, expectedErrorMap3) + expectedErrorMap4 := map[string]int{} + expectedErrorMap4["invalid_type"] = 1 + checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json", false, expectedErrorMap4) + + expectedErrorMap5 := map[string]int{} + expectedErrorMap5["required"] = 1 + expectedErrorMap5["number_any_of"] = 1 + checkIfSchemaValidateAsExpected(t, "../../translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json", false, expectedErrorMap5) + } func TestMetricsConfig(t *testing.T) { @@ -198,7 +211,9 @@ func TestSampleConfigSchema(t *testing.T) { for _, file := range files { if re.MatchString(file.Name()) { t.Logf("Validating ../../translator/tocwconfig/sampleConfig/%s\n", file.Name()) + checkIfSchemaValidateAsExpected(t, "../../translator/tocwconfig/sampleConfig/"+file.Name(), true, map[string]int{}) + t.Logf("Validated ../../translator/tocwconfig/sampleConfig/%s\n", file.Name()) } } diff --git a/plugins/inputs/windows_event_log/windows_event_log.go b/plugins/inputs/windows_event_log/windows_event_log.go index 2cf4cb8786..70eafab377 100644 --- a/plugins/inputs/windows_event_log/windows_event_log.go +++ b/plugins/inputs/windows_event_log/windows_event_log.go @@ -31,6 +31,7 @@ var startOnlyOnce sync.Once type EventConfig struct { Name string `toml:"event_name"` Levels []string `toml:"event_levels"` + EventIDs []int `toml:"event_ids"` RenderFormat string `toml:"event_format"` BatchReadSize int `toml:"batch_read_size"` LogGroupName string `toml:"log_group_name"` @@ -39,7 +40,6 @@ type EventConfig struct { Destination string `toml:"destination"` Retention int `toml:"retention_in_days"` } - type Plugin struct { FileStateFolder string `toml:"file_state_folder"` Events []EventConfig `toml:"event_config"` @@ -61,6 +61,7 @@ func (s *Plugin) SampleConfig() string { [[inputs.windows_event_log.event_config]] event_name = "System" event_levels = ["2", "3"] + event_ids = [1001, 1002] batch_read_size = 1 log_group_name = "System" log_stream_name = "STREAM_NAME" @@ -106,6 +107,7 @@ func (s *Plugin) Start(acc telegraf.Accumulator) error { eventLog := wineventlog.NewEventLog( eventConfig.Name, eventConfig.Levels, + eventConfig.EventIDs, eventConfig.LogGroupName, eventConfig.LogStreamName, eventConfig.RenderFormat, diff --git a/plugins/inputs/windows_event_log/wineventlog/utils.go b/plugins/inputs/windows_event_log/wineventlog/utils.go index e903670dc1..716b5eaf26 100644 --- a/plugins/inputs/windows_event_log/wineventlog/utils.go +++ b/plugins/inputs/windows_event_log/wineventlog/utils.go @@ -1,29 +1,18 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT -//go:build windows -// +build windows - package wineventlog import ( - "bytes" "fmt" - "io" - "log" - "strconv" - "strings" - "syscall" "time" - - "golang.org/x/text/encoding/unicode" - "golang.org/x/text/transform" ) const ( bookmarkTemplate = `` eventLogQueryTemplate = `` eventLogLevelFilter = "Level='%s'" + eventLogeventIDFilter = "EventID='%d'" eventIgnoreOldFilter = "TimeCreated[timediff(@SystemTime) <= %d]" emptySpaceScanLength = 100 UnknownBytesPerCharacter = 0 @@ -36,34 +25,7 @@ const ( UNKNOWN = "UNKNOWN" ) -var NumberOfBytesPerCharacter = UnknownBytesPerCharacter - -func RenderEventXML(eventHandle EvtHandle, renderBuf []byte) ([]byte, error) { - var bufferUsed, propertyCount uint32 - - if err := EvtRender(0, eventHandle, EvtRenderEventXml, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount); err != nil { - return nil, fmt.Errorf("error when rendering events. Details: %v", err) - } - - // Per MSDN as of Mar 14th 2022(https://docs.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtrender) - // EvtRender function is still returning buffer used as BYTES, not characters. So keep using utf16ToUTF8Bytes() - return utf16ToUTF8Bytes(renderBuf, bufferUsed) -} - -func CreateBookmark(channel string, recordID uint64) (h EvtHandle, err error) { - xml := fmt.Sprintf(bookmarkTemplate, channel, recordID) - p, err := syscall.UTF16PtrFromString(xml) - if err != nil { - return 0, err - } - h, err = EvtCreateBookmark(p) - if err != nil { - return 0, fmt.Errorf("error when creating a bookmark. Details: %v", err) - } - return h, nil -} - -func CreateQuery(path string, levels []string) (*uint16, error) { +func createFilterQuery(levels []string, eventIDs []int) string { var filterLevels string for _, level := range levels { if filterLevels == "" { @@ -73,149 +35,34 @@ func CreateQuery(path string, levels []string) (*uint16, error) { } } - //Ignore events older than 2 weeks - cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds() - ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond)) - if filterLevels != "" { - filterLevels = "*[System[(" + filterLevels + ") and " + ignoreOlderThanTwoWeeksFilter + "]]" - } else { - filterLevels = "*[System[" + ignoreOlderThanTwoWeeksFilter + "]]" - } - - xml := fmt.Sprintf(eventLogQueryTemplate, path, filterLevels) - return syscall.UTF16PtrFromString(xml) -} - -func utf16ToUTF8Bytes(in []byte, length uint32) ([]byte, error) { - - i := length - - if length%2 != 0 { - i = length - 1 - } - - for ; i-2 > 0; i -= 2 { - v1 := uint16(in[i-2]) | uint16(in[i-1])<<8 - // Stop at non-null char. - if v1 != 0 { - break - } - } - - win16be := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM) - utf16bom := unicode.BOMOverride(win16be.NewDecoder()) - unicodeReader := transform.NewReader(bytes.NewReader(in[:i]), utf16bom) - decoded, err := io.ReadAll(unicodeReader) - return decoded, err -} - -func UTF16ToUTF8BytesForWindowsEventBuffer(in []byte, length uint32) ([]byte, error) { - // Since Windows server 2022, the returned value of used buffer represents for double bytes char count, - // which is half of the actual buffer used by byte(what older Windows OS returns), checking if the length - //land on the end of used buffer, if no, double it. - if NumberOfBytesPerCharacter == UnknownBytesPerCharacter { - if isTheEndOfContent(in, length) { - log.Printf("I! Buffer used: %d is returning as single byte character count", length) - NumberOfBytesPerCharacter = 1 + //EventID filtering + var filterEventIDs string + for i, eventID := range eventIDs { + if i == 0 { + filterEventIDs = fmt.Sprintf(eventLogeventIDFilter, eventID) } else { - log.Printf("I! Buffer used: %d is returning as double byte character count, doubling it to get the whole buffer content.", length) - NumberOfBytesPerCharacter = 2 - } - } - - i := int(length) * NumberOfBytesPerCharacter - - if i > cap(in) { - i = cap(in) - } - - return utf16ToUTF8Bytes(in, uint32(i)) -} - -func isTheEndOfContent(in []byte, length uint32) bool { - // scan next (emptySpaceScanLength) bytes, if any of them is none '0', return false - i := int(length) - - if i%2 != 0 { - i -= 1 - } - max := len(in) - if i+emptySpaceScanLength < max { - max = i + emptySpaceScanLength - } - - for ; i < max-2; i += 2 { - v1 := uint16(in[i+2]) | uint16(in[i+1])<<8 - // Stop at non-null char. - if v1 != 0 { - return false + filterEventIDs = filterEventIDs + " or " + fmt.Sprintf(eventLogeventIDFilter, eventID) } } - return true -} -func WindowsEventLogLevelName(levelId int32) string { - switch levelId { - case 1: - return CRITICAL - case 2: - return ERROR - case 3: - return WARNING - case 0, 4: - return INFORMATION - case 5: - return VERBOSE - default: - return UNKNOWN + //query results + var query string + if filterLevels != "" && filterEventIDs != "" { + query = "(" + filterLevels + ") and (" + filterEventIDs + ")" + } else if filterLevels != "" && filterEventIDs == "" { + query = "(" + filterLevels + ")" + } else if filterLevels == "" && filterEventIDs != "" { + query = "(" + filterEventIDs + ")" } -} - -// insertPlaceholderValues formats the message with the correct values if we see those data -// in evtDataValues. -// -// In some cases wevtapi does not insert values when formatting the message. The message -// will contain insertion string placeholders, of the form %n, where %1 indicates the first -// insertion string, and so on. Noted that wevtapi start the index with 1. -// https://learn.microsoft.com/en-us/windows/win32/eventlog/event-identifiers#insertion-strings -func insertPlaceholderValues(rawMessage string, evtDataValues []Datum) string { - if len(evtDataValues) == 0 || len(rawMessage) == 0 { - return rawMessage - } - var sb strings.Builder - prevIndex := 0 - searchingIndex := false - for i, c := range rawMessage { - // found `%` previously. Determine the index number from the following character(s) - if searchingIndex && (c > '9' || c < '0') { - // Convert the Slice since the last `%` and see if it's a valid number. - ind, err := strconv.Atoi(rawMessage[prevIndex+1 : i]) - // If the index is in [1 - len(evtDataValues)], get it from evtDataValues. - if err == nil && ind <= len(evtDataValues) && ind > 0 { - sb.WriteString(evtDataValues[ind-1].Value) - } else { - sb.WriteString(rawMessage[prevIndex:i]) - } - prevIndex = i - // In case of consecutive `%`, continue searching for the next index - if c != '%' { - searchingIndex = false - } - } else { - if c == '%' { - sb.WriteString(rawMessage[prevIndex:i]) - searchingIndex = true - prevIndex = i - } - } - } - // handle the slice since the last `%` to the end of rawMessage - ind, err := strconv.Atoi(rawMessage[prevIndex+1:]) - if searchingIndex && err == nil && ind <= len(evtDataValues) && ind > 0 { - sb.WriteString(evtDataValues[ind-1].Value) + //Ignore events older than 2 weeks + cutOffPeriod := (time.Hour * 24 * 14).Nanoseconds() + ignoreOlderThanTwoWeeksFilter := fmt.Sprintf(eventIgnoreOldFilter, cutOffPeriod/int64(time.Millisecond)) + if query != "" { + query = "*[System[" + query + " and " + ignoreOlderThanTwoWeeksFilter + "]]" } else { - sb.WriteString(rawMessage[prevIndex:]) + query = "*[System[" + ignoreOlderThanTwoWeeksFilter + "]]" } - return sb.String() + + return query } diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_test.go b/plugins/inputs/windows_event_log/wineventlog/utils_test.go index 40586504d3..89cb25de82 100644 --- a/plugins/inputs/windows_event_log/wineventlog/utils_test.go +++ b/plugins/inputs/windows_event_log/wineventlog/utils_test.go @@ -1,134 +1,51 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT -//go:build windows -// +build windows - package wineventlog import ( - "encoding/hex" "testing" "github.com/stretchr/testify/assert" ) -func TestPayload_Value(t *testing.T) { - // one null test - resetState() - originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000" - data, _ := hex.DecodeString(originalHexStr) - bufferUsed := len(data) - bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str := string(bytes[:]) - assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) - - // odd bytes test - originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000" - data, _ = hex.DecodeString(originalHexStr) - bufferUsed = len(data) - bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str = string(bytes[:]) - assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) - - // two nulls test - originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000000000" - data, _ = hex.DecodeString(originalHexStr) - bufferUsed = len(data) - bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str = string(bytes[:]) - assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) - -} - -func TestDecodingWithDifferentBufferUsedReturned(t *testing.T) { - // one null test - resetState() - originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000" - data, _ := hex.DecodeString(originalHexStr) - bufferUsed := len(data) / 2 - bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str := string(bytes[:]) - assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) - - // odd bytes test - originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000" - data, _ = hex.DecodeString(originalHexStr) - bufferUsed = len(data) / 2 - bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str = string(bytes[:]) - assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) - -} - -func TestFullBufferUsedWithHalfUsedSizeReturned(t *testing.T) { - resetState() - cap := 1 << 10 - data := make([]byte, cap) - data[0] = 'a' - for i := 2; i < cap; i *= 2 { - copy(data[i:], data[:i]) - } - bufferUsed := cap / 2 - - bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) - str := string(bytes[:]) - assert.Equal(t, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", str) - assert.Equal(t, bufferUsed, len(str)) -} - -func TestInsertPlaceholderValues(t *testing.T) { - evtDataValues := []Datum{ - {"value_1"}, {"value_2"}, {"value_3"}, {"value_4"}, - } +func TestCreateFilterQuery(t *testing.T) { tests := []struct { name string - message string - expected string + levels []string + eventIDs []int + want string }{ { - "Placeholders %{number} should be replaced by insertion strings", - "Service %1 in region %3 stop at %2", - "Service value_1 in region value_3 stop at value_2", - }, - { - "String without a placeholder should remain the same after insertion", - "This is a sentence without placeholders", - "This is a sentence without placeholders", - }, - { - "Empty string should remain the same", - "", - "", - }, - { - "Index should start from 1 and less than or equal to the amount of values in event data", - "%0 %3 %5", - "%0 value_3 %5", + name: "levels_Test", + levels: []string{"Error", "Critical"}, + eventIDs: []int{}, + want: "*[System[(Level='Error' or Level='Critical') and TimeCreated[timediff(@SystemTime) <= 1209600000]]]", }, { - "Handle consecutive % characters", - "%1 %%3% %2", - "value_1 %value_3% value_2", + name: "EventID_Test", + levels: []string{}, + eventIDs: []int{1001, 1002}, + want: "*[System[(EventID='1001' or EventID='1002') and TimeCreated[timediff(@SystemTime) <= 1209600000]]]", }, { - "Handle % character at the end of message", - "%3 %2%", - "value_3 value_2%", + name: "levels_EventID_Test", + levels: []string{"Error", "Critical"}, + eventIDs: []int{4625, 4624}, + want: "*[System[(Level='Error' or Level='Critical') and (EventID='4625' or EventID='4624') and TimeCreated[timediff(@SystemTime) <= 1209600000]]]", }, { - "Characters after a % other than numbers should be ignored", - "%foo, %foo1, %#$%^&1", - "%foo, %foo1, %#$%^&1", + name: "no_Input", + levels: []string{}, + eventIDs: []int{}, + want: "*[System[TimeCreated[timediff(@SystemTime) <= 1209600000]]]", }, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - assert.Equal(t, tc.expected, insertPlaceholderValues(tc.message, evtDataValues)) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := createFilterQuery(tt.levels, tt.eventIDs) + assert.Equal(t, tt.want, got) + }) } } - -func resetState() { - NumberOfBytesPerCharacter = 0 -} diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_windows.go b/plugins/inputs/windows_event_log/wineventlog/utils_windows.go new file mode 100644 index 0000000000..4f02167de2 --- /dev/null +++ b/plugins/inputs/windows_event_log/wineventlog/utils_windows.go @@ -0,0 +1,189 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT + +//go:build windows +// +build windows + +package wineventlog + +import ( + "bytes" + "fmt" + "io" + "log" + "strconv" + "strings" + "syscall" + + "golang.org/x/text/encoding/unicode" + "golang.org/x/text/transform" +) + +var NumberOfBytesPerCharacter = UnknownBytesPerCharacter + +func RenderEventXML(eventHandle EvtHandle, renderBuf []byte) ([]byte, error) { + var bufferUsed, propertyCount uint32 + + if err := EvtRender(0, eventHandle, EvtRenderEventXml, uint32(len(renderBuf)), &renderBuf[0], &bufferUsed, &propertyCount); err != nil { + return nil, fmt.Errorf("error when rendering events. Details: %v", err) + } + + // Per MSDN as of Mar 14th 2022(https://docs.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtrender) + // EvtRender function is still returning buffer used as BYTES, not characters. So keep using utf16ToUTF8Bytes() + return utf16ToUTF8Bytes(renderBuf, bufferUsed) +} + +func CreateBookmark(channel string, recordID uint64) (h EvtHandle, err error) { + xml := fmt.Sprintf(bookmarkTemplate, channel, recordID) + p, err := syscall.UTF16PtrFromString(xml) + if err != nil { + return 0, err + } + h, err = EvtCreateBookmark(p) + if err != nil { + return 0, fmt.Errorf("error when creating a bookmark. Details: %v", err) + } + return h, nil +} + +func CreateQuery(path string, levels []string, eventIDs []int) (*uint16, error) { + + query := createFilterQuery(levels, eventIDs) + + xml := fmt.Sprintf(eventLogQueryTemplate, path, query) + return syscall.UTF16PtrFromString(xml) +} + +func utf16ToUTF8Bytes(in []byte, length uint32) ([]byte, error) { + + i := length + + if length%2 != 0 { + i = length - 1 + } + + for ; i-2 > 0; i -= 2 { + v1 := uint16(in[i-2]) | uint16(in[i-1])<<8 + // Stop at non-null char. + if v1 != 0 { + break + } + } + + win16be := unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM) + utf16bom := unicode.BOMOverride(win16be.NewDecoder()) + unicodeReader := transform.NewReader(bytes.NewReader(in[:i]), utf16bom) + decoded, err := io.ReadAll(unicodeReader) + return decoded, err +} + +func UTF16ToUTF8BytesForWindowsEventBuffer(in []byte, length uint32) ([]byte, error) { + // Since Windows server 2022, the returned value of used buffer represents for double bytes char count, + // which is half of the actual buffer used by byte(what older Windows OS returns), checking if the length + //land on the end of used buffer, if no, double it. + if NumberOfBytesPerCharacter == UnknownBytesPerCharacter { + if isTheEndOfContent(in, length) { + log.Printf("I! Buffer used: %d is returning as single byte character count", length) + NumberOfBytesPerCharacter = 1 + } else { + log.Printf("I! Buffer used: %d is returning as double byte character count, doubling it to get the whole buffer content.", length) + NumberOfBytesPerCharacter = 2 + } + } + + i := int(length) * NumberOfBytesPerCharacter + + if i > cap(in) { + i = cap(in) + } + + return utf16ToUTF8Bytes(in, uint32(i)) +} + +func isTheEndOfContent(in []byte, length uint32) bool { + // scan next (emptySpaceScanLength) bytes, if any of them is none '0', return false + i := int(length) + + if i%2 != 0 { + i -= 1 + } + max := len(in) + if i+emptySpaceScanLength < max { + max = i + emptySpaceScanLength + } + + for ; i < max-2; i += 2 { + v1 := uint16(in[i+2]) | uint16(in[i+1])<<8 + // Stop at non-null char. + if v1 != 0 { + return false + } + } + return true +} + +func WindowsEventLogLevelName(levelId int32) string { + switch levelId { + case 1: + return CRITICAL + case 2: + return ERROR + case 3: + return WARNING + case 0, 4: + return INFORMATION + case 5: + return VERBOSE + default: + return UNKNOWN + } +} + +// insertPlaceholderValues formats the message with the correct values if we see those data +// in evtDataValues. +// +// In some cases wevtapi does not insert values when formatting the message. The message +// will contain insertion string placeholders, of the form %n, where %1 indicates the first +// insertion string, and so on. Noted that wevtapi start the index with 1. +// https://learn.microsoft.com/en-us/windows/win32/eventlog/event-identifiers#insertion-strings +func insertPlaceholderValues(rawMessage string, evtDataValues []Datum) string { + if len(evtDataValues) == 0 || len(rawMessage) == 0 { + return rawMessage + } + var sb strings.Builder + prevIndex := 0 + searchingIndex := false + for i, c := range rawMessage { + // found `%` previously. Determine the index number from the following character(s) + if searchingIndex && (c > '9' || c < '0') { + // Convert the Slice since the last `%` and see if it's a valid number. + ind, err := strconv.Atoi(rawMessage[prevIndex+1 : i]) + // If the index is in [1 - len(evtDataValues)], get it from evtDataValues. + if err == nil && ind <= len(evtDataValues) && ind > 0 { + sb.WriteString(evtDataValues[ind-1].Value) + } else { + sb.WriteString(rawMessage[prevIndex:i]) + } + prevIndex = i + // In case of consecutive `%`, continue searching for the next index + if c != '%' { + searchingIndex = false + } + } else { + if c == '%' { + sb.WriteString(rawMessage[prevIndex:i]) + searchingIndex = true + prevIndex = i + } + + } + } + // handle the slice since the last `%` to the end of rawMessage + ind, err := strconv.Atoi(rawMessage[prevIndex+1:]) + if searchingIndex && err == nil && ind <= len(evtDataValues) && ind > 0 { + sb.WriteString(evtDataValues[ind-1].Value) + } else { + sb.WriteString(rawMessage[prevIndex:]) + } + return sb.String() +} diff --git a/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go b/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go new file mode 100644 index 0000000000..40586504d3 --- /dev/null +++ b/plugins/inputs/windows_event_log/wineventlog/utils_windows_test.go @@ -0,0 +1,134 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT + +//go:build windows +// +build windows + +package wineventlog + +import ( + "encoding/hex" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPayload_Value(t *testing.T) { + // one null test + resetState() + originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000" + data, _ := hex.DecodeString(originalHexStr) + bufferUsed := len(data) + bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str := string(bytes[:]) + assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) + + // odd bytes test + originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000" + data, _ = hex.DecodeString(originalHexStr) + bufferUsed = len(data) + bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str = string(bytes[:]) + assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) + + // two nulls test + originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000000000" + data, _ = hex.DecodeString(originalHexStr) + bufferUsed = len(data) + bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str = string(bytes[:]) + assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) + +} + +func TestDecodingWithDifferentBufferUsedReturned(t *testing.T) { + // one null test + resetState() + originalHexStr := "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e000000" + data, _ := hex.DecodeString(originalHexStr) + bufferUsed := len(data) / 2 + bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str := string(bytes[:]) + assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) + + // odd bytes test + originalHexStr = "3c004500760065006e007400200078006d006c006e0073003d00270068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00770069006e002f0032003000300034002f00300038002f006500760065006e00740073002f006500760065006e00740027003e003c00530079007300740065006d003e003c00500072006f007600690064006500720020004e0061006d0065003d0027004d006900630072006f0073006f00660074002d00570069006e0064006f00770073002d00530065006300750072006900740079002d004100750064006900740069006e0067002700200047007500690064003d0027007b00350034003800340039003600320035002d0035003400370038002d0034003900390034002d0041003500420041002d003300450033004200300033003200380043003300300044007d0027002f003e003c004500760065006e007400490044003e0034003600320035003c002f004500760065006e007400490044003e003c00560065007200730069006f006e003e0030003c002f00560065007200730069006f006e003e003c004c006500760065006c003e0030003c002f004c006500760065006c003e003c005400610073006b003e00310032003500340034003c002f005400610073006b003e003c004f00700063006f00640065003e0030003c002f004f00700063006f00640065003e003c004b006500790077006f007200640073003e003000780038003000310030003000300030003000300030003000300030003000300030003c002f004b006500790077006f007200640073003e003c00540069006d00650043007200650061007400650064002000530079007300740065006d00540069006d0065003d00270032003000310039002d00300035002d00300035005400320033003a00310032003a00330037002e003300340039003400370036003100300030005a0027002f003e003c004500760065006e0074005200650063006f0072006400490044003e003600390034003600370034003c002f004500760065006e0074005200650063006f0072006400490044003e003c0043006f007200720065006c006100740069006f006e00200041006300740069007600690074007900490044003d0027007b00320035003200320035004600410031002d0044004100420039002d0030003000300031002d0041003600350046002d003200320032003500420039004400410044003400300031007d0027002f003e003c0045007800650063007500740069006f006e002000500072006f006300650073007300490044003d00270038003000340027002000540068007200650061006400490044003d002700310030003800300027002f003e003c004300680061006e006e0065006c003e00530065006300750072006900740079003c002f004300680061006e006e0065006c003e003c0043006f006d00700075007400650072003e0045004300320041004d0041005a002d0035004a00360049004600530046003c002f0043006f006d00700075007400650072003e003c00530065006300750072006900740079002f003e003c002f00530079007300740065006d003e003c004500760065006e00740044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a00650063007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740055007300650072004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a0065006300740044006f006d00610069006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005300750062006a006500630074004c006f0067006f006e004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700540061007200670065007400550073006500720053006900640027003e0053002d0031002d0030002d0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740055007300650072004e0061006d00650027003e00410044004d0049004e004900530054005200410054004f0052003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270054006100720067006500740044006f006d00610069006e004e0061006d00650027003e003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007400610074007500730027003e0030007800630030003000300030003000360064003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004600610069006c0075007200650052006500610073006f006e0027003e002500250032003300310033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270053007500620053007400610074007500730027003e0030007800630030003000300030003000360061003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00540079007000650027003e0033003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006f0067006f006e00500072006f0063006500730073004e0061006d00650027003e004e0074004c006d0053007300700020003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700410075007400680065006e007400690063006100740069006f006e005000610063006b006100670065004e0061006d00650027003e004e0054004c004d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270057006f0072006b00730074006100740069006f006e004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027005400720061006e0073006d00690074007400650064005300650072007600690063006500730027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004c006d005000610063006b006100670065004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004b00650079004c0065006e0067007400680027003e0030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004900640027003e003000780030003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d002700500072006f0063006500730073004e0061006d00650027003e002d003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d00270049007000410064006400720065007300730027003e003100340036002e00350036002e0036002e003100360036003c002f0044006100740061003e003c00440061007400610020004e0061006d0065003d0027004900700050006f007200740027003e0030003c002f0044006100740061003e003c002f004500760065006e00740044006100740061003e003c002f004500760065006e0074003e00000000" + data, _ = hex.DecodeString(originalHexStr) + bufferUsed = len(data) / 2 + bytes, _ = UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str = string(bytes[:]) + assert.Equal(t, "4625001254400x8010000000000000694674SecurityEC2AMAZ-5J6IFSFS-1-0-0--0x0S-1-0-0ADMINISTRATOR0xc000006d%%23130xc000006a3NtLmSsp NTLM---00x0-146.56.6.1660", str) + +} + +func TestFullBufferUsedWithHalfUsedSizeReturned(t *testing.T) { + resetState() + cap := 1 << 10 + data := make([]byte, cap) + data[0] = 'a' + for i := 2; i < cap; i *= 2 { + copy(data[i:], data[:i]) + } + bufferUsed := cap / 2 + + bytes, _ := UTF16ToUTF8BytesForWindowsEventBuffer(data, uint32(bufferUsed)) + str := string(bytes[:]) + assert.Equal(t, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", str) + assert.Equal(t, bufferUsed, len(str)) +} + +func TestInsertPlaceholderValues(t *testing.T) { + evtDataValues := []Datum{ + {"value_1"}, {"value_2"}, {"value_3"}, {"value_4"}, + } + tests := []struct { + name string + message string + expected string + }{ + { + "Placeholders %{number} should be replaced by insertion strings", + "Service %1 in region %3 stop at %2", + "Service value_1 in region value_3 stop at value_2", + }, + { + "String without a placeholder should remain the same after insertion", + "This is a sentence without placeholders", + "This is a sentence without placeholders", + }, + { + "Empty string should remain the same", + "", + "", + }, + { + "Index should start from 1 and less than or equal to the amount of values in event data", + "%0 %3 %5", + "%0 value_3 %5", + }, + { + "Handle consecutive % characters", + "%1 %%3% %2", + "value_1 %value_3% value_2", + }, + { + "Handle % character at the end of message", + "%3 %2%", + "value_3 value_2%", + }, + { + "Characters after a % other than numbers should be ignored", + "%foo, %foo1, %#$%^&1", + "%foo, %foo1, %#$%^&1", + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + assert.Equal(t, tc.expected, insertPlaceholderValues(tc.message, evtDataValues)) + }) + } +} + +func resetState() { + NumberOfBytesPerCharacter = 0 +} diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go index 1ed6d12b78..39f1e7f122 100644 --- a/plugins/inputs/windows_event_log/wineventlog/wineventlog.go +++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog.go @@ -49,6 +49,7 @@ func (e *wevtAPIError) Error() string { type windowsEventLog struct { name string levels []string + eventIDs []int logGroupName string logStreamName string logGroupClass string @@ -66,10 +67,11 @@ type windowsEventLog struct { resubscribeCh chan struct{} } -func NewEventLog(name string, levels []string, logGroupName, logStreamName, renderFormat, destination string, stateManager state.FileRangeManager, maximumToRead int, retention int, logGroupClass string) *windowsEventLog { +func NewEventLog(name string, levels []string, eventIDs []int, logGroupName, logStreamName, renderFormat, destination string, stateManager state.FileRangeManager, maximumToRead int, retention int, logGroupClass string) *windowsEventLog { eventLog := &windowsEventLog{ name: name, levels: levels, + eventIDs: eventIDs, logGroupName: logGroupName, logStreamName: logStreamName, logGroupClass: logGroupClass, @@ -210,7 +212,7 @@ func (w *windowsEventLog) open() error { if err != nil { return err } - query, err := CreateQuery(w.name, w.levels) + query, err := CreateQuery(w.name, w.levels, w.eventIDs) if err != nil { return err } diff --git a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go index 047bba571c..42c9a731c7 100644 --- a/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go +++ b/plugins/inputs/windows_event_log/wineventlog/wineventlog_test.go @@ -24,6 +24,7 @@ var ( NAME = "Application" // 2 is ERROR LEVELS = []string{"2"} + EVENTIDS = []int{777} GROUP_NAME = "fake" STREAM_NAME = "fake" RENDER_FMT = FormatPlainText @@ -36,7 +37,7 @@ var ( // TestNewEventLog verifies constructor's default values. func TestNewEventLog(t *testing.T) { - elog := newTestEventLog(t, NAME, LEVELS) + elog := newTestEventLog(t, NAME, LEVELS, EVENTIDS) assert.Equal(t, NAME, elog.name) assert.Equal(t, uint64(0), elog.eventOffset) assert.Zero(t, elog.eventHandle) @@ -46,23 +47,27 @@ func TestNewEventLog(t *testing.T) { // And fails with invalid inputs. func TestOpen(t *testing.T) { // Happy path. - elog := newTestEventLog(t, NAME, LEVELS) + elog := newTestEventLog(t, NAME, LEVELS, EVENTIDS) assert.NoError(t, elog.Open()) assert.NotZero(t, elog.eventHandle) assert.NoError(t, elog.Close()) // Bad event log source name does not cause Open() to fail. // But eventHandle will be 0 and Close() will fail because of it. - elog = newTestEventLog(t, "FakeBadElogName", LEVELS) + elog = newTestEventLog(t, "FakeBadElogName", LEVELS, EVENTIDS) assert.NoError(t, elog.Open()) assert.Zero(t, elog.eventHandle) assert.Error(t, elog.Close()) // bad LEVELS does not cause Open() to fail. - elog = newTestEventLog(t, NAME, []string{"498"}) + elog = newTestEventLog(t, NAME, []string{"498"}, EVENTIDS) + assert.NoError(t, elog.Open()) + assert.NotZero(t, elog.eventHandle) + assert.NoError(t, elog.Close()) + elog = newTestEventLog(t, NAME, LEVELS, []int{98698}) assert.NoError(t, elog.Open()) assert.NotZero(t, elog.eventHandle) assert.NoError(t, elog.Close()) // bad wlog.eventOffset does not cause Open() to fail. - elog = newTestEventLog(t, NAME, []string{"498"}) + elog = newTestEventLog(t, NAME, []string{"498"}, EVENTIDS) elog.eventOffset = 9987 assert.NoError(t, elog.Open()) assert.NotZero(t, elog.eventHandle) @@ -72,7 +77,7 @@ func TestOpen(t *testing.T) { // TestReadGoodSource will verify we can read events written by a registered // event log source. func TestReadGoodSource(t *testing.T) { - elog := newTestEventLog(t, NAME, LEVELS) + elog := newTestEventLog(t, NAME, LEVELS, EVENTIDS) assert.NoError(t, elog.Open()) seekToEnd(t, elog) writeEvents(t, 10, true, "CWA_UnitTest111", 777) @@ -84,7 +89,7 @@ func TestReadGoodSource(t *testing.T) { // TestReadBadSource will verify that we cannot read events written by an // unregistered event log source. func TestReadBadSource(t *testing.T) { - elog := newTestEventLog(t, NAME, LEVELS) + elog := newTestEventLog(t, NAME, LEVELS, EVENTIDS) assert.NoError(t, elog.Open()) seekToEnd(t, elog) writeEvents(t, 10, false, "CWA_UnitTest222", 888) @@ -97,7 +102,7 @@ func TestReadBadSource(t *testing.T) { // registered event log source, even if the batch contains events from an // unregistered source too. func TestReadWithBothSources(t *testing.T) { - elog := newTestEventLog(t, NAME, LEVELS) + elog := newTestEventLog(t, NAME, LEVELS, EVENTIDS) assert.NoError(t, elog.Open()) seekToEnd(t, elog) writeEvents(t, 10, true, "CWA_UnitTest111", 777) @@ -135,12 +140,13 @@ func writeEvents(t *testing.T, msgCount int, doRegister bool, logSrc string, eve wlog, err := eventlog.Open(logSrc) assert.NoError(t, err) for i := 0; i < msgCount; i++ { - wlog.Error(eventId, fmt.Sprintf("CWA_UnitTest event msg %v", i)) + err = wlog.Error(eventId, fmt.Sprintf("CWA_UnitTest event msg %v", i)) + assert.NoError(t, err) } err = wlog.Close() assert.NoError(t, err) // Must sleep after wlog.Error() otherwise elog.read() will not see results. - time.Sleep(1 * time.Second) + time.Sleep(3 * time.Second) } // readHelper reads all events (since last read). @@ -171,13 +177,13 @@ func checkEvents(t *testing.T, records []*windowsEventLogRecord, substring strin assert.Equal(t, count, found, "expected %v, %v, actual %v", substring, count, found) } -func newTestEventLog(t *testing.T, name string, levels []string) *windowsEventLog { +func newTestEventLog(t *testing.T, name string, levels []string, eventids []int) *windowsEventLog { t.Helper() manager := state.NewFileRangeManager(state.ManagerConfig{ StateFileDir: t.TempDir(), StateFilePrefix: logscommon.WindowsEventLogPrefix, Name: GROUP_NAME + "_" + STREAM_NAME + "_" + name, }) - return NewEventLog(name, levels, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST, + return NewEventLog(name, levels, eventids, GROUP_NAME, STREAM_NAME, RENDER_FMT, DEST, manager, BATCH_SIZE, RETENTION, LOG_GROUP_CLASS) } diff --git a/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json b/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json new file mode 100644 index 0000000000..10413f58a5 --- /dev/null +++ b/translator/config/sampleSchema/invalidLogWindowsEventsWithInvalidEventIdsType.json @@ -0,0 +1,17 @@ +{ + "logs": { + "logs_collected": { + "windows_events": { + "collect_list": [ + { + "event_name": "System", + "event_ids": "4562", + "log_group_name": "System", + "log_stream_name": "System" + } + ] + } + }, + "log_stream_name": "LOG_STREAM_NAME" + } +} \ No newline at end of file diff --git a/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json b/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json new file mode 100644 index 0000000000..be0ccd9e02 --- /dev/null +++ b/translator/config/sampleSchema/invalidLogWindowsEventsWithMissingEventIdsAndEventLevels.json @@ -0,0 +1,16 @@ +{ + "logs": { + "logs_collected": { + "windows_events": { + "collect_list": [ + { + "event_name": "System", + "log_group_name": "System", + "log_stream_name": "System" + } + ] + } + }, + "log_stream_name": "LOG_STREAM_NAME" + } +} \ No newline at end of file diff --git a/translator/config/schema.json b/translator/config/schema.json index 0279bf2c9d..e6eed15db0 100644 --- a/translator/config/schema.json +++ b/translator/config/schema.json @@ -1058,6 +1058,16 @@ "uniqueItems": true } }, + "event_ids":{ + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 65535 + }, + "minItems": 1, + "uniqueItems": true + }, "log_stream_name": { "$ref": "#/definitions/logsDefinition/definitions/logStreamNameDefinition" }, @@ -1079,8 +1089,15 @@ } }, "required": [ - "event_name", - "event_levels" + "event_name" + ], + "anyOf": [ + { + "required": ["event_levels"] + }, + { + "required": ["event_ids"] + } ], "additionalProperties": false }, diff --git a/translator/defaultKeyCase.go b/translator/defaultKeyCase.go index 87f358a816..de7e582aed 100644 --- a/translator/defaultKeyCase.go +++ b/translator/defaultKeyCase.go @@ -74,6 +74,25 @@ func DefaultStringArrayCase(key string, defaultVal, input interface{}) (returnKe return } +func DefaultIntegralArrayCase(key string, defaultVal, input interface{}) (string, interface{}) { + returnKey, returnVal := DefaultCase(key, defaultVal, input) + if arrayVal, ok := returnVal.([]interface{}); ok { + intArrayVal := []int{} + for _, v := range arrayVal { + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + intArrayVal = append(intArrayVal, intVal) + } + } + returnVal = intArrayVal + } else { + AddErrorMessages( + fmt.Sprintf("int array key: %s", key), + fmt.Sprintf("%s value (%v) in json is not valid as an array of integers.", key, returnVal)) + } + return returnKey, returnVal +} + func DefaultRetentionInDaysCase(key string, defaultVal, input interface{}) (returnKey string, returnVal interface{}) { returnKey, returnVal = DefaultIntegralCase(key, defaultVal, input) if intVal, ok := returnVal.(int); ok && IsValidRetentionDays(intVal) { diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.conf b/translator/tocwconfig/sampleConfig/windows_eventids.conf new file mode 100644 index 0000000000..5d0c21526d --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids.conf @@ -0,0 +1,48 @@ +[agent] + collection_jitter = "0s" + debug = false + flush_interval = "1s" + flush_jitter = "0s" + hostname = "" + interval = "60s" + logfile = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log" + logtarget = "lumberjack" + metric_batch_size = 1000 + metric_buffer_limit = 10000 + omit_hostname = false + precision = "" + quiet = false + round_interval = false + +[inputs] + + [[inputs.windows_event_log]] + destination = "cloudwatchlogs" + file_state_folder = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\state" + + [[inputs.windows_event_log.event_config]] + batch_read_size = 170 + event_ids = [4562, 4589] + event_name = "System" + log_group_class = "" + log_group_name = "System" + log_stream_name = "System" + retention_in_days = -1 + + [[inputs.windows_event_log.event_config]] + batch_read_size = 170 + event_ids = [1452, 9687] + event_name = "Application" + log_group_class = "" + log_group_name = "Application" + log_stream_name = "Application" + retention_in_days = -1 + +[outputs] + + [[outputs.cloudwatchlogs]] + force_flush_interval = "5s" + log_stream_name = "log_stream_name" + mode = "" + region = "us-west-2" + region_type = "ACJ" diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.json b/translator/tocwconfig/sampleConfig/windows_eventids.json new file mode 100644 index 0000000000..1f2b7c0037 --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids.json @@ -0,0 +1,29 @@ +{ + "logs": { + "logs_collected": { + "windows_events": { + "collect_list": [ + { + "event_name": "System", + "event_ids": [ + 4562, + 4589 + ], + "log_group_name": "System", + "log_stream_name": "System" + }, + { + "event_name": "Application", + "event_ids": [ + 1452, + 9687 + ], + "log_group_name": "Application", + "log_stream_name": "Application" + } + ] + } + }, + "log_stream_name": "log_stream_name" + } +} diff --git a/translator/tocwconfig/sampleConfig/windows_eventids.yaml b/translator/tocwconfig/sampleConfig/windows_eventids.yaml new file mode 100644 index 0000000000..5647ec5a92 --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids.yaml @@ -0,0 +1,33 @@ +exporters: + nop: {} +extensions: + entitystore: + mode: ec2 + region: us-west-2 +receivers: + nop: {} +service: + extensions: + - entitystore + pipelines: + metrics/nop: + exporters: + - nop + processors: [] + receivers: + - nop + telemetry: + logs: + encoding: console + level: info + output_paths: + - c:\ProgramData\Amazon\AmazonCloudWatchAgent\Logs\amazon-cloudwatch-agent.log + sampling: + enabled: true + initial: 2 + thereafter: 500 + tick: 10s + metrics: + level: None + traces: + level: None diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf new file mode 100644 index 0000000000..9da3a55bfc --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.conf @@ -0,0 +1,50 @@ +[agent] + collection_jitter = "0s" + debug = false + flush_interval = "1s" + flush_jitter = "0s" + hostname = "" + interval = "60s" + logfile = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\amazon-cloudwatch-agent.log" + logtarget = "lumberjack" + metric_batch_size = 1000 + metric_buffer_limit = 10000 + omit_hostname = false + precision = "" + quiet = false + round_interval = false + +[inputs] + + [[inputs.windows_event_log]] + destination = "cloudwatchlogs" + file_state_folder = "c:\\ProgramData\\Amazon\\AmazonCloudWatchAgent\\Logs\\state" + + [[inputs.windows_event_log.event_config]] + batch_read_size = 170 + event_ids = [4562, 4589] + event_levels = ["4", "0", "2"] + event_name = "System" + log_group_class = "" + log_group_name = "System" + log_stream_name = "System" + retention_in_days = -1 + + [[inputs.windows_event_log.event_config]] + batch_read_size = 170 + event_ids = [1104, 3215] + event_levels = ["4", "0", "2"] + event_name = "Application" + log_group_class = "" + log_group_name = "Application" + log_stream_name = "Application" + retention_in_days = -1 + +[outputs] + + [[outputs.cloudwatchlogs]] + force_flush_interval = "5s" + log_stream_name = "log_stream_name" + mode = "" + region = "us-west-2" + region_type = "ACJ" diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json new file mode 100644 index 0000000000..5a8d52b1d3 --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.json @@ -0,0 +1,37 @@ +{ + "logs": { + "logs_collected": { + "windows_events": { + "collect_list": [ + { + "event_name": "System", + "event_levels": [ + "INFORMATION", + "ERROR" + ], + "event_ids": [ + 4562, + 4589 + ], + "log_group_name": "System", + "log_stream_name": "System" + }, + { + "event_name": "Application", + "event_levels": [ + "INFORMATION", + "ERROR" + ], + "event_ids": [ + 1104, + 3215 + ], + "log_group_name": "Application", + "log_stream_name": "Application" + } + ] + } + }, + "log_stream_name": "log_stream_name" + } +} \ No newline at end of file diff --git a/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml new file mode 100644 index 0000000000..5647ec5a92 --- /dev/null +++ b/translator/tocwconfig/sampleConfig/windows_eventids_and_levels.yaml @@ -0,0 +1,33 @@ +exporters: + nop: {} +extensions: + entitystore: + mode: ec2 + region: us-west-2 +receivers: + nop: {} +service: + extensions: + - entitystore + pipelines: + metrics/nop: + exporters: + - nop + processors: [] + receivers: + - nop + telemetry: + logs: + encoding: console + level: info + output_paths: + - c:\ProgramData\Amazon\AmazonCloudWatchAgent\Logs\amazon-cloudwatch-agent.log + sampling: + enabled: true + initial: 2 + thereafter: 500 + tick: 10s + metrics: + level: None + traces: + level: None diff --git a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf index 662eb7f1d1..a91e4918b7 100755 --- a/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf +++ b/translator/tocwconfig/sampleConfig/windows_eventlog_only_config.conf @@ -24,6 +24,7 @@ batch_read_size = 170 event_levels = ["4", "0", "2"] event_name = "System" + log_group_class = "" log_group_name = "System" log_stream_name = "System" retention_in_days = -1 @@ -32,6 +33,7 @@ batch_read_size = 170 event_levels = ["4", "0", "2"] event_name = "Application" + log_group_class = "" log_group_name = "Application" log_stream_name = "Application" retention_in_days = -1 @@ -41,4 +43,6 @@ [[outputs.cloudwatchlogs]] force_flush_interval = "5s" log_stream_name = "log_stream_name" + mode = "" region = "us-west-2" + region_type = "ACJ" diff --git a/translator/tocwconfig/tocwconfig_test.go b/translator/tocwconfig/tocwconfig_test.go index 23923b4ae7..2992ed6358 100644 --- a/translator/tocwconfig/tocwconfig_test.go +++ b/translator/tocwconfig/tocwconfig_test.go @@ -340,6 +340,18 @@ func TestWindowsEventOnlyConfig(t *testing.T) { checkTranslation(t, "windows_eventlog_only_config", "windows", expectedEnvVars, "") } +func TestWindowsEventIDOnly(t *testing.T) { + resetContext(t) + expectedEnvVars := map[string]string{} + checkTranslation(t, "windows_eventids", "windows", expectedEnvVars, "") +} + +// test both event_ids and levels +func TestWindowsEventIdsAndLevels(t *testing.T) { + resetContext(t) + expectedEnvVars := map[string]string{} + checkTranslation(t, "windows_eventids_and_levels", "windows", expectedEnvVars, "") +} func TestStatsDConfig(t *testing.T) { testCases := map[string]testCase{ "linux": { @@ -923,11 +935,10 @@ func verifyToYamlTranslation(t *testing.T, input interface{}, expectedYamlFilePa require.NoError(t, yaml.Unmarshal([]byte(yamlStr), &actual)) //assert.NoError(t, os.WriteFile(expectedYamlFilePath, []byte(yamlStr), 0644)) // useful for regenerating YAML - opt := cmpopts.SortSlices(func(x, y interface{}) bool { return pretty.Sprint(x) < pretty.Sprint(y) }) - // assert.Equal(t, expected, actual) // this is useful for debugging differences between the YAML + //assert.Equal(t, expected, actual) // this is useful for debugging differences between the YAML require.True(t, cmp.Equal(expected, actual, opt), "D! YAML diff: %s", cmp.Diff(expected, actual)) } diff --git a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go index 49f071999b..eb4a511199 100644 --- a/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go +++ b/translator/tocwconfig/totomlconfig/tomlConfigTemplate/tomlConfig.go @@ -105,6 +105,7 @@ type ( eventConfig struct { BatchReadSize int `toml:"batch_read_size"` EventLevels []string `toml:"event_levels"` + EventIDs []int `toml:"event_ids"` EventName string `toml:"event_name"` LogGroupName string `toml:"log_group_name"` LogStreamName string `toml:"log_stream_name"` diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go index d795271be7..ef4a22dbfd 100644 --- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go +++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist.go @@ -34,7 +34,7 @@ func RegisterRule(fieldname string, r Rule) { type CollectList struct { } -var customizedJsonConfigKeys = []string{"event_name", EventLevelsKey} +var customizedJSONConfigKeys = []string{"event_name", EventLevelsKey} var eventLevelMapping = map[string]string{ "VERBOSE": "5", "INFORMATION": "4", @@ -77,7 +77,7 @@ func init() { func getTransformedConfig(input interface{}) interface{} { result := map[string]interface{}{} // Extract customer specified config - util.SetWithSameKeyIfFound(input, customizedJsonConfigKeys, result) + util.SetWithSameKeyIfFound(input, customizedJSONConfigKeys, result) // Set Fixed config addFixedJsonConfig(result) @@ -95,27 +95,25 @@ func addFixedJsonConfig(result map[string]interface{}) { result[BatchReadSizeKey] = BatchReadSizeValue var inputEventLevels []interface{} - if eventLevels, ok := result[EventLevelsKey]; !ok { - return - } else { + if eventLevels, ok := result[EventLevelsKey]; ok { inputEventLevels = eventLevels.([]interface{}) - } - resultEventLevels := []interface{}{} - for _, eventLevel := range inputEventLevels { - switch eventLevel.(string) { - case "CRITICAL": - resultEventLevels = append(resultEventLevels, "1") - case "ERROR": - resultEventLevels = append(resultEventLevels, "2") - case "WARNING": - resultEventLevels = append(resultEventLevels, "3") - case "INFORMATION": - resultEventLevels = append(resultEventLevels, "4", "0") - case "VERBOSE": - resultEventLevels = append(resultEventLevels, "5") - default: - translator.AddErrorMessages(GetCurPath(), fmt.Sprintf("Cannot find the mapping for Windows event level %v.", eventLevel)) + resultEventLevels := []interface{}{} + for _, eventLevel := range inputEventLevels { + switch eventLevel.(string) { + case "CRITICAL": + resultEventLevels = append(resultEventLevels, "1") + case "ERROR": + resultEventLevels = append(resultEventLevels, "2") + case "WARNING": + resultEventLevels = append(resultEventLevels, "3") + case "INFORMATION": + resultEventLevels = append(resultEventLevels, "4", "0") + case "VERBOSE": + resultEventLevels = append(resultEventLevels, "5") + default: + translator.AddErrorMessages(GetCurPath(), fmt.Sprintf("Cannot find the mapping for Windows event level %v.", eventLevel)) + } } + result[EventLevelsKey] = resultEventLevels } - result[EventLevelsKey] = resultEventLevels } diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go index 0c7409dfe3..5ed9006131 100644 --- a/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go +++ b/translator/translate/logs/logs_collected/windows_events/collect_list/collectlist_test.go @@ -15,7 +15,7 @@ import ( func TestApplyRule(t *testing.T) { c := new(CollectList) - var rawJsonString = ` + var rawJSONString = ` { "collect_list": [ { @@ -24,8 +24,13 @@ func TestApplyRule(t *testing.T) { "INFORMATION", "CRITICAL" ], + "event_ids": [ + 100, + 120, + 300 + ], "log_group_name": "System", - "log_group_class": "STANDARD" + "log_group_class": "STANDARD" }, { "event_name": "Application", @@ -34,6 +39,10 @@ func TestApplyRule(t *testing.T) { "VERBOSE", "ERROR" ], + "event_ids": [ + 4625, + 3568 + ], "event_format": "xml", "log_group_name": "Application", "retention_in_days": 1 @@ -47,6 +56,7 @@ func TestApplyRule(t *testing.T) { map[string]interface{}{ "event_name": "System", "event_levels": []interface{}{"4", "0", "1"}, + "event_ids": []int{100, 120, 300}, "log_group_name": "System", "batch_read_size": BatchReadSizeValue, "retention_in_days": -1, @@ -55,6 +65,7 @@ func TestApplyRule(t *testing.T) { map[string]interface{}{ "event_name": "Application", "event_levels": []interface{}{"4", "0", "5", "2"}, + "event_ids": []int{4625, 3568}, "event_format": "xml", "log_group_name": "Application", "batch_read_size": BatchReadSizeValue, @@ -65,7 +76,7 @@ func TestApplyRule(t *testing.T) { var actual interface{} - err := json.Unmarshal([]byte(rawJsonString), &input) + err := json.Unmarshal([]byte(rawJSONString), &input) if err == nil { _, actual = c.ApplyRule(input) assert.Equal(t, expected, actual) @@ -76,7 +87,7 @@ func TestApplyRule(t *testing.T) { func TestDuplicateRetention(t *testing.T) { c := new(CollectList) - var rawJsonString = ` + var rawJSONString = ` { "collect_list": [ { @@ -85,6 +96,10 @@ func TestDuplicateRetention(t *testing.T) { "INFORMATION", "CRITICAL" ], + "event_ids": [ + 100, + 120 + ], "log_group_name": "System", "retention_in_days": 3, "log_group_class": "INFREQUENT_ACCESS" @@ -96,6 +111,10 @@ func TestDuplicateRetention(t *testing.T) { "VERBOSE", "ERROR" ], + "event_ids": [ + 100, + 120 + ], "event_format": "xml", "log_group_name": "System", "retention_in_days": 3, @@ -108,6 +127,10 @@ func TestDuplicateRetention(t *testing.T) { "VERBOSE", "ERROR" ], + "event_ids": [ + 100, + 120 + ], "event_format": "xml", "log_group_name": "System", "retention_in_days": 3, @@ -122,6 +145,7 @@ func TestDuplicateRetention(t *testing.T) { map[string]interface{}{ "event_name": "System", "event_levels": []interface{}{"4", "0", "1"}, + "event_ids": []int{100, 120}, "log_group_name": "System", "batch_read_size": BatchReadSizeValue, "retention_in_days": 3, @@ -130,6 +154,7 @@ func TestDuplicateRetention(t *testing.T) { map[string]interface{}{ "event_name": "Application", "event_levels": []interface{}{"4", "0", "5", "2"}, + "event_ids": []int{100, 120}, "event_format": "xml", "log_group_name": "System", "batch_read_size": BatchReadSizeValue, @@ -139,6 +164,7 @@ func TestDuplicateRetention(t *testing.T) { map[string]interface{}{ "event_name": "Application", "event_levels": []interface{}{"4", "0", "5", "2"}, + "event_ids": []int{100, 120}, "event_format": "xml", "log_group_name": "System", "batch_read_size": BatchReadSizeValue, @@ -149,19 +175,19 @@ func TestDuplicateRetention(t *testing.T) { var actual interface{} - error := json.Unmarshal([]byte(rawJsonString), &input) - if error == nil { + err := json.Unmarshal([]byte(rawJSONString), &input) + if err == nil { _, actual = c.ApplyRule(input) assert.Equal(t, 0, len(translator.ErrorMessages)) assert.Equal(t, expected, actual) } else { - assert.Fail(t, error.Error()) + assert.Fail(t, err.Error()) } } func TestConflictingRetention(t *testing.T) { c := new(CollectList) - var rawJsonString = ` + var rawJSONString = ` { "collect_list": [ { @@ -170,8 +196,12 @@ func TestConflictingRetention(t *testing.T) { "INFORMATION", "CRITICAL" ], + "event_ids": [ + 100, + 120 + ], "log_group_name": "System", - "retention_in_days": 3 + "retention_in_days": 3 }, { "event_name": "Application", @@ -180,9 +210,13 @@ func TestConflictingRetention(t *testing.T) { "VERBOSE", "ERROR" ], + "event_ids": [ + 100, + 120 + ], "event_format": "xml", "log_group_name": "System", - "retention_in_days": 1 + "retention_in_days": 1 } ] } @@ -193,6 +227,7 @@ func TestConflictingRetention(t *testing.T) { map[string]interface{}{ "event_name": "System", "event_levels": []interface{}{"4", "0", "1"}, + "event_ids": []int{100, 120}, "log_group_name": "System", "batch_read_size": BatchReadSizeValue, "retention_in_days": 3, @@ -201,6 +236,7 @@ func TestConflictingRetention(t *testing.T) { map[string]interface{}{ "event_name": "Application", "event_levels": []interface{}{"4", "0", "5", "2"}, + "event_ids": []int{100, 120}, "event_format": "xml", "log_group_name": "System", "batch_read_size": BatchReadSizeValue, @@ -211,13 +247,40 @@ func TestConflictingRetention(t *testing.T) { var actual interface{} - error := json.Unmarshal([]byte(rawJsonString), &input) - if error == nil { + err := json.Unmarshal([]byte(rawJSONString), &input) + if err == nil { _, actual = c.ApplyRule(input) assert.GreaterOrEqual(t, 1, len(translator.ErrorMessages)) assert.Equal(t, "Under path : /logs/logs_collected/windows_events/collect_list/ | Error : Different retention_in_days values can't be set for the same log group: system", translator.ErrorMessages[len(translator.ErrorMessages)-1]) assert.Equal(t, expected, actual) } else { - assert.Fail(t, error.Error()) + assert.Fail(t, err.Error()) } } + +func TestEventID(t *testing.T) { + //Inputs + rawJSONString := `{ + "collect_list": [{ + "event_name": "System", + "event_ids": [100, 101, 102], + "event_levels": ["ERROR", "CRITICAL"] + }] + }` + + var config interface{} + err := json.Unmarshal([]byte(rawJSONString), &config) + assert.NoError(t, err) + + //process new configutation + c := new(CollectList) + _, val := c.ApplyRule(config) + + // Verify event_ids in final configuration + result := val.([]interface{})[0].(map[string]interface{}) + + eventIDs, exists := result["event_ids"] + assert.True(t, exists, "event_ids should exist in final configuration") + assert.Equal(t, []int{100, 101, 102}, eventIDs) + +} diff --git a/translator/translate/logs/logs_collected/windows_events/collect_list/ruleEventIDs.go b/translator/translate/logs/logs_collected/windows_events/collect_list/ruleEventIDs.go new file mode 100644 index 0000000000..b168640417 --- /dev/null +++ b/translator/translate/logs/logs_collected/windows_events/collect_list/ruleEventIDs.go @@ -0,0 +1,53 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT + +package collectlist + +import ( + "fmt" + + "github.com/aws/amazon-cloudwatch-agent/translator" +) + +const EventIDsSectionKey = "event_ids" + +type EventIDs struct { +} + +func isValidEventID(eventID int) bool { + + // Reference: https://learn.microsoft.com/en-us/windows/win32/winauto/allocation-of-winevent-ids + // Documentation for Windows Event Log identifiers and ranges + const ( + minEventID = 0 + maxEventID = 65535 + ) + return eventID >= minEventID && eventID <= maxEventID +} + +func (f *EventIDs) ApplyRule(input interface{}) (string, interface{}) { + m, ok := input.(map[string]interface{}) + if !ok { + return "", nil + } + + if _, exists := m[EventIDsSectionKey]; exists { + _, eventIDs := translator.DefaultIntegralArrayCase(EventIDsSectionKey, []interface{}{}, input) + + // Validate each event ID + if eventIDsArray, ok := eventIDs.([]int); ok { + for i, eventID := range eventIDsArray { + if !isValidEventID(eventID) { + translator.AddErrorMessages(GetCurPath(), fmt.Sprintf("Invalid event ID %d at index %d. Event IDs must be between 0 and 65535.", eventID, i)) + } + } + } + return EventIDsSectionKey, eventIDs + } + return EventIDsSectionKey, nil +} + +func init() { + e := new(EventIDs) + RegisterRule(EventIDsSectionKey, e) +} diff --git a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go index 9aa6944e69..d6ca4352d7 100644 --- a/translator/translate/logs/logs_collected/windows_events/windows_event_test.go +++ b/translator/translate/logs/logs_collected/windows_events/windows_event_test.go @@ -25,6 +25,10 @@ func TestApplyRule(t *testing.T) { "INFORMATION", "SUCCESS" ], + "event_ids": [ + 456, + 300 + ], "log_group_name": "System", "log_stream_name": "System" }