Skip to content

Commit 18c7d00

Browse files
committed
feat(rule_engine): Validate event/category names
The rule engine compiler ensures that the provided event or category names are match the internal catalog nomenclature.
1 parent 1dd69e3 commit 18c7d00

File tree

9 files changed

+95
-1
lines changed

9 files changed

+95
-1
lines changed

pkg/event/category.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,13 @@ func Categories() []string {
122122
string(Threadpool),
123123
}
124124
}
125+
126+
// IsCategoryKnown indicates if the category is known given its name.
127+
func IsCategoryKnown(name string) bool {
128+
for _, category := range Categories() {
129+
if category == name {
130+
return true
131+
}
132+
}
133+
return false
134+
}

pkg/event/metainfo_windows.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,16 @@ outer:
314314
return typs
315315
}
316316

317+
// IsKnown indicates if the event type is known given the event name.
318+
func IsKnown(name string) bool {
319+
for _, evt := range GetTypesMeta() {
320+
if evt.Name == name {
321+
return true
322+
}
323+
}
324+
return false
325+
}
326+
317327
// GetTypesMetaIndexed returns indexed event types metadata
318328
// that is guaranteed to always return the same event indices.
319329
func GetTypesMetaIndexed() []Info { return indexedEvents }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: match https connections
2+
id: 8f36f8e0-a5c2-498f-9563-eea306daa586
3+
version: 1.0.0
4+
condition: evt.category = 'net' and net.dport = 443
5+
min-engine-version: 2.0.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: match https connections
2+
id: 8f36f8e0-a5c2-498f-9563-eea306daa586
3+
version: 1.0.0
4+
condition: evt.name = 'Recv' and net.dport = 443
5+
min-engine-version: 2.0.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: match https connections
2+
id: 8f36f8e0-a5c2-498f-9563-eea306daa586
3+
version: 1.0.0
4+
condition: evt.category = 'network' and net.dport = 443
5+
min-engine-version: 2.0.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: match https connections
2+
id: 8f36f8e0-a5c2-498f-9563-eea306daa586
3+
version: 1.0.0
4+
condition: evt.name = 'RecvTcp4' and net.dport = 443
5+
min-engine-version: 2.0.0
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
name: match https connections
2+
id: 8f36f8e0-a5c2-498f-9563-eea306daa586
3+
version: 1.0.0
4+
condition: evt.name in ('Recv', 'Accept', 'CreateProc') and net.dport = 443
5+
min-engine-version: 2.0.0

pkg/rules/compiler.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ var (
4444
ErrMalformedMinEngineVer = func(rule, v string, err error) error {
4545
return fmt.Errorf("rule %q has a malformed minimum engine version: %s: %v", rule, v, err)
4646
}
47+
ErrUnknownEventName = func(rule, name string) error {
48+
return fmt.Errorf("rule %s references an invalid event name %q in the evt.name field", rule, name)
49+
}
50+
ErrUnknownCategoryName = func(rule, name string) error {
51+
return fmt.Errorf("rule %s references an invalid event category %q in the evt.category field", rule, name)
52+
}
4753
)
4854

4955
type compiler struct {
@@ -89,6 +95,7 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru
8995
return nil, nil, ErrIncompatibleFilter(f.Name, f.MinEngineVersion)
9096
}
9197
}
98+
9299
// output warning for deprecated fields
93100
for _, field := range fltr.GetFields() {
94101
deprecated, d := fields.IsDeprecated(field.Name)
@@ -97,7 +104,23 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru
97104
"was deprecated starting from version %s. "+
98105
"Please consider migrating to %s field(s) "+
99106
"because [%s] will be removed in future versions.",
100-
f.Name, field, d.Since, d.Fields, field)
107+
f.Name, field.Name, d.Since, d.Fields, field.Name)
108+
}
109+
}
110+
111+
// validate the value of the event/category fields
112+
for field, values := range fltr.GetStringFields() {
113+
for _, v := range values {
114+
switch field {
115+
case fields.EvtName, fields.KevtName:
116+
if !event.IsKnown(v) {
117+
return nil, nil, ErrUnknownEventName(f.Name, v)
118+
}
119+
case fields.EvtCategory, fields.KevtCategory:
120+
if !event.IsCategoryKnown(v) {
121+
return nil, nil, ErrUnknownCategoryName(f.Name, v)
122+
}
123+
}
101124
}
102125
}
103126

pkg/rules/compiler_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,29 @@ func TestCompileMinEngineVersion(t *testing.T) {
7070
})
7171
}
7272
}
73+
74+
func TestCompileEventCategoryFieldNames(t *testing.T) {
75+
var tests = []struct {
76+
rules string
77+
err error
78+
}{
79+
{"_fixtures/field_values/correct_event_name_field.yml", nil},
80+
{"_fixtures/field_values/incorrect_event_name_field.yml", ErrUnknownEventName("match https connections", "RecvTcp4")},
81+
{"_fixtures/field_values/incorrect_event_name_in_operator.yml", ErrUnknownEventName("match https connections", "CreateProc")},
82+
{"_fixtures/field_values/correct_category_name_field.yml", nil},
83+
{"_fixtures/field_values/incorrect_category_name_field.yml", ErrUnknownCategoryName("match https connections", "network")},
84+
}
85+
86+
for _, tt := range tests {
87+
t.Run(tt.rules, func(t *testing.T) {
88+
c := newCompiler(new(ps.SnapshotterMock), newConfig(tt.rules))
89+
_, _, err := c.compile()
90+
if err != nil && tt.err != nil {
91+
require.Error(t, err)
92+
}
93+
if err != nil {
94+
require.EqualError(t, err, tt.err.Error())
95+
}
96+
})
97+
}
98+
}

0 commit comments

Comments
 (0)