github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/macro.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 eval holds eval related files 7 package eval 8 9 import ( 10 "fmt" 11 12 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/ast" 13 ) 14 15 // MacroID - ID of a Macro 16 type MacroID = string 17 18 // Macro - Macro object identified by an `ID` containing a SECL `Expression` 19 type Macro struct { 20 ID MacroID 21 Opts *Opts 22 23 evaluator *MacroEvaluator 24 ast *ast.Macro 25 } 26 27 // MacroEvaluator - Evaluation part of a Macro 28 type MacroEvaluator struct { 29 Value interface{} 30 EventTypes []EventType 31 32 fieldValues map[Field][]FieldValue 33 fields []Field 34 } 35 36 // NewMacro parses an expression and returns a new macro 37 func NewMacro(id, expression string, model Model, parsingContext *ast.ParsingContext, opts *Opts) (*Macro, error) { 38 macro := &Macro{ 39 ID: id, 40 Opts: opts, 41 } 42 43 if err := macro.Parse(parsingContext, expression); err != nil { 44 return nil, fmt.Errorf("syntax error: %w", err) 45 } 46 47 if err := macro.GenEvaluator(expression, model); err != nil { 48 return nil, fmt.Errorf("compilation error: %w", err) 49 } 50 51 return macro, nil 52 } 53 54 // NewStringValuesMacro returns a new macro from an array of strings 55 func NewStringValuesMacro(id string, values []string, opts *Opts) (*Macro, error) { 56 var evaluator StringValuesEvaluator 57 for _, value := range values { 58 fieldValue := FieldValue{ 59 Type: ScalarValueType, 60 Value: value, 61 } 62 63 evaluator.Values.AppendFieldValue(fieldValue) 64 } 65 66 if err := evaluator.Compile(DefaultStringCmpOpts); err != nil { 67 return nil, err 68 } 69 70 return &Macro{ 71 ID: id, 72 Opts: opts, 73 evaluator: &MacroEvaluator{Value: &evaluator}, 74 }, nil 75 } 76 77 // GetEvaluator - Returns the MacroEvaluator of the Macro corresponding to the SECL `Expression` 78 func (m *Macro) GetEvaluator() *MacroEvaluator { 79 return m.evaluator 80 } 81 82 // GetAst - Returns the representation of the SECL `Expression` 83 func (m *Macro) GetAst() *ast.Macro { 84 return m.ast 85 } 86 87 // Parse - Transforms the SECL `Expression` into its AST representation 88 func (m *Macro) Parse(parsingContext *ast.ParsingContext, expression string) error { 89 astMacro, err := parsingContext.ParseMacro(expression) 90 if err != nil { 91 return err 92 } 93 m.ast = astMacro 94 return nil 95 } 96 97 func macroToEvaluator(macro *ast.Macro, model Model, opts *Opts, field Field) (*MacroEvaluator, error) { 98 macros := make(map[MacroID]*MacroEvaluator) 99 for _, macro := range opts.MacroStore.List() { 100 macros[macro.ID] = macro.evaluator 101 } 102 state := NewState(model, field, macros) 103 104 var eval interface{} 105 var err error 106 107 switch { 108 case macro.Expression != nil: 109 eval, _, err = nodeToEvaluator(macro.Expression, opts, state) 110 case macro.Array != nil: 111 eval, _, err = nodeToEvaluator(macro.Array, opts, state) 112 case macro.Primary != nil: 113 eval, _, err = nodeToEvaluator(macro.Primary, opts, state) 114 } 115 116 if err != nil { 117 return nil, err 118 } 119 120 events, err := eventTypesFromFields(model, state) 121 if err != nil { 122 return nil, err 123 } 124 125 return &MacroEvaluator{ 126 Value: eval, 127 EventTypes: events, 128 129 fieldValues: state.fieldValues, 130 fields: KeysOfMap(state.fieldValues), 131 }, nil 132 } 133 134 // GenEvaluator - Compiles and generates the evalutor 135 func (m *Macro) GenEvaluator(expression string, model Model) error { 136 evaluator, err := macroToEvaluator(m.ast, model, m.Opts, "") 137 if err != nil { 138 if err, ok := err.(*ErrAstToEval); ok { 139 return fmt.Errorf("macro syntax error: %w", &ErrRuleParse{pos: err.Pos, expr: expression}) 140 } 141 return fmt.Errorf("macro compilation error: %w", err) 142 } 143 m.evaluator = evaluator 144 145 return nil 146 } 147 148 // GetEventTypes - Returns a list of all the Event Type that the `Expression` handles 149 func (m *Macro) GetEventTypes() []EventType { 150 eventTypes := m.evaluator.EventTypes 151 152 for _, macro := range m.Opts.MacroStore.List() { 153 eventTypes = append(eventTypes, macro.evaluator.EventTypes...) 154 } 155 156 return eventTypes 157 } 158 159 // GetFields - Returns all the Field that the Macro handles included sub-Macro 160 func (m *Macro) GetFields() []Field { 161 fields := m.evaluator.GetFields() 162 163 for _, macro := range m.Opts.MacroStore.List() { 164 fields = append(fields, macro.evaluator.GetFields()...) 165 } 166 167 return fields 168 } 169 170 // GetFields - Returns all the Field that the MacroEvaluator handles 171 func (m *MacroEvaluator) GetFields() []Field { 172 return m.fields 173 }