Skip to content

Commit

Permalink
[Libbeat] Fix array matching in contains condition (#11691)
Browse files Browse the repository at this point in the history
Matching arrays of strings inside a contains condition doesn't work properly
with the output of JSON decoding as it is expecting fields of type []string
when they are in this case []interface{}.

Fixes: #3138
  • Loading branch information
adriansr committed Apr 10, 2019
1 parent 118ae55 commit 6a56dad
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Expand Up @@ -55,6 +55,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Fix a parsing error with the X-Pack license check on 32-bit system. {issue}11650[11650]
- Fix ILM policy always being overwritten. {pull}11671[11671]
- Fix template always being overwritten. {pull}11671[11671]
- Fix matching of string arrays in contains condition. {pull}11691[11691]

*Auditbeat*

Expand Down
46 changes: 34 additions & 12 deletions libbeat/common/match/matcher.go
Expand Up @@ -119,19 +119,23 @@ func (m *Matcher) Unpack(s string) error {
return nil
}

func (m *Matcher) MatchAnyString(strs []string) bool {
// MatchAnyString succeeds if any string in the given array contains a match.
func (m *Matcher) MatchAnyString(strs interface{}) bool {
return matchAnyStrings(m.stringMatcher, strs)
}

func (m *Matcher) MatchAllStrings(strs []string) bool {
// MatchAllStrings succeeds if all strings in the given array contain a match.
func (m *Matcher) MatchAllStrings(strs interface{}) bool {
return matchAllStrings(m.stringMatcher, strs)
}

func (m *ExactMatcher) MatchAnyString(strs []string) bool {
// MatchAnyString succeeds if any string in the given array is an exact match.
func (m *ExactMatcher) MatchAnyString(strs interface{}) bool {
return matchAnyStrings(m.stringMatcher, strs)
}

func (m *ExactMatcher) MatchAllStrings(strs []string) bool {
// MatchAllStrings succeeds if all strings in the given array are an exact match.
func (m *ExactMatcher) MatchAllStrings(strs interface{}) bool {
return matchAllStrings(m.stringMatcher, strs)
}

Expand All @@ -145,19 +149,37 @@ func (m *ExactMatcher) Unpack(s string) error {
return nil
}

func matchAnyStrings(m stringMatcher, strs []string) bool {
for _, s := range strs {
if m.MatchString(s) {
return true
func matchAnyStrings(m stringMatcher, strs interface{}) bool {
switch v := strs.(type) {
case []interface{}:
for _, s := range v {
if str, ok := s.(string); ok && m.MatchString(str) {
return true
}
}
case []string:
for _, s := range v {
if m.MatchString(s) {
return true
}
}
}
return false
}

func matchAllStrings(m stringMatcher, strs []string) bool {
for _, s := range strs {
if !m.MatchString(s) {
return false
func matchAllStrings(m stringMatcher, strs interface{}) bool {
switch v := strs.(type) {
case []interface{}:
for _, s := range v {
if str, ok := s.(string); ok && !m.MatchString(str) {
return false
}
}
case []string:
for _, s := range v {
if !m.MatchString(s) {
return false
}
}
}
return true
Expand Down
3 changes: 2 additions & 1 deletion libbeat/conditions/conditions_test.go
Expand Up @@ -68,8 +68,9 @@ var secdTestEvent = &beat.Event{
"ppid": 1,
"state": "running",
"username": "monica",
"keywords": []string{"foo", "bar"},
"keywords": []interface{}{"foo", "bar"},
},
"tags": []string{"auditbeat", "prod", "security"},
"type": "process",
"final": false,
},
Expand Down
3 changes: 1 addition & 2 deletions libbeat/conditions/matcher.go
Expand Up @@ -86,11 +86,10 @@ func (c Matcher) Check(event ValuesMap) bool {
return false
}

case []string:
case []interface{}, []string:
if !matcher.MatchAnyString(v) {
return false
}

default:
str, err := ExtractString(value)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions libbeat/conditions/matcher_test.go
Expand Up @@ -64,6 +64,14 @@ func TestContainsSingleFieldPositiveMatch(t *testing.T) {
})
}

func TestContainsArrayOfStringPositiveMatch(t *testing.T) {
testConfig(t, true, secdTestEvent, &Config{
Contains: &Fields{fields: map[string]interface{}{
"tags": "prod",
}},
})
}

func TestRegexpCondition(t *testing.T) {
logp.TestingSetup()

Expand Down

0 comments on commit 6a56dad

Please sign in to comment.