conditional.go 2.2 KB

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