-
Notifications
You must be signed in to change notification settings - Fork 467
/
profiles.go
87 lines (76 loc) · 3.07 KB
/
profiles.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package csconfig
import (
"fmt"
"io"
"os"
"time"
"github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm"
"github.com/crowdsecurity/crowdsec/pkg/exprhelpers"
"github.com/crowdsecurity/crowdsec/pkg/models"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)
//Profile structure(s) are used by the local API to "decide" what kind of decision should be applied when a scenario with an active remediation has been triggered
type ProfileCfg struct {
Name string `yaml:"name,omitempty"`
Debug *bool `yaml:"debug,omitempty"`
Filters []string `yaml:"filters,omitempty"` //A list of OR'ed expressions. the models.Alert object
RuntimeFilters []*vm.Program `json:"-" yaml:"-"`
DebugFilters []*exprhelpers.ExprDebugger `json:"-" yaml:"-"`
Decisions []models.Decision `yaml:"decisions,omitempty"`
OnSuccess string `yaml:"on_success,omitempty"` //continue or break
OnFailure string `yaml:"on_failure,omitempty"` //continue or break
Notifications []string `yaml:"notifications,omitempty"`
}
func (c *LocalApiServerCfg) LoadProfiles() error {
if c.ProfilesPath == "" {
return fmt.Errorf("empty profiles path")
}
yamlFile, err := os.Open(c.ProfilesPath)
if err != nil {
return errors.Wrapf(err, "while opening %s", c.ProfilesPath)
}
//process the yaml
dec := yaml.NewDecoder(yamlFile)
dec.SetStrict(true)
for {
t := ProfileCfg{}
err = dec.Decode(&t)
if err != nil {
if err == io.EOF {
break
}
return errors.Wrapf(err, "while decoding %s", c.ProfilesPath)
}
c.Profiles = append(c.Profiles, &t)
}
for pIdx, profile := range c.Profiles {
var runtimeFilter *vm.Program
var debugFilter *exprhelpers.ExprDebugger
c.Profiles[pIdx].RuntimeFilters = make([]*vm.Program, len(profile.Filters))
c.Profiles[pIdx].DebugFilters = make([]*exprhelpers.ExprDebugger, len(profile.Filters))
for fIdx, filter := range profile.Filters {
if runtimeFilter, err = expr.Compile(filter, expr.Env(exprhelpers.GetExprEnv(map[string]interface{}{"Alert": &models.Alert{}}))); err != nil {
return errors.Wrapf(err, "Error compiling filter of %s", profile.Name)
}
c.Profiles[pIdx].RuntimeFilters[fIdx] = runtimeFilter
if debugFilter, err = exprhelpers.NewDebugger(filter, expr.Env(exprhelpers.GetExprEnv(map[string]interface{}{"Alert": &models.Alert{}}))); err != nil {
log.Debugf("Error compiling debug filter of %s : %s", profile.Name, err)
// Don't fail if we can't compile the filter - for now
// return errors.Wrapf(err, "Error compiling debug filter of %s", profile.Name)
}
c.Profiles[pIdx].DebugFilters[fIdx] = debugFilter
}
for _, decision := range profile.Decisions {
if _, err := time.ParseDuration(*decision.Duration); err != nil {
return errors.Wrapf(err, "Error parsing duration '%s' of %s", *decision.Duration, profile.Name)
}
}
}
if len(c.Profiles) == 0 {
return fmt.Errorf("zero profiles loaded for LAPI")
}
return nil
}