github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/rules/actions.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 "errors" 11 "fmt" 12 13 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/ast" 14 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" 15 "github.com/DataDog/datadog-agent/pkg/security/secl/model" 16 ) 17 18 // ActionName defines an action name 19 type ActionName = string 20 21 const ( 22 // KillAction name a the kill action 23 KillAction ActionName = "kill" 24 ) 25 26 // ActionDefinition describes a rule action section 27 type ActionDefinition struct { 28 Filter *string `yaml:"filter"` 29 Set *SetDefinition `yaml:"set"` 30 Kill *KillDefinition `yaml:"kill"` 31 32 // internal 33 InternalCallback *InternalCallbackDefinition 34 FilterEvaluator *eval.RuleEvaluator 35 } 36 37 // Check returns an error if the action in invalid 38 func (a *ActionDefinition) Check(opts PolicyLoaderOpts) error { 39 if a.Set == nil && a.InternalCallback == nil && a.Kill == nil { 40 return errors.New("either 'set' or 'kill' section of an action must be specified") 41 } 42 43 if a.Set != nil { 44 if a.Kill != nil { 45 return errors.New("only of 'set' or 'kill' section of an action can be specified") 46 } 47 48 if a.Set.Name == "" { 49 return errors.New("action name is empty") 50 } 51 52 if (a.Set.Value == nil && a.Set.Field == "") || (a.Set.Value != nil && a.Set.Field != "") { 53 return errors.New("either 'value' or 'field' must be specified") 54 } 55 } else if a.Kill != nil { 56 if opts.DisableEnforcement { 57 a.Kill = nil 58 return errors.New("'kill' action is disabled globally") 59 } 60 61 if a.Kill.Signal == "" { 62 return errors.New("a valid signal has to be specified to the 'kill' action") 63 } 64 65 if _, found := model.SignalConstants[a.Kill.Signal]; !found { 66 return fmt.Errorf("unsupported signal '%s'", a.Kill.Signal) 67 } 68 } 69 70 return nil 71 } 72 73 // CompileFilter compiles the filter expression 74 func (a *ActionDefinition) CompileFilter(parsingContext *ast.ParsingContext, model eval.Model, evalOpts *eval.Opts) error { 75 if a.Filter == nil || *a.Filter == "" { 76 return nil 77 } 78 79 expression := *a.Filter 80 81 rule := &Rule{ 82 Rule: eval.NewRule("action_rule", expression, evalOpts), 83 } 84 85 if err := rule.Parse(parsingContext); err != nil { 86 return &ErrActionFilter{Expression: expression, Err: err} 87 } 88 89 if err := rule.GenEvaluator(model, parsingContext); err != nil { 90 return &ErrActionFilter{Expression: expression, Err: err} 91 } 92 93 a.FilterEvaluator = rule.GetEvaluator() 94 95 return nil 96 } 97 98 // IsAccepted returns whether a filter is accepted and has to be executed 99 func (a *ActionDefinition) IsAccepted(ctx *eval.Context) bool { 100 return a.FilterEvaluator == nil || a.FilterEvaluator.Eval(ctx) 101 } 102 103 // Scope describes the scope variables 104 type Scope string 105 106 // SetDefinition describes the 'set' section of a rule action 107 type SetDefinition struct { 108 Name string `yaml:"name"` 109 Value interface{} `yaml:"value"` 110 Field string `yaml:"field"` 111 Append bool `yaml:"append"` 112 Scope Scope `yaml:"scope"` 113 } 114 115 // InternalCallbackDefinition describes an internal rule action 116 type InternalCallbackDefinition struct{} 117 118 // KillDefinition describes the 'kill' section of a rule action 119 type KillDefinition struct { 120 Signal string `yaml:"signal"` 121 Scope string `yaml:"scope"` 122 }