github.com/crowdsecurity/crowdsec@v1.6.1/pkg/leakybucket/conditional.go (about)

     1  package leakybucket
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/antonmedv/expr"
     8  	"github.com/antonmedv/expr/vm"
     9  	"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
    10  	"github.com/crowdsecurity/crowdsec/pkg/types"
    11  )
    12  
    13  var conditionalExprCache map[string]vm.Program
    14  var conditionalExprCacheLock sync.Mutex
    15  
    16  type ConditionalOverflow struct {
    17  	ConditionalFilter        string
    18  	ConditionalFilterRuntime *vm.Program
    19  	DumbProcessor
    20  }
    21  
    22  func (c *ConditionalOverflow) OnBucketInit(g *BucketFactory) error {
    23  	var err error
    24  	var compiledExpr *vm.Program
    25  
    26  	if conditionalExprCache == nil {
    27  		conditionalExprCache = make(map[string]vm.Program)
    28  	}
    29  	conditionalExprCacheLock.Lock()
    30  	if compiled, ok := conditionalExprCache[g.ConditionalOverflow]; ok {
    31  		conditionalExprCacheLock.Unlock()
    32  		c.ConditionalFilterRuntime = &compiled
    33  	} else {
    34  		conditionalExprCacheLock.Unlock()
    35  		//release the lock during compile
    36  		compiledExpr, err = expr.Compile(g.ConditionalOverflow, exprhelpers.GetExprOptions(map[string]interface{}{"queue": &types.Queue{}, "leaky": &Leaky{}, "evt": &types.Event{}})...)
    37  		if err != nil {
    38  			return fmt.Errorf("conditional compile error : %w", err)
    39  		}
    40  		c.ConditionalFilterRuntime = compiledExpr
    41  		conditionalExprCacheLock.Lock()
    42  		conditionalExprCache[g.ConditionalOverflow] = *compiledExpr
    43  		conditionalExprCacheLock.Unlock()
    44  	}
    45  	return err
    46  }
    47  
    48  func (c *ConditionalOverflow) AfterBucketPour(b *BucketFactory) func(types.Event, *Leaky) *types.Event {
    49  	return func(msg types.Event, l *Leaky) *types.Event {
    50  		var condition, ok bool
    51  		if c.ConditionalFilterRuntime != nil {
    52  			l.logger.Debugf("Running condition expression : %s", c.ConditionalFilter)
    53  
    54  			ret, err := exprhelpers.Run(c.ConditionalFilterRuntime,
    55  				map[string]interface{}{"evt": &msg, "queue": l.Queue, "leaky": l},
    56  				l.logger, b.Debug)
    57  			if err != nil {
    58  				l.logger.Errorf("unable to run conditional filter : %s", err)
    59  				return &msg
    60  			}
    61  			l.logger.Debugf("Conditional bucket expression returned : %v", ret)
    62  
    63  			if condition, ok = ret.(bool); !ok {
    64  				l.logger.Warningf("overflow condition, unexpected non-bool return : %T", ret)
    65  				return &msg
    66  			}
    67  
    68  			if condition {
    69  				l.logger.Debugf("Conditional bucket overflow")
    70  				l.Ovflw_ts = l.Last_ts
    71  				l.Out <- l.Queue
    72  				return nil
    73  			}
    74  		}
    75  
    76  		return &msg
    77  	}
    78  }