diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc
index 907f42d65b7..ad90dd4693a 100644
--- a/CHANGELOG.next.asciidoc
+++ b/CHANGELOG.next.asciidoc
@@ -399,6 +399,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff]
*Winlogbeat*
- Add handling for missing `EvtVarType`s in experimental api. {issue}19337[19337] {pull}41418[41418]
+- Implement exclusion range support for event_id. {issue}38623[38623] {pull}41639[41639]
*Functionbeat*
diff --git a/winlogbeat/docs/winlogbeat-options.asciidoc b/winlogbeat/docs/winlogbeat-options.asciidoc
index 2dd25ca409e..27a86bc04fb 100644
--- a/winlogbeat/docs/winlogbeat-options.asciidoc
+++ b/winlogbeat/docs/winlogbeat-options.asciidoc
@@ -230,14 +230,15 @@ and descriptions.
A whitelist and blacklist of event IDs. The value is a comma-separated list. The
accepted values are single event IDs to include (e.g. 4624), a range of event
-IDs to include (e.g. 4700-4800), and single event IDs to exclude (e.g. -4735).
+IDs to include (e.g. 4700-4800), single event IDs to exclude (e.g. -4735),
+and a range of event IDs to exclude (e.g. -4701-4710).
*{vista_and_newer}*
[source,yaml]
--------------------------------------------------------------------------------
winlogbeat.event_logs:
- name: Security
- event_id: 4624, 4625, 4700-4800, -4735
+ event_id: 4624, 4625, 4700-4800, -4735, -4701-4710
--------------------------------------------------------------------------------
[WARNING]
diff --git a/winlogbeat/sys/wineventlog/query.go b/winlogbeat/sys/wineventlog/query.go
index c48208f38fa..014e0d20a84 100644
--- a/winlogbeat/sys/wineventlog/query.go
+++ b/winlogbeat/sys/wineventlog/query.go
@@ -33,7 +33,7 @@ const (
query = `
{{if .Suppress}}
- *[System[({{join .Suppress " or "}})]]{{end}}
+ *[System[{{.Suppress}}]]{{end}}
`
)
@@ -44,6 +44,7 @@ var (
incEventIDRegex = regexp.MustCompile(`^\d+$`)
incEventIDRangeRegex = regexp.MustCompile(`^(\d+)\s*-\s*(\d+)$`)
excEventIDRegex = regexp.MustCompile(`^-(\d+)$`)
+ excEventIDRangeRegex = regexp.MustCompile(`^-(\d+)\s*-\s*(\d+)$`)
)
// Query that identifies the source of the events and one or more selectors or
@@ -101,7 +102,7 @@ func (q Query) Build() (string, error) {
type queryParams struct {
Path string
Select []string
- Suppress []string
+ Suppress string
}
func (qp *queryParams) ignoreOlderSelect(q Query) error {
@@ -140,6 +141,15 @@ func (qp *queryParams) eventIDSelect(q Query) error {
}
includes = append(includes,
fmt.Sprintf("(EventID >= %d and EventID <= %d)", r1, r2))
+ case excEventIDRangeRegex.MatchString(c):
+ m := excEventIDRangeRegex.FindStringSubmatch(c)
+ r1, _ := strconv.Atoi(m[1])
+ r2, _ := strconv.Atoi(m[2])
+ if r1 >= r2 {
+ return fmt.Errorf("event ID range '%s' is invalid", c)
+ }
+ excludes = append(excludes,
+ fmt.Sprintf("(EventID >= %d and EventID <= %d)", r1, r2))
default:
return fmt.Errorf("invalid event ID query component ('%s')", c)
}
@@ -150,10 +160,9 @@ func (qp *queryParams) eventIDSelect(q Query) error {
} else if len(includes) > 1 {
qp.Select = append(qp.Select, "("+strings.Join(includes, " or ")+")")
}
- if len(excludes) == 1 {
- qp.Suppress = append(qp.Suppress, excludes...)
- } else if len(excludes) > 1 {
- qp.Suppress = append(qp.Suppress, "("+strings.Join(excludes, " or ")+")")
+
+ if len(excludes) > 0 {
+ qp.Suppress = "(" + strings.Join(excludes, " or ") + ")"
}
return nil
diff --git a/winlogbeat/sys/wineventlog/query_test.go b/winlogbeat/sys/wineventlog/query_test.go
index 9c85b2bca4e..4405de5eda3 100644
--- a/winlogbeat/sys/wineventlog/query_test.go
+++ b/winlogbeat/sys/wineventlog/query_test.go
@@ -99,14 +99,14 @@ func TestCombinedQuery(t *testing.T) {
const expected = `
- *[System[(EventID=75)]]
+ *[System[(EventID=75 or (EventID >= 97 and EventID <= 99))]]
`
q, err := Query{
Log: "Application",
IgnoreOlder: time.Hour,
- EventID: "1, 1-100, -75",
+ EventID: "1, 1-100, -75, -97-99",
Level: "Warning",
}.Build()
if assert.NoError(t, err) {