github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/rules/evaluation_set.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package rules holds rules related files 7 package rules 8 9 import ( 10 "fmt" 11 12 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/ast" 13 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" 14 "github.com/hashicorp/go-multierror" 15 ) 16 17 // EvaluationSet defines an evalation set 18 type EvaluationSet struct { 19 RuleSets map[eval.RuleSetTagValue]*RuleSet 20 } 21 22 // NewEvaluationSet returns a new policy set for the specified data model 23 func NewEvaluationSet(ruleSetsToInclude []*RuleSet) (*EvaluationSet, error) { 24 ruleSets := make(map[string]*RuleSet) 25 26 if len(ruleSetsToInclude) == 0 { 27 return nil, ErrNoRuleSetsInEvaluationSet 28 } 29 30 for _, ruleSet := range ruleSetsToInclude { 31 if ruleSet != nil { 32 ruleSets[ruleSet.GetRuleSetTag()] = ruleSet 33 } else { 34 return nil, fmt.Errorf("nil rule set with tag value %s provided include in an evaluation set", ruleSet.GetRuleSetTag()) 35 } 36 } 37 38 return &EvaluationSet{RuleSets: ruleSets}, nil 39 } 40 41 // GetPolicies returns the policies 42 func (es *EvaluationSet) GetPolicies() []*Policy { 43 var policies []*Policy 44 45 seen := make(map[string]bool) 46 47 for _, rs := range es.RuleSets { 48 for _, policy := range rs.policies { 49 if _, ok := seen[policy.Name]; !ok { 50 seen[policy.Name] = true 51 policies = append(policies, policy) 52 } 53 } 54 } 55 56 return policies 57 } 58 59 type ruleIndexEntry struct { 60 value eval.RuleSetTagValue 61 ruleID eval.RuleID 62 } 63 64 // LoadPolicies load policies 65 func (es *EvaluationSet) LoadPolicies(loader *PolicyLoader, opts PolicyLoaderOpts) *multierror.Error { 66 var ( 67 errs *multierror.Error 68 rules = make(map[eval.RuleSetTagValue][]*RuleDefinition) 69 allMacros []*MacroDefinition 70 macroIndex = make(map[string]*MacroDefinition) 71 rulesIndex = make(map[ruleIndexEntry]*RuleDefinition) 72 ) 73 74 parsingContext := ast.NewParsingContext() 75 76 policies, err := loader.LoadPolicies(opts) 77 if err != nil { 78 errs = multierror.Append(errs, err) 79 } 80 for _, rs := range es.RuleSets { 81 rs.policies = policies 82 } 83 84 for _, policy := range policies { 85 for _, macro := range policy.Macros { 86 if existingMacro := macroIndex[macro.ID]; existingMacro != nil { 87 if err := existingMacro.MergeWith(macro); err != nil { 88 errs = multierror.Append(errs, err) 89 } 90 } else { 91 macroIndex[macro.ID] = macro 92 allMacros = append(allMacros, macro) 93 } 94 } 95 96 for _, rule := range policy.Rules { 97 tagValue, _ := rule.GetTag("ruleset") 98 if tagValue == "" { 99 tagValue = DefaultRuleSetTagValue 100 } 101 102 if existingRule := rulesIndex[ruleIndexEntry{tagValue, rule.ID}]; existingRule != nil { 103 if err := existingRule.MergeWith(rule); err != nil { 104 errs = multierror.Append(errs, err) 105 } 106 } else { 107 rulesIndex[ruleIndexEntry{tagValue, rule.ID}] = rule 108 rules[tagValue] = append(rules[tagValue], rule) 109 } 110 } 111 } 112 113 for ruleSetTagValue, rs := range es.RuleSets { 114 for rulesIndexTagValue, ruleList := range rules { 115 if rulesIndexTagValue == ruleSetTagValue { 116 // Add the macros to the ruleset and generate macros evaluators 117 if err := rs.AddMacros(parsingContext, allMacros); err.ErrorOrNil() != nil { 118 errs = multierror.Append(errs, err) 119 } 120 121 if err := rs.populateFieldsWithRuleActionsData(ruleList, opts); err.ErrorOrNil() != nil { 122 errs = multierror.Append(errs, err) 123 } 124 125 // Add rules to the ruleset and generate rules evaluators 126 if err := rs.AddRules(parsingContext, ruleList); err.ErrorOrNil() != nil { 127 errs = multierror.Append(errs, err) 128 } 129 } 130 } 131 } 132 133 for ruleSetTag, ruleSet := range es.RuleSets { 134 if ruleSet == nil { 135 delete(es.RuleSets, ruleSetTag) 136 } 137 } 138 139 return errs 140 }