diff --git a/cmd/crowdsec-cli/main.go b/cmd/crowdsec-cli/main.go index fda4cddc2bc6..03da8a9ca631 100644 --- a/cmd/crowdsec-cli/main.go +++ b/cmd/crowdsec-cli/main.go @@ -29,6 +29,8 @@ var mergedConfig string // flagBranch overrides the value in csConfig.Cscli.HubBranch var flagBranch = "" +type configGetter func() *csconfig.Config + func initConfig() { var err error @@ -195,7 +197,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall cmd.AddCommand(NewCLIDashboard().NewCommand()) cmd.AddCommand(NewCLIDecisions().NewCommand()) cmd.AddCommand(NewCLIAlerts().NewCommand()) - cmd.AddCommand(NewCLISimulation().NewCommand()) + cmd.AddCommand(NewCLISimulation(getconfig).NewCommand()) cmd.AddCommand(NewCLIBouncers(getconfig).NewCommand()) cmd.AddCommand(NewCLIMachines().NewCommand()) cmd.AddCommand(NewCLICapi().NewCommand()) diff --git a/cmd/crowdsec-cli/simulation.go b/cmd/crowdsec-cli/simulation.go index 99dac7c17f28..ceaf1fb4358f 100644 --- a/cmd/crowdsec-cli/simulation.go +++ b/cmd/crowdsec-cli/simulation.go @@ -13,13 +13,17 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/cwhub" ) -type cliSimulation struct{} +type cliSimulation struct{ + cfg configGetter +} -func NewCLISimulation() *cliSimulation { - return &cliSimulation{} +func NewCLISimulation(getconfig configGetter) *cliSimulation { + return &cliSimulation{ + cfg: getconfig, + } } -func (cli cliSimulation) NewCommand() *cobra.Command { +func (cli *cliSimulation) NewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "simulation [command]", Short: "Manage simulation status of scenarios", @@ -27,16 +31,16 @@ func (cli cliSimulation) NewCommand() *cobra.Command { cscli simulation enable crowdsecurity/ssh-bf cscli simulation disable crowdsecurity/ssh-bf`, DisableAutoGenTag: true, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(_ *cobra.Command, _ []string) error { if err := csConfig.LoadSimulation(); err != nil { - log.Fatal(err) + return err } if csConfig.Cscli.SimulationConfig == nil { return fmt.Errorf("no simulation configured") } return nil }, - PersistentPostRun: func(cmd *cobra.Command, args []string) { + PersistentPostRun: func(cmd *cobra.Command, _ []string) { if cmd.Name() != "status" { log.Infof(ReloadMessage()) } @@ -52,7 +56,7 @@ cscli simulation disable crowdsecurity/ssh-bf`, return cmd } -func (cli cliSimulation) NewEnableCmd() *cobra.Command { +func (cli *cliSimulation) NewEnableCmd() *cobra.Command { var forceGlobalSimulation bool cmd := &cobra.Command{ @@ -60,10 +64,10 @@ func (cli cliSimulation) NewEnableCmd() *cobra.Command { Short: "Enable the simulation, globally or on specified scenarios", Example: `cscli simulation enable`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { hub, err := require.Hub(csConfig, nil, nil) if err != nil { - log.Fatal(err) + return err } if len(args) > 0 { @@ -86,27 +90,25 @@ func (cli cliSimulation) NewEnableCmd() *cobra.Command { continue } if *csConfig.Cscli.SimulationConfig.Simulation && isExcluded { - if err := removeFromExclusion(scenario); err != nil { - log.Fatal(err) - } + cli.removeFromExclusion(scenario) log.Printf("simulation enabled for '%s'", scenario) continue } - if err := addToExclusion(scenario); err != nil { - log.Fatal(err) - } + cli.addToExclusion(scenario) log.Printf("simulation mode for '%s' enabled", scenario) } - if err := dumpSimulationFile(); err != nil { - log.Fatalf("simulation enable: %s", err) + if err := cli.dumpSimulationFile(); err != nil { + return fmt.Errorf("simulation enable: %s", err) } } else if forceGlobalSimulation { - if err := enableGlobalSimulation(); err != nil { - log.Fatalf("unable to enable global simulation mode : %s", err) + if err := cli.enableGlobalSimulation(); err != nil { + return fmt.Errorf("unable to enable global simulation mode: %s", err) } } else { printHelp(cmd) } + + return nil }, } cmd.Flags().BoolVarP(&forceGlobalSimulation, "global", "g", false, "Enable global simulation (reverse mode)") @@ -114,7 +116,7 @@ func (cli cliSimulation) NewEnableCmd() *cobra.Command { return cmd } -func (cli cliSimulation) NewDisableCmd() *cobra.Command { +func (cli *cliSimulation) NewDisableCmd() *cobra.Command { var forceGlobalSimulation bool cmd := &cobra.Command{ @@ -122,7 +124,7 @@ func (cli cliSimulation) NewDisableCmd() *cobra.Command { Short: "Disable the simulation mode. Disable only specified scenarios", Example: `cscli simulation disable`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { if len(args) > 0 { for _, scenario := range args { isExcluded := slices.Contains(csConfig.Cscli.SimulationConfig.Exclusions, scenario) @@ -131,9 +133,7 @@ func (cli cliSimulation) NewDisableCmd() *cobra.Command { continue } if !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded { - if err := removeFromExclusion(scenario); err != nil { - log.Fatal(err) - } + cli.removeFromExclusion(scenario) log.Printf("simulation mode for '%s' disabled", scenario) continue } @@ -141,21 +141,21 @@ func (cli cliSimulation) NewDisableCmd() *cobra.Command { log.Warningf("simulation mode is enabled but is already disable for '%s'", scenario) continue } - if err := addToExclusion(scenario); err != nil { - log.Fatal(err) - } + cli.addToExclusion(scenario) log.Printf("simulation mode for '%s' disabled", scenario) } - if err := dumpSimulationFile(); err != nil { - log.Fatalf("simulation disable: %s", err) + if err := cli.dumpSimulationFile(); err != nil { + return fmt.Errorf("simulation disable: %s", err) } } else if forceGlobalSimulation { - if err := disableGlobalSimulation(); err != nil { - log.Fatalf("unable to disable global simulation mode : %s", err) + if err := cli.disableGlobalSimulation(); err != nil { + return fmt.Errorf("unable to disable global simulation mode: %s", err) } } else { printHelp(cmd) } + + return nil }, } cmd.Flags().BoolVarP(&forceGlobalSimulation, "global", "g", false, "Disable global simulation (reverse mode)") @@ -163,16 +163,14 @@ func (cli cliSimulation) NewDisableCmd() *cobra.Command { return cmd } -func (cli cliSimulation) NewStatusCmd() *cobra.Command { +func (cli *cliSimulation) NewStatusCmd() *cobra.Command { cmd := &cobra.Command{ Use: "status", Short: "Show simulation mode status", Example: `cscli simulation status`, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { - if err := simulationStatus(); err != nil { - log.Fatal(err) - } + Run: func(_ *cobra.Command, _ []string) { + cli.status() }, PersistentPostRun: func(cmd *cobra.Command, args []string) { }, @@ -181,29 +179,26 @@ func (cli cliSimulation) NewStatusCmd() *cobra.Command { return cmd } -func addToExclusion(name string) error { +func (cli *cliSimulation) addToExclusion(name string) { csConfig.Cscli.SimulationConfig.Exclusions = append(csConfig.Cscli.SimulationConfig.Exclusions, name) - return nil } -func removeFromExclusion(name string) error { +func (cli *cliSimulation) removeFromExclusion(name string) { index := slices.Index(csConfig.Cscli.SimulationConfig.Exclusions, name) // Remove element from the slice csConfig.Cscli.SimulationConfig.Exclusions[index] = csConfig.Cscli.SimulationConfig.Exclusions[len(csConfig.Cscli.SimulationConfig.Exclusions)-1] csConfig.Cscli.SimulationConfig.Exclusions[len(csConfig.Cscli.SimulationConfig.Exclusions)-1] = "" csConfig.Cscli.SimulationConfig.Exclusions = csConfig.Cscli.SimulationConfig.Exclusions[:len(csConfig.Cscli.SimulationConfig.Exclusions)-1] - - return nil } -func enableGlobalSimulation() error { +func (cli *cliSimulation) enableGlobalSimulation() error { csConfig.Cscli.SimulationConfig.Simulation = new(bool) *csConfig.Cscli.SimulationConfig.Simulation = true csConfig.Cscli.SimulationConfig.Exclusions = []string{} - if err := dumpSimulationFile(); err != nil { - log.Fatalf("unable to dump simulation file: %s", err) + if err := cli.dumpSimulationFile(); err != nil { + return fmt.Errorf("unable to dump simulation file: %s", err) } log.Printf("global simulation: enabled") @@ -211,7 +206,7 @@ func enableGlobalSimulation() error { return nil } -func dumpSimulationFile() error { +func (cli *cliSimulation) dumpSimulationFile() error { newConfigSim, err := yaml.Marshal(csConfig.Cscli.SimulationConfig) if err != nil { return fmt.Errorf("unable to marshal simulation configuration: %s", err) @@ -225,7 +220,7 @@ func dumpSimulationFile() error { return nil } -func disableGlobalSimulation() error { +func (cli *cliSimulation) disableGlobalSimulation() error { csConfig.Cscli.SimulationConfig.Simulation = new(bool) *csConfig.Cscli.SimulationConfig.Simulation = false @@ -243,10 +238,10 @@ func disableGlobalSimulation() error { return nil } -func simulationStatus() error { +func (cli *cliSimulation) status() { if csConfig.Cscli.SimulationConfig == nil { log.Printf("global simulation: disabled (configuration file is missing)") - return nil + return } if *csConfig.Cscli.SimulationConfig.Simulation { log.Println("global simulation: enabled") @@ -265,5 +260,4 @@ func simulationStatus() error { } } } - return nil }