csprofiles: fix default decision duration, lint (#2703)
* return nil with errors * errors.Wrap -> fmt.Errorf * var -> const * fix default decision duration * lint (whitespace)
This commit is contained in:
parent
0ef5f20aa7
commit
733f5e165b
1 changed files with 36 additions and 24 deletions
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"github.com/antonmedv/expr"
|
"github.com/antonmedv/expr"
|
||||||
"github.com/antonmedv/expr/vm"
|
"github.com/antonmedv/expr/vm"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
|
@ -22,19 +21,23 @@ type Runtime struct {
|
||||||
Logger *log.Entry `json:"-" yaml:"-"`
|
Logger *log.Entry `json:"-" yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultDuration = "4h"
|
const defaultDuration = "4h"
|
||||||
|
|
||||||
func NewProfile(profilesCfg []*csconfig.ProfileCfg) ([]*Runtime, error) {
|
func NewProfile(profilesCfg []*csconfig.ProfileCfg) ([]*Runtime, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
profilesRuntime := make([]*Runtime, 0)
|
profilesRuntime := make([]*Runtime, 0)
|
||||||
|
|
||||||
for _, profile := range profilesCfg {
|
for _, profile := range profilesCfg {
|
||||||
var runtimeFilter, runtimeDurationExpr *vm.Program
|
var runtimeFilter, runtimeDurationExpr *vm.Program
|
||||||
|
|
||||||
runtime := &Runtime{}
|
runtime := &Runtime{}
|
||||||
|
|
||||||
xlog := log.New()
|
xlog := log.New()
|
||||||
if err := types.ConfigureLogger(xlog); err != nil {
|
if err := types.ConfigureLogger(xlog); err != nil {
|
||||||
log.Fatalf("While creating profiles-specific logger : %s", err)
|
log.Fatalf("While creating profiles-specific logger : %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
xlog.SetLevel(log.InfoLevel)
|
xlog.SetLevel(log.InfoLevel)
|
||||||
runtime.Logger = xlog.WithFields(log.Fields{
|
runtime.Logger = xlog.WithFields(log.Fields{
|
||||||
"type": "profile",
|
"type": "profile",
|
||||||
|
@ -43,17 +46,20 @@ func NewProfile(profilesCfg []*csconfig.ProfileCfg) ([]*Runtime, error) {
|
||||||
|
|
||||||
runtime.RuntimeFilters = make([]*vm.Program, len(profile.Filters))
|
runtime.RuntimeFilters = make([]*vm.Program, len(profile.Filters))
|
||||||
runtime.Cfg = profile
|
runtime.Cfg = profile
|
||||||
if runtime.Cfg.OnSuccess != "" && runtime.Cfg.OnSuccess != "continue" && runtime.Cfg.OnSuccess != "break" {
|
|
||||||
return []*Runtime{}, fmt.Errorf("invalid 'on_success' for '%s': %s", profile.Name, runtime.Cfg.OnSuccess)
|
|
||||||
}
|
|
||||||
if runtime.Cfg.OnFailure != "" && runtime.Cfg.OnFailure != "continue" && runtime.Cfg.OnFailure != "break" && runtime.Cfg.OnFailure != "apply" {
|
|
||||||
return []*Runtime{}, fmt.Errorf("invalid 'on_failure' for '%s' : %s", profile.Name, runtime.Cfg.OnFailure)
|
|
||||||
}
|
|
||||||
for fIdx, filter := range profile.Filters {
|
|
||||||
|
|
||||||
|
if runtime.Cfg.OnSuccess != "" && runtime.Cfg.OnSuccess != "continue" && runtime.Cfg.OnSuccess != "break" {
|
||||||
|
return nil, fmt.Errorf("invalid 'on_success' for '%s': %s", profile.Name, runtime.Cfg.OnSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.Cfg.OnFailure != "" && runtime.Cfg.OnFailure != "continue" && runtime.Cfg.OnFailure != "break" && runtime.Cfg.OnFailure != "apply" {
|
||||||
|
return nil, fmt.Errorf("invalid 'on_failure' for '%s' : %s", profile.Name, runtime.Cfg.OnFailure)
|
||||||
|
}
|
||||||
|
|
||||||
|
for fIdx, filter := range profile.Filters {
|
||||||
if runtimeFilter, err = expr.Compile(filter, exprhelpers.GetExprOptions(map[string]interface{}{"Alert": &models.Alert{}})...); err != nil {
|
if runtimeFilter, err = expr.Compile(filter, exprhelpers.GetExprOptions(map[string]interface{}{"Alert": &models.Alert{}})...); err != nil {
|
||||||
return []*Runtime{}, errors.Wrapf(err, "error compiling filter of '%s'", profile.Name)
|
return nil, fmt.Errorf("error compiling filter of '%s': %w", profile.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.RuntimeFilters[fIdx] = runtimeFilter
|
runtime.RuntimeFilters[fIdx] = runtimeFilter
|
||||||
if profile.Debug != nil && *profile.Debug {
|
if profile.Debug != nil && *profile.Debug {
|
||||||
runtime.Logger.Logger.SetLevel(log.DebugLevel)
|
runtime.Logger.Logger.SetLevel(log.DebugLevel)
|
||||||
|
@ -62,8 +68,9 @@ func NewProfile(profilesCfg []*csconfig.ProfileCfg) ([]*Runtime, error) {
|
||||||
|
|
||||||
if profile.DurationExpr != "" {
|
if profile.DurationExpr != "" {
|
||||||
if runtimeDurationExpr, err = expr.Compile(profile.DurationExpr, exprhelpers.GetExprOptions(map[string]interface{}{"Alert": &models.Alert{}})...); err != nil {
|
if runtimeDurationExpr, err = expr.Compile(profile.DurationExpr, exprhelpers.GetExprOptions(map[string]interface{}{"Alert": &models.Alert{}})...); err != nil {
|
||||||
return []*Runtime{}, errors.Wrapf(err, "error compiling duration_expr of %s", profile.Name)
|
return nil, fmt.Errorf("error compiling duration_expr of %s: %w", profile.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.RuntimeDurationExpr = runtimeDurationExpr
|
runtime.RuntimeDurationExpr = runtimeDurationExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,14 +83,16 @@ func NewProfile(profilesCfg []*csconfig.ProfileCfg) ([]*Runtime, error) {
|
||||||
runtime.Logger.Warningf("No duration specified for %s, using default duration %s", profile.Name, defaultDuration)
|
runtime.Logger.Warningf("No duration specified for %s, using default duration %s", profile.Name, defaultDuration)
|
||||||
duration = defaultDuration
|
duration = defaultDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := time.ParseDuration(duration); err != nil {
|
if _, err := time.ParseDuration(duration); err != nil {
|
||||||
return []*Runtime{}, errors.Wrapf(err, "error parsing duration '%s' of %s", duration, profile.Name)
|
return nil, fmt.Errorf("error parsing duration '%s' of %s: %w", duration, profile.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profilesRuntime = append(profilesRuntime, runtime)
|
profilesRuntime = append(profilesRuntime, runtime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return profilesRuntime, nil
|
return profilesRuntime, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,30 +119,29 @@ func (Profile *Runtime) GenerateDecisionFromProfile(Alert *models.Alert) ([]*mod
|
||||||
*decision.Scope = *Alert.Source.Scope
|
*decision.Scope = *Alert.Source.Scope
|
||||||
}
|
}
|
||||||
/*some fields are populated from the reference object : duration, scope, type*/
|
/*some fields are populated from the reference object : duration, scope, type*/
|
||||||
|
|
||||||
decision.Duration = new(string)
|
decision.Duration = new(string)
|
||||||
|
if refDecision.Duration != nil {
|
||||||
|
*decision.Duration = *refDecision.Duration
|
||||||
|
}
|
||||||
|
|
||||||
if Profile.Cfg.DurationExpr != "" && Profile.RuntimeDurationExpr != nil {
|
if Profile.Cfg.DurationExpr != "" && Profile.RuntimeDurationExpr != nil {
|
||||||
profileDebug := false
|
profileDebug := false
|
||||||
if Profile.Cfg.Debug != nil && *Profile.Cfg.Debug {
|
if Profile.Cfg.Debug != nil && *Profile.Cfg.Debug {
|
||||||
profileDebug = true
|
profileDebug = true
|
||||||
}
|
}
|
||||||
|
|
||||||
duration, err := exprhelpers.Run(Profile.RuntimeDurationExpr, map[string]interface{}{"Alert": Alert}, Profile.Logger, profileDebug)
|
duration, err := exprhelpers.Run(Profile.RuntimeDurationExpr, map[string]interface{}{"Alert": Alert}, Profile.Logger, profileDebug)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Profile.Logger.Warningf("Failed to run duration_expr : %v", err)
|
Profile.Logger.Warningf("Failed to run duration_expr : %v", err)
|
||||||
*decision.Duration = *refDecision.Duration
|
|
||||||
} else {
|
} else {
|
||||||
durationStr := fmt.Sprint(duration)
|
durationStr := fmt.Sprint(duration)
|
||||||
if _, err := time.ParseDuration(durationStr); err != nil {
|
if _, err := time.ParseDuration(durationStr); err != nil {
|
||||||
Profile.Logger.Warningf("Failed to parse expr duration result '%s'", duration)
|
Profile.Logger.Warningf("Failed to parse expr duration result '%s'", duration)
|
||||||
*decision.Duration = *refDecision.Duration
|
|
||||||
} else {
|
} else {
|
||||||
*decision.Duration = durationStr
|
*decision.Duration = durationStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if refDecision.Duration == nil {
|
|
||||||
*decision.Duration = defaultDuration
|
|
||||||
}
|
|
||||||
*decision.Duration = *refDecision.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decision.Type = new(string)
|
decision.Type = new(string)
|
||||||
|
@ -144,13 +152,16 @@ func (Profile *Runtime) GenerateDecisionFromProfile(Alert *models.Alert) ([]*mod
|
||||||
*decision.Value = *Alert.Source.Value
|
*decision.Value = *Alert.Source.Value
|
||||||
decision.Origin = new(string)
|
decision.Origin = new(string)
|
||||||
*decision.Origin = types.CrowdSecOrigin
|
*decision.Origin = types.CrowdSecOrigin
|
||||||
|
|
||||||
if refDecision.Origin != nil {
|
if refDecision.Origin != nil {
|
||||||
*decision.Origin = fmt.Sprintf("%s/%s", *decision.Origin, *refDecision.Origin)
|
*decision.Origin = fmt.Sprintf("%s/%s", *decision.Origin, *refDecision.Origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
decision.Scenario = new(string)
|
decision.Scenario = new(string)
|
||||||
*decision.Scenario = *Alert.Scenario
|
*decision.Scenario = *Alert.Scenario
|
||||||
decisions = append(decisions, &decision)
|
decisions = append(decisions, &decision)
|
||||||
}
|
}
|
||||||
|
|
||||||
return decisions, nil
|
return decisions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,16 +170,19 @@ func (Profile *Runtime) EvaluateProfile(Alert *models.Alert) ([]*models.Decision
|
||||||
var decisions []*models.Decision
|
var decisions []*models.Decision
|
||||||
|
|
||||||
matched := false
|
matched := false
|
||||||
|
|
||||||
for eIdx, expression := range Profile.RuntimeFilters {
|
for eIdx, expression := range Profile.RuntimeFilters {
|
||||||
debugProfile := false
|
debugProfile := false
|
||||||
if Profile.Cfg.Debug != nil && *Profile.Cfg.Debug {
|
if Profile.Cfg.Debug != nil && *Profile.Cfg.Debug {
|
||||||
debugProfile = true
|
debugProfile = true
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := exprhelpers.Run(expression, map[string]interface{}{"Alert": Alert}, Profile.Logger, debugProfile)
|
output, err := exprhelpers.Run(expression, map[string]interface{}{"Alert": Alert}, Profile.Logger, debugProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Profile.Logger.Warningf("failed to run profile expr for %s : %v", Profile.Cfg.Name, err)
|
Profile.Logger.Warningf("failed to run profile expr for %s: %v", Profile.Cfg.Name, err)
|
||||||
return nil, matched, errors.Wrapf(err, "while running expression %s", Profile.Cfg.Filters[eIdx])
|
return nil, matched, fmt.Errorf("while running expression %s: %w", Profile.Cfg.Filters[eIdx], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch out := output.(type) {
|
switch out := output.(type) {
|
||||||
case bool:
|
case bool:
|
||||||
if out {
|
if out {
|
||||||
|
@ -176,7 +190,7 @@ func (Profile *Runtime) EvaluateProfile(Alert *models.Alert) ([]*models.Decision
|
||||||
/*the expression matched, create the associated decision*/
|
/*the expression matched, create the associated decision*/
|
||||||
subdecisions, err := Profile.GenerateDecisionFromProfile(Alert)
|
subdecisions, err := Profile.GenerateDecisionFromProfile(Alert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, matched, errors.Wrapf(err, "while generating decision from profile %s", Profile.Cfg.Name)
|
return nil, matched, fmt.Errorf("while generating decision from profile %s: %w", Profile.Cfg.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
decisions = append(decisions, subdecisions...)
|
decisions = append(decisions, subdecisions...)
|
||||||
|
@ -189,9 +203,7 @@ func (Profile *Runtime) EvaluateProfile(Alert *models.Alert) ([]*models.Decision
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, matched, fmt.Errorf("unexpected type %t (%v) while running '%s'", output, output, Profile.Cfg.Filters[eIdx])
|
return nil, matched, fmt.Errorf("unexpected type %t (%v) while running '%s'", output, output, Profile.Cfg.Filters[eIdx])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return decisions, matched, nil
|
return decisions, matched, nil
|
||||||
|
|
Loading…
Reference in a new issue