diff --git a/pkg/event/category.go b/pkg/event/category.go index 0f86043c7..f136415c9 100644 --- a/pkg/event/category.go +++ b/pkg/event/category.go @@ -122,3 +122,13 @@ func Categories() []string { string(Threadpool), } } + +// IsCategoryKnown indicates if the category is known given its name. +func IsCategoryKnown(name string) bool { + for _, category := range Categories() { + if category == name { + return true + } + } + return false +} diff --git a/pkg/event/metainfo_windows.go b/pkg/event/metainfo_windows.go index d7913cf22..6f8df0e9d 100644 --- a/pkg/event/metainfo_windows.go +++ b/pkg/event/metainfo_windows.go @@ -314,6 +314,16 @@ outer: return typs } +// IsKnown indicates if the event type is known given the event name. +func IsKnown(name string) bool { + for _, evt := range GetTypesMeta() { + if evt.Name == name { + return true + } + } + return false +} + // GetTypesMetaIndexed returns indexed event types metadata // that is guaranteed to always return the same event indices. func GetTypesMetaIndexed() []Info { return indexedEvents } diff --git a/pkg/rules/_fixtures/field_values/correct_category_name_field.yml b/pkg/rules/_fixtures/field_values/correct_category_name_field.yml new file mode 100644 index 000000000..377b123cb --- /dev/null +++ b/pkg/rules/_fixtures/field_values/correct_category_name_field.yml @@ -0,0 +1,5 @@ +name: match https connections +id: 8f36f8e0-a5c2-498f-9563-eea306daa586 +version: 1.0.0 +condition: evt.category = 'net' and net.dport = 443 +min-engine-version: 2.0.0 diff --git a/pkg/rules/_fixtures/field_values/correct_event_name_field.yml b/pkg/rules/_fixtures/field_values/correct_event_name_field.yml new file mode 100644 index 000000000..55e643f66 --- /dev/null +++ b/pkg/rules/_fixtures/field_values/correct_event_name_field.yml @@ -0,0 +1,5 @@ +name: match https connections +id: 8f36f8e0-a5c2-498f-9563-eea306daa586 +version: 1.0.0 +condition: evt.name = 'Recv' and net.dport = 443 +min-engine-version: 2.0.0 diff --git a/pkg/rules/_fixtures/field_values/incorrect_category_name_field.yml b/pkg/rules/_fixtures/field_values/incorrect_category_name_field.yml new file mode 100644 index 000000000..0970eb35a --- /dev/null +++ b/pkg/rules/_fixtures/field_values/incorrect_category_name_field.yml @@ -0,0 +1,5 @@ +name: match https connections +id: 8f36f8e0-a5c2-498f-9563-eea306daa586 +version: 1.0.0 +condition: evt.category = 'network' and net.dport = 443 +min-engine-version: 2.0.0 diff --git a/pkg/rules/_fixtures/field_values/incorrect_event_name_field.yml b/pkg/rules/_fixtures/field_values/incorrect_event_name_field.yml new file mode 100644 index 000000000..132c12621 --- /dev/null +++ b/pkg/rules/_fixtures/field_values/incorrect_event_name_field.yml @@ -0,0 +1,5 @@ +name: match https connections +id: 8f36f8e0-a5c2-498f-9563-eea306daa586 +version: 1.0.0 +condition: evt.name = 'RecvTcp4' and net.dport = 443 +min-engine-version: 2.0.0 diff --git a/pkg/rules/_fixtures/field_values/incorrect_event_name_in_operator.yml b/pkg/rules/_fixtures/field_values/incorrect_event_name_in_operator.yml new file mode 100644 index 000000000..67870eea6 --- /dev/null +++ b/pkg/rules/_fixtures/field_values/incorrect_event_name_in_operator.yml @@ -0,0 +1,5 @@ +name: match https connections +id: 8f36f8e0-a5c2-498f-9563-eea306daa586 +version: 1.0.0 +condition: evt.name in ('Recv', 'Accept', 'CreateProc') and net.dport = 443 +min-engine-version: 2.0.0 diff --git a/pkg/rules/compiler.go b/pkg/rules/compiler.go index 7d964f3c2..8b038a810 100644 --- a/pkg/rules/compiler.go +++ b/pkg/rules/compiler.go @@ -44,6 +44,12 @@ var ( ErrMalformedMinEngineVer = func(rule, v string, err error) error { return fmt.Errorf("rule %q has a malformed minimum engine version: %s: %v", rule, v, err) } + ErrUnknownEventName = func(rule, name string) error { + return fmt.Errorf("rule %s references an invalid event name %q in the evt.name field", rule, name) + } + ErrUnknownCategoryName = func(rule, name string) error { + return fmt.Errorf("rule %s references an invalid event category %q in the evt.category field", rule, name) + } ) type compiler struct { @@ -89,6 +95,7 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru return nil, nil, ErrIncompatibleFilter(f.Name, f.MinEngineVersion) } } + // output warning for deprecated fields for _, field := range fltr.GetFields() { deprecated, d := fields.IsDeprecated(field.Name) @@ -97,7 +104,23 @@ func (c *compiler) compile() (map[*config.FilterConfig]filter.Filter, *config.Ru "was deprecated starting from version %s. "+ "Please consider migrating to %s field(s) "+ "because [%s] will be removed in future versions.", - f.Name, field, d.Since, d.Fields, field) + f.Name, field.Name, d.Since, d.Fields, field.Name) + } + } + + // validate the value of the event/category fields + for field, values := range fltr.GetStringFields() { + for _, v := range values { + switch field { + case fields.EvtName, fields.KevtName: + if !event.IsKnown(v) { + return nil, nil, ErrUnknownEventName(f.Name, v) + } + case fields.EvtCategory, fields.KevtCategory: + if !event.IsCategoryKnown(v) { + return nil, nil, ErrUnknownCategoryName(f.Name, v) + } + } } } diff --git a/pkg/rules/compiler_test.go b/pkg/rules/compiler_test.go index 2bc6ac531..fff233bf5 100644 --- a/pkg/rules/compiler_test.go +++ b/pkg/rules/compiler_test.go @@ -70,3 +70,29 @@ func TestCompileMinEngineVersion(t *testing.T) { }) } } + +func TestCompileEventCategoryFieldNames(t *testing.T) { + var tests = []struct { + rules string + err error + }{ + {"_fixtures/field_values/correct_event_name_field.yml", nil}, + {"_fixtures/field_values/incorrect_event_name_field.yml", ErrUnknownEventName("match https connections", "RecvTcp4")}, + {"_fixtures/field_values/incorrect_event_name_in_operator.yml", ErrUnknownEventName("match https connections", "CreateProc")}, + {"_fixtures/field_values/correct_category_name_field.yml", nil}, + {"_fixtures/field_values/incorrect_category_name_field.yml", ErrUnknownCategoryName("match https connections", "network")}, + } + + for _, tt := range tests { + t.Run(tt.rules, func(t *testing.T) { + c := newCompiler(new(ps.SnapshotterMock), newConfig(tt.rules)) + _, _, err := c.compile() + if err != nil && tt.err != nil { + require.Error(t, err) + } + if err != nil { + require.EqualError(t, err, tt.err.Error()) + } + }) + } +}