github.com/crowdsecurity/crowdsec@v1.6.1/pkg/parser/whitelist.go (about)

     1  package parser
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     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  	"github.com/prometheus/client_golang/prometheus"
    12  )
    13  
    14  type Whitelist struct {
    15  	Reason  string   `yaml:"reason,omitempty"`
    16  	Ips     []string `yaml:"ip,omitempty"`
    17  	B_Ips   []net.IP
    18  	Cidrs   []string `yaml:"cidr,omitempty"`
    19  	B_Cidrs []*net.IPNet
    20  	Exprs   []string `yaml:"expression,omitempty"`
    21  	B_Exprs []*ExprWhitelist
    22  }
    23  
    24  type ExprWhitelist struct {
    25  	Filter *vm.Program
    26  }
    27  
    28  func (n *Node) ContainsWLs() bool {
    29  	return n.ContainsIPLists() || n.ContainsExprLists()
    30  }
    31  
    32  func (n *Node) ContainsExprLists() bool {
    33  	return len(n.Whitelist.B_Exprs) > 0
    34  }
    35  
    36  func (n *Node) ContainsIPLists() bool {
    37  	return len(n.Whitelist.B_Ips) > 0 || len(n.Whitelist.B_Cidrs) > 0
    38  }
    39  
    40  func (n *Node) CheckIPsWL(p *types.Event) bool {
    41  	srcs := p.ParseIPSources()
    42  	isWhitelisted := false
    43  	if !n.ContainsIPLists() {
    44  		return isWhitelisted
    45  	}
    46  	NodesWlHits.With(prometheus.Labels{"source": p.Line.Src, "type": p.Line.Module, "name": n.Name, "reason": n.Whitelist.Reason}).Inc()
    47  	for _, src := range srcs {
    48  		if isWhitelisted {
    49  			break
    50  		}
    51  		for _, v := range n.Whitelist.B_Ips {
    52  			if v.Equal(src) {
    53  				n.Logger.Debugf("Event from [%s] is whitelisted by IP (%s), reason [%s]", src, v, n.Whitelist.Reason)
    54  				isWhitelisted = true
    55  				break
    56  			}
    57  			n.Logger.Tracef("whitelist: %s is not eq [%s]", src, v)
    58  		}
    59  		for _, v := range n.Whitelist.B_Cidrs {
    60  			if v.Contains(src) {
    61  				n.Logger.Debugf("Event from [%s] is whitelisted by CIDR (%s), reason [%s]", src, v, n.Whitelist.Reason)
    62  				isWhitelisted = true
    63  				break
    64  			}
    65  			n.Logger.Tracef("whitelist: %s not in [%s]", src, v)
    66  		}
    67  	}
    68  	if isWhitelisted {
    69  		NodesWlHitsOk.With(prometheus.Labels{"source": p.Line.Src, "type": p.Line.Module, "name": n.Name, "reason": n.Whitelist.Reason}).Inc()
    70  	}
    71  	return isWhitelisted
    72  }
    73  
    74  func (n *Node) CheckExprWL(cachedExprEnv map[string]interface{}, p *types.Event) (bool, error) {
    75  	isWhitelisted := false
    76  
    77  	if !n.ContainsExprLists() {
    78  		return false, nil
    79  	}
    80  	NodesWlHits.With(prometheus.Labels{"source": p.Line.Src, "type": p.Line.Module, "name": n.Name, "reason": n.Whitelist.Reason}).Inc()
    81  	/* run whitelist expression tests anyway */
    82  	for eidx, e := range n.Whitelist.B_Exprs {
    83  		//if we already know the event is whitelisted, skip the rest of the expressions
    84  		if isWhitelisted {
    85  			break
    86  		}
    87  
    88  		output, err := exprhelpers.Run(e.Filter, cachedExprEnv, n.Logger, n.Debug)
    89  		if err != nil {
    90  			n.Logger.Warningf("failed to run whitelist expr : %v", err)
    91  			n.Logger.Debug("Event leaving node : ko")
    92  			return isWhitelisted, err
    93  		}
    94  		switch out := output.(type) {
    95  		case bool:
    96  			if out {
    97  				n.Logger.Debugf("Event is whitelisted by expr, reason [%s]", n.Whitelist.Reason)
    98  				isWhitelisted = true
    99  			}
   100  		default:
   101  			n.Logger.Errorf("unexpected type %t (%v) while running '%s'", output, output, n.Whitelist.Exprs[eidx])
   102  		}
   103  	}
   104  	if isWhitelisted {
   105  		NodesWlHitsOk.With(prometheus.Labels{"source": p.Line.Src, "type": p.Line.Module, "name": n.Name, "reason": n.Whitelist.Reason}).Inc()
   106  	}
   107  	return isWhitelisted, nil
   108  }
   109  
   110  func (n *Node) CompileWLs() (bool, error) {
   111  	for _, v := range n.Whitelist.Ips {
   112  		n.Whitelist.B_Ips = append(n.Whitelist.B_Ips, net.ParseIP(v))
   113  		n.Logger.Debugf("adding ip %s to whitelists", net.ParseIP(v))
   114  	}
   115  
   116  	for _, v := range n.Whitelist.Cidrs {
   117  		_, tnet, err := net.ParseCIDR(v)
   118  		if err != nil {
   119  			return false, fmt.Errorf("unable to parse cidr whitelist '%s' : %v", v, err)
   120  		}
   121  		n.Whitelist.B_Cidrs = append(n.Whitelist.B_Cidrs, tnet)
   122  		n.Logger.Debugf("adding cidr %s to whitelists", tnet)
   123  	}
   124  
   125  	for _, filter := range n.Whitelist.Exprs {
   126  		var err error
   127  		expression := &ExprWhitelist{}
   128  		expression.Filter, err = expr.Compile(filter, exprhelpers.GetExprOptions(map[string]interface{}{"evt": &types.Event{}})...)
   129  		if err != nil {
   130  			return false, fmt.Errorf("unable to compile whitelist expression '%s' : %v", filter, err)
   131  		}
   132  		n.Whitelist.B_Exprs = append(n.Whitelist.B_Exprs, expression)
   133  		n.Logger.Debugf("adding expression %s to whitelists", filter)
   134  	}
   135  	return n.ContainsWLs(), nil
   136  }