55 "fmt"
66 "strconv"
77 "strings"
8- "time"
98
109 "github.com/davecgh/go-spew/spew"
1110 "github.com/expr-lang/expr"
@@ -17,7 +16,6 @@ import (
1716 "github.com/crowdsecurity/go-cs-lib/ptr"
1817 "github.com/crowdsecurity/grokky"
1918
20- "github.com/crowdsecurity/crowdsec/pkg/cache"
2119 "github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
2220 "github.com/crowdsecurity/crowdsec/pkg/metrics"
2321 "github.com/crowdsecurity/crowdsec/pkg/types"
@@ -63,7 +61,8 @@ type Node struct {
6361 Statics []Static `yaml:"statics,omitempty"`
6462 RuntimeStatics []RuntimeStatic `yaml:"-"`
6563 // Stash allows to capture data from the log line and store it in an accessible cache
66- Stash []DataCapture `yaml:"stash,omitempty"`
64+ Stashes []Stash `yaml:"stash,omitempty"`
65+ RuntimeStashes []RuntimeStash `yaml:"-"`
6766 // Whitelists
6867 Whitelist Whitelist `yaml:"whitelist,omitempty"`
6968 Data []* types.DataSource `yaml:"data,omitempty"`
@@ -96,32 +95,9 @@ func (n *Node) validate(ectx EnricherCtx) error {
9695 }
9796 }
9897
99- for idx := range n .Stash {
100- // pointer not value, to avoid throwing away the defaults
101- stash := & n .Stash [idx ]
102-
103- if stash .Name == "" {
104- return fmt .Errorf ("stash %d: name must be set" , idx )
105- }
106-
107- if stash .Value == "" {
108- return fmt .Errorf ("stash %s: value expression must be set" , stash .Name )
109- }
110-
111- if stash .Key == "" {
112- return fmt .Errorf ("stash %s: key expression must be set" , stash .Name )
113- }
114-
115- if stash .TTL == "" {
116- return fmt .Errorf ("stash %s: ttl must be set" , stash .Name )
117- }
118-
119- if stash .Strategy == "" {
120- stash .Strategy = "LRU"
121- }
122- // should be configurable
123- if stash .MaxMapSize == 0 {
124- stash .MaxMapSize = 100
98+ for idx , stash := range n .Stashes {
99+ if err := stash .Validate (); err != nil {
100+ return fmt .Errorf ("stash %d: %w" , idx , err )
125101 }
126102 }
127103
@@ -270,52 +246,8 @@ func (n *Node) processGrok(p *types.Event, cachedExprEnv map[string]any) (bool,
270246}
271247
272248func (n * Node ) processStash (_ * types.Event , cachedExprEnv map [string ]any , logger * log.Entry ) error {
273- for idx , stash := range n .Stash {
274- var (
275- key string
276- value string
277- )
278-
279- if stash .ValueExpression == nil {
280- logger .Warningf ("Stash %d has no value expression, skipping" , idx )
281- continue
282- }
283-
284- if stash .KeyExpression == nil {
285- logger .Warningf ("Stash %d has no key expression, skipping" , idx )
286- continue
287- }
288- // collect the data
289- output , err := exprhelpers .Run (stash .ValueExpression , cachedExprEnv , logger , n .Debug )
290- if err != nil {
291- logger .Warningf ("Error while running stash val expression: %v" , err )
292- }
293- // can we expect anything else than a string ?
294- switch output := output .(type ) {
295- case string :
296- value = output
297- default :
298- logger .Warningf ("unexpected type %T (%v) while running %q" , output , output , stash .Value )
299- continue
300- }
301-
302- // collect the key
303- output , err = exprhelpers .Run (stash .KeyExpression , cachedExprEnv , logger , n .Debug )
304- if err != nil {
305- logger .Warningf ("Error while running stash key expression: %v" , err )
306- }
307- // can we expect anything else than a string ?
308- switch output := output .(type ) {
309- case string :
310- key = output
311- default :
312- logger .Warningf ("unexpected type %T (%v) while running %q" , output , output , stash .Key )
313- continue
314- }
315-
316- if err = cache .SetKey (stash .Name , key , value , & stash .TTLVal ); err != nil {
317- logger .Warningf ("failed to store data in cache: %s" , err .Error ())
318- }
249+ for idx , stash := range n .RuntimeStashes {
250+ stash .Apply (idx , cachedExprEnv , n .Logger , n .Debug )
319251 }
320252
321253 return nil
@@ -531,36 +463,12 @@ func (n *Node) compile(pctx *UnixParserCtx, ectx EnricherCtx) error {
531463 valid = true
532464 }
533465
534- /* load data capture (stash) */
535- for i , stash := range n .Stash {
536- n .Stash [i ].ValueExpression , err = expr .Compile (stash .Value ,
537- exprhelpers .GetExprOptions (map [string ]any {"evt" : & types.Event {}})... )
466+ for _ , stash := range n .Stashes {
467+ compiled , err := stash .Compile (n .Logger )
538468 if err != nil {
539- return fmt .Errorf ("while compiling stash value expression: %w" , err )
540- }
541-
542- n .Stash [i ].KeyExpression , err = expr .Compile (stash .Key ,
543- exprhelpers .GetExprOptions (map [string ]any {"evt" : & types.Event {}})... )
544- if err != nil {
545- return fmt .Errorf ("while compiling stash key expression: %w" , err )
546- }
547-
548- n .Stash [i ].TTLVal , err = time .ParseDuration (stash .TTL )
549- if err != nil {
550- return fmt .Errorf ("while parsing stash ttl: %w" , err )
551- }
552-
553- logLvl := n .Logger .Logger .GetLevel ()
554- // init the cache, does it make sense to create it here just to be sure everything is fine ?
555- if err = cache .CacheInit (cache.CacheCfg {
556- Size : n .Stash [i ].MaxMapSize ,
557- TTL : n .Stash [i ].TTLVal ,
558- Name : n .Stash [i ].Name ,
559- Strategy : n .Stash [i ].Strategy ,
560- LogLevel : & logLvl ,
561- }); err != nil {
562- return fmt .Errorf ("while initializing cache: %w" , err )
469+ return fmt .Errorf ("stash %s: %w" , stash .Name , err )
563470 }
471+ n .RuntimeStashes = append (n .RuntimeStashes , * compiled )
564472 }
565473
566474 /* compile leafs if present */
0 commit comments