Skip to content

Commit ab79382

Browse files
fix[backend](rules): changed after events by correlation (keeping retro compatibility
1 parent 308623a commit ab79382

7 files changed

Lines changed: 84 additions & 17 deletions

File tree

backend/modules/eventprocessing/domain/correlation_rule.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package domain
22

3-
import "time"
3+
import (
4+
"fmt"
5+
"time"
6+
)
47

58
type UtmCorrelationRules struct {
69
ID int64 `gorm:"column:id;primaryKey"`
@@ -28,7 +31,10 @@ type UtmCorrelationRules struct {
2831
SystemOwner bool `gorm:"column:system_owner;not null"`
2932

3033
// Nullable JSON TEXT columns for advanced rule configuration.
34+
//[deprecated] only keeped for compatibility
3135
AfterEventsDef string `gorm:"column:rule_after_events_def"`
36+
//
37+
CorrelationDef string `gorm:"column:rule_correlation_def"`
3238
RuleGroupByDef string `gorm:"column:rule_group_by_def"`
3339
DeduplicateByDef string `gorm:"column:rule_deduplicate_by_def"`
3440

@@ -38,4 +44,16 @@ type UtmCorrelationRules struct {
3844
DataTypes []UtmDataTypes `gorm:"many2many:utm_group_rules_data_type;joinForeignKey:rule_id;joinReferences:data_type_id"`
3945
}
4046

47+
func (self *UtmCorrelationRules) GetCorrelationDef() (string,error){
48+
var correlate string
49+
if self.AfterEventsDef!="" && self.CorrelationDef !=""{
50+
return "",fmt.Errorf("only one afterEvents or correlation allowed")
51+
}else if self.AfterEventsDef!="" {
52+
correlate = self.AfterEventsDef
53+
}else{
54+
correlate= self.CorrelationDef
55+
}
56+
return correlate,nil
57+
}
58+
4159
func (UtmCorrelationRules) TableName() string { return "utm_correlation_rules" }

backend/modules/eventprocessing/dto/correlation_rule.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dto
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"time"
67
)
78

@@ -23,7 +24,29 @@ type RuleDataTypeResponse struct {
2324
SystemOwner bool `json:"systemOwner"`
2425
}
2526

27+
28+
type CorrelationOwner struct{
29+
//[deprecated] only keeped for compatibility
30+
AfterEventsDef json.RawMessage `json:"afterEvents"`
31+
//
32+
CorrelationDef json.RawMessage `json:"correlation"`
33+
}
34+
35+
func (self *CorrelationOwner) GetCorrelationDef() (json.RawMessage,error){
36+
var correlate json.RawMessage
37+
if self.AfterEventsDef!=nil && self.CorrelationDef !=nil{
38+
return nil,fmt.Errorf("only one afterEvents or correlation allowed")
39+
}else if self.AfterEventsDef!=nil {
40+
correlate = self.AfterEventsDef
41+
}else{
42+
correlate= self.CorrelationDef
43+
}
44+
return correlate,nil
45+
}
46+
47+
2648
type CreateCorrelationRuleRequest struct {
49+
CorrelationOwner
2750
// JSON tags match Java UtmCorrelationRulesDTO field names for wire compatibility.
2851
RuleName string `json:"name"`
2952
RuleAdversary string `json:"adversary"`
@@ -38,7 +61,6 @@ type CreateCorrelationRuleRequest struct {
3861

3962
RuleReferencesDef json.RawMessage `json:"references"`
4063
RuleDefinitionDef json.RawMessage `json:"definition"`
41-
AfterEventsDef json.RawMessage `json:"afterEvents"`
4264
RuleGroupByDef json.RawMessage `json:"groupBy"`
4365
DeduplicateByDef json.RawMessage `json:"deduplicateBy"`
4466

@@ -47,7 +69,10 @@ type CreateCorrelationRuleRequest struct {
4769
DataTypes []DataTypeRef `json:"dataTypes"`
4870
}
4971

72+
73+
5074
type UpdateCorrelationRuleRequest struct {
75+
CorrelationOwner
5176
// RelPath identifies the rule to update (the YAML-direct identity).
5277
RelPath string `json:"relPath"`
5378

@@ -64,7 +89,6 @@ type UpdateCorrelationRuleRequest struct {
6489

6590
RuleReferencesDef json.RawMessage `json:"references"`
6691
RuleDefinitionDef json.RawMessage `json:"definition"`
67-
AfterEventsDef json.RawMessage `json:"afterEvents"`
6892
RuleGroupByDef json.RawMessage `json:"groupBy"`
6993
DeduplicateByDef json.RawMessage `json:"deduplicateBy"`
7094

@@ -73,6 +97,7 @@ type UpdateCorrelationRuleRequest struct {
7397
DataTypes []DataTypeRef `json:"dataTypes"`
7498
}
7599

100+
76101
type CorrelationRuleResponse struct {
77102
// RelPath is the rule identity (replaces the legacy numeric id).
78103
RelPath string `json:"relPath"`
@@ -90,7 +115,7 @@ type CorrelationRuleResponse struct {
90115

91116
RuleReferencesDef json.RawMessage `json:"references"`
92117
RuleDefinitionDef json.RawMessage `json:"definition"`
93-
AfterEventsDef json.RawMessage `json:"afterEvents"`
118+
CorrelationDef json.RawMessage `json:"correlation"`
94119
RuleGroupByDef json.RawMessage `json:"groupBy"`
95120
DeduplicateByDef json.RawMessage `json:"deduplicateBy"`
96121

backend/modules/eventprocessing/module.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,5 +126,5 @@ func (m *Module) GetIngestionStatsUsecase() connectors.IngestionStatsUsecase {
126126
}
127127

128128
func (m *Module) AfterEventsByRuleName(name string) (json.RawMessage, bool) {
129-
return m.ruleStore.AfterEventsByName(name)
129+
return m.ruleStore.CorrelationsByName(name)
130130
}

backend/modules/eventprocessing/usecase/correlation_rule.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,24 @@ func NewCorrelationRuleUsecase(store *RuleStore) connectors.CorrelationRuleUseca
2424
return &correlationRuleUsecase{store: store}
2525
}
2626

27+
28+
2729
func (u *correlationRuleUsecase) Create(_ context.Context, req dto.CreateCorrelationRuleRequest) error {
2830
if len(req.DataTypes) == 0 {
2931
return domain.ErrDataTypesRequired
3032
}
31-
if err := validateRuleContent(req.RuleDefinitionDef, req.AfterEventsDef); err != nil {
33+
34+
correlate,err:= req.GetCorrelationDef()
35+
if err!=nil{
36+
return err
37+
}
38+
39+
if err := validateRuleContent(req.RuleDefinitionDef,correlate ); err != nil {
3240
return err
3341
}
3442
rule := buildRule(req.RuleName, req.RuleAdversary, req.RuleConfidentiality, req.RuleIntegrity,
3543
req.RuleAvailability, req.RuleCategory, req.RuleTechnique, req.RuleDescription,
36-
req.RuleReferencesDef, req.RuleDefinitionDef, req.AfterEventsDef, req.RuleGroupByDef,
44+
req.RuleReferencesDef, req.RuleDefinitionDef, correlate, req.RuleGroupByDef,
3745
req.DeduplicateByDef, req.DataTypes)
3846

3947
created, err := u.store.Create(rule)
@@ -105,10 +113,10 @@ func validateImportedRule(r Rule) error {
105113
if strings.TrimSpace(r.Where) == "" {
106114
return domain.ErrCorrelationRuleNullDefinition
107115
}
108-
if r.AfterEvents == nil {
116+
if r.Correlation == nil {
109117
return nil
110118
}
111-
raw, err := json.Marshal(r.AfterEvents)
119+
raw, err := json.Marshal(r.Correlation)
112120
if err != nil {
113121
return fmt.Errorf("%w: afterEvents is not serializable", domain.ErrCorrelationRuleInvalidContent)
114122
}
@@ -131,12 +139,18 @@ func (u *correlationRuleUsecase) Update(_ context.Context, req dto.UpdateCorrela
131139
if len(req.DataTypes) == 0 {
132140
return domain.ErrDataTypesRequired
133141
}
134-
if err := validateRuleContent(req.RuleDefinitionDef, req.AfterEventsDef); err != nil {
142+
143+
correlate,err:= req.GetCorrelationDef()
144+
if err!=nil{
145+
return err
146+
}
147+
148+
if err := validateRuleContent(req.RuleDefinitionDef, correlate); err != nil {
135149
return err
136150
}
137151
rule := buildRule(req.RuleName, req.RuleAdversary, req.RuleConfidentiality, req.RuleIntegrity,
138152
req.RuleAvailability, req.RuleCategory, req.RuleTechnique, req.RuleDescription,
139-
req.RuleReferencesDef, req.RuleDefinitionDef, req.AfterEventsDef, req.RuleGroupByDef,
153+
req.RuleReferencesDef, req.RuleDefinitionDef, correlate, req.RuleGroupByDef,
140154
req.DeduplicateByDef, req.DataTypes)
141155

142156
if _, err := u.store.Update(req.RelPath, rule); err != nil {
@@ -210,7 +224,7 @@ func buildRule(name, adversary string, conf, integ, avail int, category, techniq
210224
Impact: Impact{Confidentiality: conf, Integrity: integ, Availability: avail},
211225
Where: rawToWhere(def),
212226
References: rawToAnySlice(refs),
213-
AfterEvents: rawToAny(after),
227+
Correlation: rawToAny(after),
214228
GroupBy: rawToStrSlice(groupBy),
215229
DeduplicateBy: rawToStrSlice(dedup),
216230
}
@@ -237,7 +251,7 @@ func storedToResponse(sr *StoredRule) *dto.CorrelationRuleResponse {
237251
RuleDescription: sr.Description,
238252
RuleReferencesDef: anyToRaw(sr.References),
239253
RuleDefinitionDef: anyToRaw(sr.Where),
240-
AfterEventsDef: anyToRaw(sr.AfterEvents),
254+
CorrelationDef: anyToRaw(sr.Correlation),
241255
RuleGroupByDef: anyToRaw(sr.GroupBy),
242256
DeduplicateByDef: anyToRaw(sr.DeduplicateBy),
243257
RuleLastUpdate: &mod,

backend/modules/eventprocessing/usecase/rule_bootstrap.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,16 @@ func legacyToRule(row *domain.UtmCorrelationRules) Rule {
264264
for _, dt := range row.DataTypes {
265265
names = append(names, dt.DataType)
266266
}
267+
268+
correlation,err:=row.GetCorrelationDef()
269+
if err!=nil{
270+
catcher.Error("skipping invalid after events of rule, %s",err,map[string]any{
271+
"rule":row.RuleName,
272+
"afterEvents":row.AfterEventsDef,
273+
"correlation":row.CorrelationDef,
274+
})
275+
}
276+
267277
return Rule{
268278
Name: row.RuleName,
269279
Adversary: row.RuleAdversary,
@@ -274,7 +284,7 @@ func legacyToRule(row *domain.UtmCorrelationRules) Rule {
274284
Impact: Impact{Confidentiality: row.RuleConfidentiality, Integrity: row.RuleIntegrity, Availability: row.RuleAvailability},
275285
Where: rawToWhere(toRaw(row.RuleDefinitionDef)),
276286
References: rawToAnySlice(toRaw(row.RuleReferencesDef)),
277-
AfterEvents: rawToAny(toRaw(row.AfterEventsDef)),
287+
Correlation: rawToAny(toRaw(correlation)),
278288
GroupBy: rawToStrSlice(toRaw(row.RuleGroupByDef)),
279289
DeduplicateBy: rawToStrSlice(toRaw(row.DeduplicateByDef)),
280290
}

backend/modules/eventprocessing/usecase/rule_model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type Rule struct {
3838
References []any `yaml:"references,omitempty"`
3939
Description string `yaml:"description,omitempty"`
4040
Where string `yaml:"where"`
41-
AfterEvents any `yaml:"afterEvents,omitempty"`
41+
Correlation any `yaml:"correlation,omitempty"`
4242
GroupBy []string `yaml:"groupBy,omitempty"`
4343
DeduplicateBy []string `yaml:"deduplicateBy,omitempty"`
4444
}

backend/modules/eventprocessing/usecase/rule_store.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,12 @@ func (s *RuleStore) FindByName(name string) *StoredRule {
162162
return nil
163163
}
164164

165-
func (s *RuleStore) AfterEventsByName(name string) (json.RawMessage, bool) {
165+
func (s *RuleStore) CorrelationsByName(name string) (json.RawMessage, bool) {
166166
sr := s.FindByName(name)
167167
if sr == nil {
168168
return nil, false
169169
}
170-
return anyToRaw(sr.AfterEvents), true
170+
return anyToRaw(sr.Correlation), true
171171
}
172172

173173
// List applies the filter, sorts by name and paginates. It returns the page

0 commit comments

Comments
 (0)