From 3585467f1490c50ef621d8051197316fbf753328 Mon Sep 17 00:00:00 2001 From: Thibault bui Koechlin Date: Fri, 10 Jul 2020 17:17:53 +0200 Subject: [PATCH] support simulation mode --- cmd/crowdsec/output.go | 12 ++++++ pkg/csconfig/config.go | 75 +++++++++++++++++++---------------- pkg/outputs/ouputs.go | 9 +++-- pkg/types/signal_occurence.go | 1 + 4 files changed, 60 insertions(+), 37 deletions(-) diff --git a/cmd/crowdsec/output.go b/cmd/crowdsec/output.go index f4c8d2334..5ff0f64dd 100644 --- a/cmd/crowdsec/output.go +++ b/cmd/crowdsec/output.go @@ -33,6 +33,10 @@ LOOP: log.Infof("Done shutdown down output") break LOOP case event := <-overflow: + //if global simulation -> everything is simulation unless told otherwise + if cConfig.SimulationCfg != nil && cConfig.SimulationCfg.Simulation { + event.Overflow.Simulation = true + } if cConfig.Profiling { start = time.Now() } @@ -47,6 +51,14 @@ LOOP: if err != nil { return fmt.Errorf("postoverflow failed : %s", err) } + //check scenarios in simulation + if cConfig.SimulationCfg != nil { + for _, scenario_name := range cConfig.SimulationCfg.Exclusions { + if event.Overflow.Scenario == scenario_name { + event.Overflow.Simulation = !event.Overflow.Simulation + } + } + } if event.Overflow.Scenario == "" && event.Overflow.MapKey != "" { //log.Infof("Deleting expired entry %s", event.Overflow.MapKey) diff --git a/pkg/csconfig/config.go b/pkg/csconfig/config.go index 823d79696..de962acd0 100644 --- a/pkg/csconfig/config.go +++ b/pkg/csconfig/config.go @@ -15,29 +15,36 @@ import ( "gopkg.in/yaml.v2" ) +type SimulationConfig struct { + Simulation bool `yaml:"simulation"` + Exclusions []string `yaml:"exclusions,omitempty"` +} + // CrowdSec is the structure of the crowdsec configuration type CrowdSec struct { - WorkingFolder string `yaml:"working_dir,omitempty"` - DataFolder string `yaml:"data_dir,omitempty"` - ConfigFolder string `yaml:"config_dir,omitempty"` - AcquisitionFile string `yaml:"acquis_path,omitempty"` - SingleFile string //for forensic mode - SingleFileLabel string //for forensic mode - PIDFolder string `yaml:"pid_dir,omitempty"` - LogFolder string `yaml:"log_dir,omitempty"` - LogMode string `yaml:"log_mode,omitempty"` //like file, syslog or stdout ? - LogLevel log.Level `yaml:"log_level,omitempty"` //trace,debug,info,warning,error - Daemonize bool `yaml:"daemon,omitempty"` //true -> go background - Profiling bool `yaml:"profiling,omitempty"` //true -> enable runtime profiling - APIMode bool `yaml:"apimode,omitempty"` //true -> enable api push - CsCliFolder string `yaml:"cscli_dir"` //cscli folder - NbParsers int `yaml:"parser_routines"` //the number of go routines to start for parsing - Linter bool - Prometheus bool - HTTPListen string `yaml:"http_listen,omitempty"` - RestoreMode string - DumpBuckets bool - OutputConfig *outputs.OutputFactory `yaml:"plugin"` + WorkingFolder string `yaml:"working_dir,omitempty"` + DataFolder string `yaml:"data_dir,omitempty"` + ConfigFolder string `yaml:"config_dir,omitempty"` + AcquisitionFile string `yaml:"acquis_path,omitempty"` + SingleFile string //for forensic mode + SingleFileLabel string //for forensic mode + PIDFolder string `yaml:"pid_dir,omitempty"` + LogFolder string `yaml:"log_dir,omitempty"` + LogMode string `yaml:"log_mode,omitempty"` //like file, syslog or stdout ? + LogLevel log.Level `yaml:"log_level,omitempty"` //trace,debug,info,warning,error + Daemonize bool `yaml:"daemon,omitempty"` //true -> go background + Profiling bool `yaml:"profiling,omitempty"` //true -> enable runtime profiling + APIMode bool `yaml:"apimode,omitempty"` //true -> enable api push + CsCliFolder string `yaml:"cscli_dir"` //cscli folder + NbParsers int `yaml:"parser_routines"` //the number of go routines to start for parsing + SimulationCfgPath string `yaml:"simulation_path,omitempty"` + SimulationCfg *SimulationConfig + Linter bool + Prometheus bool + HTTPListen string `yaml:"http_listen,omitempty"` + RestoreMode string + DumpBuckets bool + OutputConfig *outputs.OutputFactory `yaml:"plugin"` } // NewCrowdSecConfig create a new crowdsec configuration with default configuration @@ -73,8 +80,18 @@ func (c *CrowdSec) GetCliConfig(configFile *string) error { c.AcquisitionFile = filepath.Clean(c.ConfigFolder + "/acquis.yaml") } } + if c.SimulationCfgPath != "" { + rcfg, err := ioutil.ReadFile(c.SimulationCfgPath) + if err != nil { + return fmt.Errorf("while reading '%s' : %s", c.SimulationCfgPath, err) + } + simCfg := SimulationConfig{} + if err := yaml.UnmarshalStrict(rcfg, &simCfg); err != nil { + return fmt.Errorf("while parsing '%s' : %s", c.SimulationCfgPath, err) + } + c.SimulationCfg = &simCfg + } return nil - } // GetOPT return flags parsed from command line @@ -111,18 +128,8 @@ func (c *CrowdSec) GetOPT() error { c.SingleFileLabel = *catFileType } - /*overriden by cfg file*/ - if *configFile != "" { - rcfg, err := ioutil.ReadFile(*configFile) - if err != nil { - return fmt.Errorf("read '%s' : %s", *configFile, err) - } - if err := yaml.UnmarshalStrict(rcfg, c); err != nil { - return fmt.Errorf("parse '%s' : %s", *configFile, err) - } - if c.AcquisitionFile == "" { - c.AcquisitionFile = filepath.Clean(c.ConfigFolder + "/acquis.yaml") - } + if err := c.GetCliConfig(configFile); err != nil { + log.Fatalf("Error while loading configuration : %s", err) } if *AcquisitionFile != "" { diff --git a/pkg/outputs/ouputs.go b/pkg/outputs/ouputs.go index e51cc289c..f0784943b 100644 --- a/pkg/outputs/ouputs.go +++ b/pkg/outputs/ouputs.go @@ -44,13 +44,16 @@ func OvflwToOrder(sig types.SignalOccurence, prof types.Profile) (*types.BanOrde var ordr types.BanOrder var warn error + if sig.Simulation { + ordr.MeasureType = "simulation:" + } //Identify remediation type if prof.Remediation.Ban { - ordr.MeasureType = "ban" + ordr.MeasureType += "ban" } else if prof.Remediation.Slow { - ordr.MeasureType = "slow" + ordr.MeasureType += "slow" } else if prof.Remediation.Captcha { - ordr.MeasureType = "captcha" + ordr.MeasureType += "captcha" } else { /*if the profil has no remediation, no order */ return nil, nil, fmt.Errorf("no remediation") diff --git a/pkg/types/signal_occurence.go b/pkg/types/signal_occurence.go index 91f0c467a..f7f259281 100644 --- a/pkg/types/signal_occurence.go +++ b/pkg/types/signal_occurence.go @@ -38,6 +38,7 @@ type SignalOccurence struct { Capacity int `json:"capacity,omitempty"` Leak_speed time.Duration `json:"leak_speed,omitempty"` Whitelisted bool `gorm:"-"` + Simulation bool `gorm:"-"` Reprocess bool //Reprocess, when true, will make the overflow being processed again as a fresh log would Labels map[string]string `gorm:"-"` }