|
@@ -15,45 +15,88 @@ import (
|
|
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
|
"github.com/crowdsecurity/crowdsec/pkg/fflag"
|
|
)
|
|
)
|
|
|
|
|
|
-var trace_lvl, dbg_lvl, nfo_lvl, wrn_lvl, err_lvl bool
|
|
|
|
-
|
|
|
|
var ConfigFilePath string
|
|
var ConfigFilePath string
|
|
var csConfig *csconfig.Config
|
|
var csConfig *csconfig.Config
|
|
var dbClient *database.Client
|
|
var dbClient *database.Client
|
|
|
|
|
|
-var outputFormat string
|
|
|
|
-var OutputColor string
|
|
|
|
|
|
+type configGetter func() *csconfig.Config
|
|
|
|
|
|
var mergedConfig string
|
|
var mergedConfig string
|
|
|
|
|
|
-// flagBranch overrides the value in csConfig.Cscli.HubBranch
|
|
|
|
-var flagBranch = ""
|
|
|
|
|
|
+type cliRoot struct {
|
|
|
|
+ logTrace bool
|
|
|
|
+ logDebug bool
|
|
|
|
+ logInfo bool
|
|
|
|
+ logWarn bool
|
|
|
|
+ logErr bool
|
|
|
|
+ outputColor string
|
|
|
|
+ outputFormat string
|
|
|
|
+ // flagBranch overrides the value in csConfig.Cscli.HubBranch
|
|
|
|
+ flagBranch string
|
|
|
|
+}
|
|
|
|
|
|
-type configGetter func() *csconfig.Config
|
|
|
|
|
|
+func newCliRoot() *cliRoot {
|
|
|
|
+ return &cliRoot{}
|
|
|
|
+}
|
|
|
|
|
|
-func initConfig() {
|
|
|
|
- var err error
|
|
|
|
|
|
+// cfg() is a helper function to get the configuration loaded from config.yaml,
|
|
|
|
+// we pass it to subcommands because the file is not read until the Execute() call
|
|
|
|
+func (cli *cliRoot) cfg() *csconfig.Config {
|
|
|
|
+ return csConfig
|
|
|
|
+}
|
|
|
|
|
|
- if trace_lvl {
|
|
|
|
- log.SetLevel(log.TraceLevel)
|
|
|
|
- } else if dbg_lvl {
|
|
|
|
- log.SetLevel(log.DebugLevel)
|
|
|
|
- } else if nfo_lvl {
|
|
|
|
- log.SetLevel(log.InfoLevel)
|
|
|
|
- } else if wrn_lvl {
|
|
|
|
- log.SetLevel(log.WarnLevel)
|
|
|
|
- } else if err_lvl {
|
|
|
|
- log.SetLevel(log.ErrorLevel)
|
|
|
|
|
|
+// wantedLogLevel returns the log level requested in the command line flags.
|
|
|
|
+func (cli *cliRoot) wantedLogLevel() log.Level {
|
|
|
|
+ switch {
|
|
|
|
+ case cli.logTrace:
|
|
|
|
+ return log.TraceLevel
|
|
|
|
+ case cli.logDebug:
|
|
|
|
+ return log.DebugLevel
|
|
|
|
+ case cli.logInfo:
|
|
|
|
+ return log.InfoLevel
|
|
|
|
+ case cli.logWarn:
|
|
|
|
+ return log.WarnLevel
|
|
|
|
+ case cli.logErr:
|
|
|
|
+ return log.ErrorLevel
|
|
|
|
+ default:
|
|
|
|
+ return log.InfoLevel
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// loadConfigFor loads the configuration file for the given sub-command.
|
|
|
|
+// If the sub-command does not need it, it returns a default configuration.
|
|
|
|
+func loadConfigFor(command string) (*csconfig.Config, string, error) {
|
|
|
|
+ noNeedConfig := []string{
|
|
|
|
+ "doc",
|
|
|
|
+ "help",
|
|
|
|
+ "completion",
|
|
|
|
+ "version",
|
|
|
|
+ "hubtest",
|
|
}
|
|
}
|
|
|
|
|
|
- if !slices.Contains(NoNeedConfig, os.Args[1]) {
|
|
|
|
|
|
+ if !slices.Contains(noNeedConfig, command) {
|
|
log.Debugf("Using %s as configuration file", ConfigFilePath)
|
|
log.Debugf("Using %s as configuration file", ConfigFilePath)
|
|
- csConfig, mergedConfig, err = csconfig.NewConfig(ConfigFilePath, false, false, true)
|
|
|
|
|
|
+
|
|
|
|
+ config, merged, err := csconfig.NewConfig(ConfigFilePath, false, false, true)
|
|
if err != nil {
|
|
if err != nil {
|
|
- log.Fatal(err)
|
|
|
|
|
|
+ return nil, "", err
|
|
}
|
|
}
|
|
- } else {
|
|
|
|
- csConfig = csconfig.NewDefaultConfig()
|
|
|
|
|
|
+
|
|
|
|
+ return config, merged, nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return csconfig.NewDefaultConfig(), "", nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// initialize is called before the subcommand is executed.
|
|
|
|
+func (cli *cliRoot) initialize() {
|
|
|
|
+ var err error
|
|
|
|
+
|
|
|
|
+ log.SetLevel(cli.wantedLogLevel())
|
|
|
|
+
|
|
|
|
+ csConfig, mergedConfig, err = loadConfigFor(os.Args[1])
|
|
|
|
+ if err != nil {
|
|
|
|
+ log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
|
|
// recap of the enabled feature flags, because logging
|
|
// recap of the enabled feature flags, because logging
|
|
@@ -62,12 +105,12 @@ func initConfig() {
|
|
log.Debugf("Enabled feature flags: %s", fflist)
|
|
log.Debugf("Enabled feature flags: %s", fflist)
|
|
}
|
|
}
|
|
|
|
|
|
- if flagBranch != "" {
|
|
|
|
- csConfig.Cscli.HubBranch = flagBranch
|
|
|
|
|
|
+ if cli.flagBranch != "" {
|
|
|
|
+ csConfig.Cscli.HubBranch = cli.flagBranch
|
|
}
|
|
}
|
|
|
|
|
|
- if outputFormat != "" {
|
|
|
|
- csConfig.Cscli.Output = outputFormat
|
|
|
|
|
|
+ if cli.outputFormat != "" {
|
|
|
|
+ csConfig.Cscli.Output = cli.outputFormat
|
|
}
|
|
}
|
|
|
|
|
|
if csConfig.Cscli.Output == "" {
|
|
if csConfig.Cscli.Output == "" {
|
|
@@ -85,11 +128,11 @@ func initConfig() {
|
|
log.SetLevel(log.ErrorLevel)
|
|
log.SetLevel(log.ErrorLevel)
|
|
}
|
|
}
|
|
|
|
|
|
- if OutputColor != "" {
|
|
|
|
- csConfig.Cscli.Color = OutputColor
|
|
|
|
|
|
+ if cli.outputColor != "" {
|
|
|
|
+ csConfig.Cscli.Color = cli.outputColor
|
|
|
|
|
|
- if OutputColor != "yes" && OutputColor != "no" && OutputColor != "auto" {
|
|
|
|
- log.Fatalf("output color %s unknown", OutputColor)
|
|
|
|
|
|
+ if cli.outputColor != "yes" && cli.outputColor != "no" && cli.outputColor != "auto" {
|
|
|
|
+ log.Fatalf("output color %s unknown", cli.outputColor)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -102,15 +145,25 @@ var validArgs = []string{
|
|
"postoverflows", "scenarios", "simulation", "support", "version",
|
|
"postoverflows", "scenarios", "simulation", "support", "version",
|
|
}
|
|
}
|
|
|
|
|
|
-var NoNeedConfig = []string{
|
|
|
|
- "doc",
|
|
|
|
- "help",
|
|
|
|
- "completion",
|
|
|
|
- "version",
|
|
|
|
- "hubtest",
|
|
|
|
|
|
+func (cli *cliRoot) colorize(cmd *cobra.Command) {
|
|
|
|
+ cc.Init(&cc.Config{
|
|
|
|
+ RootCmd: cmd,
|
|
|
|
+ Headings: cc.Yellow,
|
|
|
|
+ Commands: cc.Green + cc.Bold,
|
|
|
|
+ CmdShortDescr: cc.Cyan,
|
|
|
|
+ Example: cc.Italic,
|
|
|
|
+ ExecName: cc.Bold,
|
|
|
|
+ Aliases: cc.Bold + cc.Italic,
|
|
|
|
+ FlagsDataType: cc.White,
|
|
|
|
+ Flags: cc.Green,
|
|
|
|
+ FlagsDescr: cc.Cyan,
|
|
|
|
+ NoExtraNewlines: true,
|
|
|
|
+ NoBottomNewline: true,
|
|
|
|
+ })
|
|
|
|
+ cmd.SetOut(color.Output)
|
|
}
|
|
}
|
|
|
|
|
|
-func main() {
|
|
|
|
|
|
+func (cli *cliRoot) NewCommand() *cobra.Command {
|
|
// set the formatter asap and worry about level later
|
|
// set the formatter asap and worry about level later
|
|
logFormatter := &log.TextFormatter{TimestampFormat: time.RFC3339, FullTimestamp: true}
|
|
logFormatter := &log.TextFormatter{TimestampFormat: time.RFC3339, FullTimestamp: true}
|
|
log.SetFormatter(logFormatter)
|
|
log.SetFormatter(logFormatter)
|
|
@@ -135,33 +188,25 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|
/*TBD examples*/
|
|
/*TBD examples*/
|
|
}
|
|
}
|
|
|
|
|
|
- cc.Init(&cc.Config{
|
|
|
|
- RootCmd: cmd,
|
|
|
|
- Headings: cc.Yellow,
|
|
|
|
- Commands: cc.Green + cc.Bold,
|
|
|
|
- CmdShortDescr: cc.Cyan,
|
|
|
|
- Example: cc.Italic,
|
|
|
|
- ExecName: cc.Bold,
|
|
|
|
- Aliases: cc.Bold + cc.Italic,
|
|
|
|
- FlagsDataType: cc.White,
|
|
|
|
- Flags: cc.Green,
|
|
|
|
- FlagsDescr: cc.Cyan,
|
|
|
|
- NoExtraNewlines: true,
|
|
|
|
- NoBottomNewline: true,
|
|
|
|
- })
|
|
|
|
- cmd.SetOut(color.Output)
|
|
|
|
|
|
+ cli.colorize(cmd)
|
|
|
|
+
|
|
|
|
+ /*don't sort flags so we can enforce order*/
|
|
|
|
+ cmd.Flags().SortFlags = false
|
|
|
|
+
|
|
|
|
+ pflags := cmd.PersistentFlags()
|
|
|
|
+ pflags.SortFlags = false
|
|
|
|
+
|
|
|
|
+ pflags.StringVarP(&ConfigFilePath, "config", "c", csconfig.DefaultConfigPath("config.yaml"), "path to crowdsec config file")
|
|
|
|
+ pflags.StringVarP(&cli.outputFormat, "output", "o", "", "Output format: human, json, raw")
|
|
|
|
+ pflags.StringVarP(&cli.outputColor, "color", "", "auto", "Output color: yes, no, auto")
|
|
|
|
+ pflags.BoolVar(&cli.logDebug, "debug", false, "Set logging to debug")
|
|
|
|
+ pflags.BoolVar(&cli.logInfo, "info", false, "Set logging to info")
|
|
|
|
+ pflags.BoolVar(&cli.logWarn, "warning", false, "Set logging to warning")
|
|
|
|
+ pflags.BoolVar(&cli.logErr, "error", false, "Set logging to error")
|
|
|
|
+ pflags.BoolVar(&cli.logTrace, "trace", false, "Set logging to trace")
|
|
|
|
+ pflags.StringVar(&cli.flagBranch, "branch", "", "Override hub branch on github")
|
|
|
|
|
|
- cmd.PersistentFlags().StringVarP(&ConfigFilePath, "config", "c", csconfig.DefaultConfigPath("config.yaml"), "path to crowdsec config file")
|
|
|
|
- cmd.PersistentFlags().StringVarP(&outputFormat, "output", "o", "", "Output format: human, json, raw")
|
|
|
|
- cmd.PersistentFlags().StringVarP(&OutputColor, "color", "", "auto", "Output color: yes, no, auto")
|
|
|
|
- cmd.PersistentFlags().BoolVar(&dbg_lvl, "debug", false, "Set logging to debug")
|
|
|
|
- cmd.PersistentFlags().BoolVar(&nfo_lvl, "info", false, "Set logging to info")
|
|
|
|
- cmd.PersistentFlags().BoolVar(&wrn_lvl, "warning", false, "Set logging to warning")
|
|
|
|
- cmd.PersistentFlags().BoolVar(&err_lvl, "error", false, "Set logging to error")
|
|
|
|
- cmd.PersistentFlags().BoolVar(&trace_lvl, "trace", false, "Set logging to trace")
|
|
|
|
- cmd.PersistentFlags().StringVar(&flagBranch, "branch", "", "Override hub branch on github")
|
|
|
|
-
|
|
|
|
- if err := cmd.PersistentFlags().MarkHidden("branch"); err != nil {
|
|
|
|
|
|
+ if err := pflags.MarkHidden("branch"); err != nil {
|
|
log.Fatalf("failed to hide flag: %s", err)
|
|
log.Fatalf("failed to hide flag: %s", err)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -181,29 +226,20 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|
}
|
|
}
|
|
|
|
|
|
if len(os.Args) > 1 {
|
|
if len(os.Args) > 1 {
|
|
- cobra.OnInitialize(initConfig)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /*don't sort flags so we can enforce order*/
|
|
|
|
- cmd.Flags().SortFlags = false
|
|
|
|
- cmd.PersistentFlags().SortFlags = false
|
|
|
|
-
|
|
|
|
- // we use a getter because the config is not initialized until the Execute() call
|
|
|
|
- getconfig := func() *csconfig.Config {
|
|
|
|
- return csConfig
|
|
|
|
|
|
+ cobra.OnInitialize(cli.initialize)
|
|
}
|
|
}
|
|
|
|
|
|
cmd.AddCommand(NewCLIDoc().NewCommand(cmd))
|
|
cmd.AddCommand(NewCLIDoc().NewCommand(cmd))
|
|
cmd.AddCommand(NewCLIVersion().NewCommand())
|
|
cmd.AddCommand(NewCLIVersion().NewCommand())
|
|
cmd.AddCommand(NewConfigCmd())
|
|
cmd.AddCommand(NewConfigCmd())
|
|
- cmd.AddCommand(NewCLIHub(getconfig).NewCommand())
|
|
|
|
- cmd.AddCommand(NewCLIMetrics(getconfig).NewCommand())
|
|
|
|
- cmd.AddCommand(NewCLIDashboard(getconfig).NewCommand())
|
|
|
|
- cmd.AddCommand(NewCLIDecisions(getconfig).NewCommand())
|
|
|
|
|
|
+ cmd.AddCommand(NewCLIHub(cli.cfg).NewCommand())
|
|
|
|
+ cmd.AddCommand(NewCLIMetrics(cli.cfg).NewCommand())
|
|
|
|
+ cmd.AddCommand(NewCLIDashboard(cli.cfg).NewCommand())
|
|
|
|
+ cmd.AddCommand(NewCLIDecisions(cli.cfg).NewCommand())
|
|
cmd.AddCommand(NewCLIAlerts().NewCommand())
|
|
cmd.AddCommand(NewCLIAlerts().NewCommand())
|
|
- cmd.AddCommand(NewCLISimulation(getconfig).NewCommand())
|
|
|
|
- cmd.AddCommand(NewCLIBouncers(getconfig).NewCommand())
|
|
|
|
- cmd.AddCommand(NewCLIMachines(getconfig).NewCommand())
|
|
|
|
|
|
+ cmd.AddCommand(NewCLISimulation(cli.cfg).NewCommand())
|
|
|
|
+ cmd.AddCommand(NewCLIBouncers(cli.cfg).NewCommand())
|
|
|
|
+ cmd.AddCommand(NewCLIMachines(cli.cfg).NewCommand())
|
|
cmd.AddCommand(NewCLICapi().NewCommand())
|
|
cmd.AddCommand(NewCLICapi().NewCommand())
|
|
cmd.AddCommand(NewLapiCmd())
|
|
cmd.AddCommand(NewLapiCmd())
|
|
cmd.AddCommand(NewCompletionCmd())
|
|
cmd.AddCommand(NewCompletionCmd())
|
|
@@ -212,7 +248,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|
cmd.AddCommand(NewCLIHubTest().NewCommand())
|
|
cmd.AddCommand(NewCLIHubTest().NewCommand())
|
|
cmd.AddCommand(NewCLINotifications().NewCommand())
|
|
cmd.AddCommand(NewCLINotifications().NewCommand())
|
|
cmd.AddCommand(NewCLISupport().NewCommand())
|
|
cmd.AddCommand(NewCLISupport().NewCommand())
|
|
- cmd.AddCommand(NewCLIPapi(getconfig).NewCommand())
|
|
|
|
|
|
+ cmd.AddCommand(NewCLIPapi(cli.cfg).NewCommand())
|
|
cmd.AddCommand(NewCLICollection().NewCommand())
|
|
cmd.AddCommand(NewCLICollection().NewCommand())
|
|
cmd.AddCommand(NewCLIParser().NewCommand())
|
|
cmd.AddCommand(NewCLIParser().NewCommand())
|
|
cmd.AddCommand(NewCLIScenario().NewCommand())
|
|
cmd.AddCommand(NewCLIScenario().NewCommand())
|
|
@@ -225,6 +261,11 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|
cmd.AddCommand(NewSetupCmd())
|
|
cmd.AddCommand(NewSetupCmd())
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ return cmd
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func main() {
|
|
|
|
+ cmd := newCliRoot().NewCommand()
|
|
if err := cmd.Execute(); err != nil {
|
|
if err := cmd.Execute(); err != nil {
|
|
log.Fatal(err)
|
|
log.Fatal(err)
|
|
}
|
|
}
|