2023-01-06 08:26:16 +00:00
|
|
|
package leakybucket
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2023-03-27 14:01:42 +00:00
|
|
|
"sync"
|
2023-01-06 08:26:16 +00:00
|
|
|
|
|
|
|
"github.com/antonmedv/expr"
|
|
|
|
"github.com/antonmedv/expr/vm"
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
|
|
|
)
|
|
|
|
|
2023-03-27 14:01:42 +00:00
|
|
|
var conditionalExprCache map[string]vm.Program
|
|
|
|
var conditionalExprCacheLock sync.Mutex
|
|
|
|
|
2023-01-06 08:26:16 +00:00
|
|
|
type ConditionalOverflow struct {
|
|
|
|
ConditionalFilter string
|
|
|
|
ConditionalFilterRuntime *vm.Program
|
|
|
|
DumbProcessor
|
|
|
|
}
|
|
|
|
|
2023-03-27 14:01:42 +00:00
|
|
|
func (c *ConditionalOverflow) OnBucketInit(g *BucketFactory) error {
|
2023-01-06 08:26:16 +00:00
|
|
|
var err error
|
2023-03-27 14:01:42 +00:00
|
|
|
var compiledExpr *vm.Program
|
2023-01-06 08:26:16 +00:00
|
|
|
|
2023-03-27 14:01:42 +00:00
|
|
|
if conditionalExprCache == nil {
|
|
|
|
conditionalExprCache = make(map[string]vm.Program)
|
|
|
|
}
|
|
|
|
conditionalExprCacheLock.Lock()
|
|
|
|
if compiled, ok := conditionalExprCache[g.ConditionalOverflow]; ok {
|
|
|
|
conditionalExprCacheLock.Unlock()
|
|
|
|
c.ConditionalFilterRuntime = &compiled
|
|
|
|
} else {
|
|
|
|
conditionalExprCacheLock.Unlock()
|
|
|
|
//release the lock during compile
|
2023-11-24 10:10:54 +00:00
|
|
|
compiledExpr, err = expr.Compile(g.ConditionalOverflow, exprhelpers.GetExprOptions(map[string]interface{}{"queue": &types.Queue{}, "leaky": &Leaky{}, "evt": &types.Event{}})...)
|
2023-03-27 14:01:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("conditional compile error : %w", err)
|
|
|
|
}
|
|
|
|
c.ConditionalFilterRuntime = compiledExpr
|
|
|
|
conditionalExprCacheLock.Lock()
|
|
|
|
conditionalExprCache[g.ConditionalOverflow] = *compiledExpr
|
|
|
|
conditionalExprCacheLock.Unlock()
|
2023-01-06 08:26:16 +00:00
|
|
|
}
|
2023-03-27 14:01:42 +00:00
|
|
|
return err
|
2023-01-06 08:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ConditionalOverflow) AfterBucketPour(b *BucketFactory) func(types.Event, *Leaky) *types.Event {
|
|
|
|
return func(msg types.Event, l *Leaky) *types.Event {
|
|
|
|
var condition, ok bool
|
|
|
|
if c.ConditionalFilterRuntime != nil {
|
|
|
|
l.logger.Debugf("Running condition expression : %s", c.ConditionalFilter)
|
2023-11-24 10:10:54 +00:00
|
|
|
|
|
|
|
ret, err := exprhelpers.Run(c.ConditionalFilterRuntime,
|
|
|
|
map[string]interface{}{"evt": &msg, "queue": l.Queue, "leaky": l},
|
|
|
|
l.logger, b.Debug)
|
2023-01-06 08:26:16 +00:00
|
|
|
if err != nil {
|
|
|
|
l.logger.Errorf("unable to run conditional filter : %s", err)
|
|
|
|
return &msg
|
|
|
|
}
|
|
|
|
l.logger.Debugf("Conditional bucket expression returned : %v", ret)
|
|
|
|
|
|
|
|
if condition, ok = ret.(bool); !ok {
|
|
|
|
l.logger.Warningf("overflow condition, unexpected non-bool return : %T", ret)
|
|
|
|
return &msg
|
|
|
|
}
|
|
|
|
|
|
|
|
if condition {
|
|
|
|
l.logger.Debugf("Conditional bucket overflow")
|
2023-04-28 14:32:46 +00:00
|
|
|
l.Ovflw_ts = l.Last_ts
|
2023-01-06 08:26:16 +00:00
|
|
|
l.Out <- l.Queue
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &msg
|
|
|
|
}
|
|
|
|
}
|