From 4160bb8102a07f7ea4d96098821f42951280dd22 Mon Sep 17 00:00:00 2001 From: mmetc <92726601+mmetc@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:36:21 +0100 Subject: [PATCH] refact "cscli decisions" (#2804) * refact "cscli decisions" * CI: relax mysql test timing * lint --- cmd/crowdsec-cli/dashboard.go | 3 +- cmd/crowdsec-cli/decisions.go | 59 ++++++++++++++++------------ cmd/crowdsec-cli/decisions_import.go | 4 +- cmd/crowdsec-cli/decisions_table.go | 6 ++- cmd/crowdsec-cli/flag.go | 1 + cmd/crowdsec-cli/machines.go | 16 ++++++-- cmd/crowdsec-cli/main.go | 4 +- cmd/crowdsec-cli/papi.go | 6 +-- cmd/crowdsec-cli/simulation.go | 11 +++++- cmd/crowdsec-cli/support.go | 34 ++++++++++++---- cmd/crowdsec-cli/utils.go | 4 +- pkg/csconfig/api.go | 3 +- pkg/csconfig/config.go | 4 +- test/bats/97_ipv6_single.bats | 2 +- 14 files changed, 106 insertions(+), 51 deletions(-) diff --git a/cmd/crowdsec-cli/dashboard.go b/cmd/crowdsec-cli/dashboard.go index f32b9f061..64cb7577e 100644 --- a/cmd/crowdsec-cli/dashboard.go +++ b/cmd/crowdsec-cli/dashboard.go @@ -176,7 +176,7 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password flags.StringVar(&metabaseImage, "metabase-image", metabaseImage, "Metabase image to use") flags.StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container") flags.BoolVarP(&forceYes, "yes", "y", false, "force yes") - //flags.StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user") + // flags.StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user") flags.StringVar(&metabasePassword, "password", "", "metabase password") return cmd @@ -443,6 +443,7 @@ func checkGroups(forceYes *bool) (*user.Group, error) { func (cli *cliDashboard) chownDatabase(gid string) error { cfg := cli.cfg() intID, err := strconv.Atoi(gid) + if err != nil { return fmt.Errorf("unable to convert group ID to int: %s", err) } diff --git a/cmd/crowdsec-cli/decisions.go b/cmd/crowdsec-cli/decisions.go index 683f100d4..c5839ae00 100644 --- a/cmd/crowdsec-cli/decisions.go +++ b/cmd/crowdsec-cli/decisions.go @@ -25,7 +25,7 @@ import ( var Client *apiclient.ApiClient -func DecisionsToTable(alerts *models.GetAlertsResponse, printMachine bool) error { +func (cli *cliDecisions) decisionsToTable(alerts *models.GetAlertsResponse, printMachine bool) error { /*here we cheat a bit : to make it more readable for the user, we dedup some entries*/ spamLimit := make(map[string]bool) skipped := 0 @@ -49,7 +49,8 @@ func DecisionsToTable(alerts *models.GetAlertsResponse, printMachine bool) error alertItem.Decisions = newDecisions } - if csConfig.Cscli.Output == "raw" { + switch cli.cfg().Cscli.Output { + case "raw": csvwriter := csv.NewWriter(os.Stdout) header := []string{"id", "source", "ip", "reason", "action", "country", "as", "events_count", "expiration", "simulated", "alert_id"} @@ -89,21 +90,24 @@ func DecisionsToTable(alerts *models.GetAlertsResponse, printMachine bool) error } csvwriter.Flush() - } else if csConfig.Cscli.Output == "json" { + case "json": if *alerts == nil { // avoid returning "null" in `json" // could be cleaner if we used slice of alerts directly fmt.Println("[]") return nil } + x, _ := json.MarshalIndent(alerts, "", " ") fmt.Printf("%s", string(x)) - } else if csConfig.Cscli.Output == "human" { + case "human": if len(*alerts) == 0 { fmt.Println("No active decisions") return nil } - decisionsTable(color.Output, alerts, printMachine) + + cli.decisionsTable(color.Output, alerts, printMachine) + if skipped > 0 { fmt.Printf("%d duplicated entries skipped\n", skipped) } @@ -113,13 +117,17 @@ func DecisionsToTable(alerts *models.GetAlertsResponse, printMachine bool) error } -type cliDecisions struct {} - -func NewCLIDecisions() *cliDecisions { - return &cliDecisions{} +type cliDecisions struct { + cfg configGetter } -func (cli cliDecisions) NewCommand() *cobra.Command { +func NewCLIDecisions(getconfig configGetter) *cliDecisions { + return &cliDecisions{ + cfg: getconfig, + } +} + +func (cli *cliDecisions) NewCommand() *cobra.Command { cmd := &cobra.Command{ Use: "decisions [action]", Short: "Manage decisions", @@ -130,16 +138,17 @@ func (cli cliDecisions) NewCommand() *cobra.Command { Args: cobra.MinimumNArgs(1), DisableAutoGenTag: true, PersistentPreRunE: func(_ *cobra.Command, _ []string) error { - if err := csConfig.LoadAPIClient(); err != nil { + cfg := cli.cfg() + if err := cfg.LoadAPIClient(); err != nil { return fmt.Errorf("loading api client: %w", err) } - password := strfmt.Password(csConfig.API.Client.Credentials.Password) - apiurl, err := url.Parse(csConfig.API.Client.Credentials.URL) + password := strfmt.Password(cfg.API.Client.Credentials.Password) + apiurl, err := url.Parse(cfg.API.Client.Credentials.URL) if err != nil { - return fmt.Errorf("parsing api url %s: %w", csConfig.API.Client.Credentials.URL, err) + return fmt.Errorf("parsing api url %s: %w", cfg.API.Client.Credentials.URL, err) } Client, err = apiclient.NewClient(&apiclient.Config{ - MachineID: csConfig.API.Client.Credentials.Login, + MachineID: cfg.API.Client.Credentials.Login, Password: password, UserAgent: fmt.Sprintf("crowdsec/%s", version.String()), URL: apiurl, @@ -152,15 +161,15 @@ func (cli cliDecisions) NewCommand() *cobra.Command { }, } - cmd.AddCommand(cli.NewListCmd()) - cmd.AddCommand(cli.NewAddCmd()) - cmd.AddCommand(cli.NewDeleteCmd()) - cmd.AddCommand(cli.NewImportCmd()) + cmd.AddCommand(cli.newListCmd()) + cmd.AddCommand(cli.newAddCmd()) + cmd.AddCommand(cli.newDeleteCmd()) + cmd.AddCommand(cli.newImportCmd()) return cmd } -func (cli cliDecisions) NewListCmd() *cobra.Command { +func (cli *cliDecisions) newListCmd() *cobra.Command { var filter = apiclient.AlertsListOpts{ ValueEquals: new(string), ScopeEquals: new(string), @@ -262,7 +271,7 @@ cscli decisions list -t ban return fmt.Errorf("unable to retrieve decisions: %w", err) } - err = DecisionsToTable(alerts, printMachine) + err = cli.decisionsToTable(alerts, printMachine) if err != nil { return fmt.Errorf("unable to print decisions: %w", err) } @@ -289,7 +298,7 @@ cscli decisions list -t ban return cmd } -func (cli cliDecisions) NewAddCmd() *cobra.Command { +func (cli *cliDecisions) newAddCmd() *cobra.Command { var ( addIP string addRange string @@ -325,7 +334,7 @@ cscli decisions add --scope username --value foobar createdAt := time.Now().UTC().Format(time.RFC3339) /*take care of shorthand options*/ - if err := manageCliDecisionAlerts(&addIP, &addRange, &addScope, &addValue); err != nil { + if err = manageCliDecisionAlerts(&addIP, &addRange, &addScope, &addValue); err != nil { return err } @@ -341,7 +350,7 @@ cscli decisions add --scope username --value foobar } if addReason == "" { - addReason = fmt.Sprintf("manual '%s' from '%s'", addType, csConfig.API.Client.Credentials.Login) + addReason = fmt.Sprintf("manual '%s' from '%s'", addType, cli.cfg().API.Client.Credentials.Login) } decision := models.Decision{ Duration: &addDuration, @@ -400,7 +409,7 @@ cscli decisions add --scope username --value foobar return cmd } -func (cli cliDecisions) NewDeleteCmd() *cobra.Command { +func (cli *cliDecisions) newDeleteCmd() *cobra.Command { var delFilter = apiclient.DecisionsDeleteOpts{ ScopeEquals: new(string), ValueEquals: new(string), diff --git a/cmd/crowdsec-cli/decisions_import.go b/cmd/crowdsec-cli/decisions_import.go index 2d7ee485b..45d1841a6 100644 --- a/cmd/crowdsec-cli/decisions_import.go +++ b/cmd/crowdsec-cli/decisions_import.go @@ -67,7 +67,7 @@ func parseDecisionList(content []byte, format string) ([]decisionRaw, error) { } -func (cli cliDecisions) runImport(cmd *cobra.Command, args []string) error { +func (cli *cliDecisions) runImport(cmd *cobra.Command, args []string) error { flags := cmd.Flags() input, err := flags.GetString("input") @@ -236,7 +236,7 @@ func (cli cliDecisions) runImport(cmd *cobra.Command, args []string) error { } -func (cli cliDecisions) NewImportCmd() *cobra.Command { +func (cli *cliDecisions) newImportCmd() *cobra.Command { cmd := &cobra.Command{ Use: "import [options]", Short: "Import decisions from a file or pipe", diff --git a/cmd/crowdsec-cli/decisions_table.go b/cmd/crowdsec-cli/decisions_table.go index d8d5e0325..10021e4dd 100644 --- a/cmd/crowdsec-cli/decisions_table.go +++ b/cmd/crowdsec-cli/decisions_table.go @@ -8,13 +8,15 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/models" ) -func decisionsTable(out io.Writer, alerts *models.GetAlertsResponse, printMachine bool) { +func (cli *cliDecisions) decisionsTable(out io.Writer, alerts *models.GetAlertsResponse, printMachine bool) { t := newTable(out) t.SetRowLines(false) + header := []string{"ID", "Source", "Scope:Value", "Reason", "Action", "Country", "AS", "Events", "expiration", "Alert ID"} if printMachine { header = append(header, "Machine") } + t.SetHeaders(header...) for _, alertItem := range *alerts { @@ -22,6 +24,7 @@ func decisionsTable(out io.Writer, alerts *models.GetAlertsResponse, printMachin if *alertItem.Simulated { *decisionItem.Type = fmt.Sprintf("(simul)%s", *decisionItem.Type) } + row := []string{ strconv.Itoa(int(decisionItem.ID)), *decisionItem.Origin, @@ -42,5 +45,6 @@ func decisionsTable(out io.Writer, alerts *models.GetAlertsResponse, printMachin t.AddRow(row...) } } + t.Render() } diff --git a/cmd/crowdsec-cli/flag.go b/cmd/crowdsec-cli/flag.go index 402302a1f..e85f33d44 100644 --- a/cmd/crowdsec-cli/flag.go +++ b/cmd/crowdsec-cli/flag.go @@ -18,6 +18,7 @@ func (p *MachinePassword) Set(v string) error { if len(v) > 72 { return errors.New("password too long (max 72 characters)") } + *p = MachinePassword(v) return nil diff --git a/cmd/crowdsec-cli/machines.go b/cmd/crowdsec-cli/machines.go index 0cabccf76..1819bdcf5 100644 --- a/cmd/crowdsec-cli/machines.go +++ b/cmd/crowdsec-cli/machines.go @@ -45,6 +45,7 @@ func generatePassword(length int) string { if err != nil { log.Fatalf("failed getting data from prng for password generation : %s", err) } + buf[i] = charset[rInt.Int64()] } @@ -59,12 +60,14 @@ func generateIDPrefix() (string, error) { if err == nil { return prefix, nil } + log.Debugf("failed to get machine-id with usual files: %s", err) bID, err := uuid.NewRandom() if err == nil { return bID.String(), nil } + return "", fmt.Errorf("generating machine id: %w", err) } @@ -75,11 +78,14 @@ func generateID(prefix string) (string, error) { if prefix == "" { prefix, err = generateIDPrefix() } + if err != nil { return "", err } + prefix = strings.ReplaceAll(prefix, "-", "")[:32] suffix := generatePassword(16) + return prefix + suffix, nil } @@ -289,6 +295,7 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri if !autoAdd { return fmt.Errorf("please specify a password with --password or use --auto") } + machinePassword = generatePassword(passwordLength) } else if machinePassword == "" && interactive { qs := &survey.Password{ @@ -328,10 +335,10 @@ func (cli *cliMachines) add(args []string, machinePassword string, dumpFile stri } if dumpFile != "" && dumpFile != "-" { - err = os.WriteFile(dumpFile, apiConfigDump, 0o600) - if err != nil { + if err = os.WriteFile(dumpFile, apiConfigDump, 0o600); err != nil { return fmt.Errorf("write api credentials in '%s' failed: %s", dumpFile, err) } + fmt.Fprintf(os.Stderr, "API credentials written to '%s'.\n", dumpFile) } else { fmt.Print(string(apiConfigDump)) @@ -359,11 +366,11 @@ func (cli *cliMachines) deleteValid(cmd *cobra.Command, args []string, toComplet func (cli *cliMachines) delete(machines []string) error { for _, machineID := range machines { - err := cli.db.DeleteWatcher(machineID) - if err != nil { + if err := cli.db.DeleteWatcher(machineID); err != nil { log.Errorf("unable to delete machine '%s': %s", machineID, err) return nil } + log.Infof("machine '%s' deleted successfully", machineID) } @@ -473,6 +480,7 @@ func (cli *cliMachines) validate(machineID string) error { if err := cli.db.ValidateMachine(machineID); err != nil { return fmt.Errorf("unable to validate machine '%s': %s", machineID, err) } + log.Infof("machine '%s' validated successfully", machineID) return nil diff --git a/cmd/crowdsec-cli/main.go b/cmd/crowdsec-cli/main.go index 055c38e27..1a7c84e3c 100644 --- a/cmd/crowdsec-cli/main.go +++ b/cmd/crowdsec-cli/main.go @@ -157,8 +157,8 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall 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 { log.Fatalf("failed to hide flag: %s", err) } @@ -197,7 +197,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall cmd.AddCommand(NewCLIHub(getconfig).NewCommand()) cmd.AddCommand(NewMetricsCmd()) cmd.AddCommand(NewCLIDashboard(getconfig).NewCommand()) - cmd.AddCommand(NewCLIDecisions().NewCommand()) + cmd.AddCommand(NewCLIDecisions(getconfig).NewCommand()) cmd.AddCommand(NewCLIAlerts().NewCommand()) cmd.AddCommand(NewCLISimulation(getconfig).NewCommand()) cmd.AddCommand(NewCLIBouncers(getconfig).NewCommand()) diff --git a/cmd/crowdsec-cli/papi.go b/cmd/crowdsec-cli/papi.go index 43dcc30e0..04223ef93 100644 --- a/cmd/crowdsec-cli/papi.go +++ b/cmd/crowdsec-cli/papi.go @@ -32,7 +32,7 @@ func (cli *cliPapi) NewCommand() *cobra.Command { Short: "Manage interaction with Polling API (PAPI)", Args: cobra.MinimumNArgs(1), DisableAutoGenTag: true, - PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + PersistentPreRunE: func(_ *cobra.Command, _ []string) error { cfg := cli.cfg() if err := require.LAPI(cfg); err != nil { return err @@ -59,7 +59,7 @@ func (cli *cliPapi) NewStatusCmd() *cobra.Command { Short: "Get status of the Polling API", Args: cobra.MinimumNArgs(0), DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { var err error cfg := cli.cfg() dbClient, err = database.NewClient(cfg.DbConfig) @@ -111,7 +111,7 @@ func (cli *cliPapi) NewSyncCmd() *cobra.Command { Short: "Sync with the Polling API, pulling all non-expired orders for the instance", Args: cobra.MinimumNArgs(0), DisableAutoGenTag: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { var err error cfg := cli.cfg() t := tomb.Tomb{} diff --git a/cmd/crowdsec-cli/simulation.go b/cmd/crowdsec-cli/simulation.go index 19eb1b99d..a6e710c57 100644 --- a/cmd/crowdsec-cli/simulation.go +++ b/cmd/crowdsec-cli/simulation.go @@ -211,14 +211,17 @@ func (cli *cliSimulation) enableGlobalSimulation() error { func (cli *cliSimulation) dumpSimulationFile() error { cfg := cli.cfg() + newConfigSim, err := yaml.Marshal(cfg.Cscli.SimulationConfig) if err != nil { return fmt.Errorf("unable to marshal simulation configuration: %s", err) } + err = os.WriteFile(cfg.ConfigPaths.SimulationFilePath, newConfigSim, 0o644) if err != nil { return fmt.Errorf("write simulation config in '%s' failed: %s", cfg.ConfigPaths.SimulationFilePath, err) } + log.Debugf("updated simulation file %s", cfg.ConfigPaths.SimulationFilePath) return nil @@ -230,16 +233,19 @@ func (cli *cliSimulation) disableGlobalSimulation() error { *cfg.Cscli.SimulationConfig.Simulation = false cfg.Cscli.SimulationConfig.Exclusions = []string{} + newConfigSim, err := yaml.Marshal(cfg.Cscli.SimulationConfig) if err != nil { return fmt.Errorf("unable to marshal new simulation configuration: %s", err) } + err = os.WriteFile(cfg.ConfigPaths.SimulationFilePath, newConfigSim, 0o644) if err != nil { - return fmt.Errorf("unable to write new simulation config in '%s' : %s", cfg.ConfigPaths.SimulationFilePath, err) + return fmt.Errorf("unable to write new simulation config in '%s': %s", cfg.ConfigPaths.SimulationFilePath, err) } log.Printf("global simulation: disabled") + return nil } @@ -249,10 +255,13 @@ func (cli *cliSimulation) status() { log.Printf("global simulation: disabled (configuration file is missing)") return } + if *cfg.Cscli.SimulationConfig.Simulation { log.Println("global simulation: enabled") + if len(cfg.Cscli.SimulationConfig.Exclusions) > 0 { log.Println("Scenarios not in simulation mode :") + for _, scenario := range cfg.Cscli.SimulationConfig.Exclusions { log.Printf(" - %s", scenario) } diff --git a/cmd/crowdsec-cli/support.go b/cmd/crowdsec-cli/support.go index ed7f7cf2f..6ddfa3056 100644 --- a/cmd/crowdsec-cli/support.go +++ b/cmd/crowdsec-cli/support.go @@ -76,9 +76,10 @@ func collectMetrics() ([]byte, []byte, error) { if err != nil { return nil, nil, fmt.Errorf("could not create requests to prometheus endpoint: %s", err) } - client := &http.Client{} - resp, err := client.Do(req) + client := &http.Client{} + + resp, err := client.Do(req) if err != nil { return nil, nil, fmt.Errorf("could not get metrics from prometheus endpoint: %s", err) } @@ -100,17 +101,20 @@ func collectVersion() []byte { func collectFeatures() []byte { log.Info("Collecting feature flags") + enabledFeatures := fflag.Crowdsec.GetEnabledFeatures() w := bytes.NewBuffer(nil) for _, k := range enabledFeatures { fmt.Fprintf(w, "%s\n", k) } + return w.Bytes() } func collectOSInfo() ([]byte, error) { log.Info("Collecting OS info") + info, err := osinfo.GetOSInfo() if err != nil { @@ -133,6 +137,7 @@ func collectHubItems(hub *cwhub.Hub, itemType string) []byte { var err error out := bytes.NewBuffer(nil) + log.Infof("Collecting %s list", itemType) items := make(map[string][]*cwhub.Item) @@ -144,26 +149,33 @@ func collectHubItems(hub *cwhub.Hub, itemType string) []byte { if err := listItems(out, []string{itemType}, items, false); err != nil { log.Warnf("could not collect %s list: %s", itemType, err) } + return out.Bytes() } func collectBouncers(dbClient *database.Client) ([]byte, error) { out := bytes.NewBuffer(nil) + bouncers, err := dbClient.ListBouncers() if err != nil { return nil, fmt.Errorf("unable to list bouncers: %s", err) } + getBouncersTable(out, bouncers) + return out.Bytes(), nil } func collectAgents(dbClient *database.Client) ([]byte, error) { out := bytes.NewBuffer(nil) + machines, err := dbClient.ListMachines() if err != nil { return nil, fmt.Errorf("unable to list machines: %s", err) } + getAgentsTable(out, machines) + return out.Bytes(), nil } @@ -171,12 +183,14 @@ func collectAPIStatus(login string, password string, endpoint string, prefix str if csConfig.API.Client == nil || csConfig.API.Client.Credentials == nil { return []byte("No agent credentials found, are we LAPI ?") } - pwd := strfmt.Password(password) - apiurl, err := url.Parse(endpoint) + pwd := strfmt.Password(password) + + apiurl, err := url.Parse(endpoint) if err != nil { return []byte(fmt.Sprintf("cannot parse API URL: %s", err)) } + scenarios, err := hub.GetInstalledItemNames(cwhub.SCENARIOS) if err != nil { return []byte(fmt.Sprintf("could not collect scenarios: %s", err)) @@ -189,6 +203,7 @@ func collectAPIStatus(login string, password string, endpoint string, prefix str if err != nil { return []byte(fmt.Sprintf("could not init client: %s", err)) } + t := models.WatcherAuthRequest{ MachineID: &login, Password: &pwd, @@ -205,6 +220,7 @@ func collectAPIStatus(login string, password string, endpoint string, prefix str func collectCrowdsecConfig() []byte { log.Info("Collecting crowdsec config") + config, err := os.ReadFile(*csConfig.FilePath) if err != nil { return []byte(fmt.Sprintf("could not read config file: %s", err)) @@ -217,15 +233,18 @@ func collectCrowdsecConfig() []byte { func collectCrowdsecProfile() []byte { log.Info("Collecting crowdsec profile") + config, err := os.ReadFile(csConfig.API.Server.ProfilesPath) if err != nil { return []byte(fmt.Sprintf("could not read profile file: %s", err)) } + return config } func collectAcquisitionConfig() map[string][]byte { log.Info("Collecting acquisition config") + ret := make(map[string][]byte) for _, filename := range csConfig.Crowdsec.AcquisitionFiles { @@ -287,7 +306,7 @@ cscli support dump -f /tmp/crowdsec-support.zip `, Args: cobra.NoArgs, DisableAutoGenTag: true, - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { var err error var skipHub, skipDB, skipCAPI, skipLAPI, skipAgent bool infos := map[string][]byte{ @@ -307,13 +326,13 @@ cscli support dump -f /tmp/crowdsec-support.zip infos[SUPPORT_AGENTS_PATH] = []byte(err.Error()) } - if err := csConfig.LoadAPIServer(true); err != nil { + if err = csConfig.LoadAPIServer(true); err != nil { log.Warnf("could not load LAPI, skipping CAPI check") skipLAPI = true infos[SUPPORT_CAPI_STATUS_PATH] = []byte(err.Error()) } - if err := csConfig.LoadCrowdsec(); err != nil { + if err = csConfig.LoadCrowdsec(); err != nil { log.Warnf("could not load agent config, skipping crowdsec config check") skipAgent = true } @@ -399,7 +418,6 @@ cscli support dump -f /tmp/crowdsec-support.zip } if !skipAgent { - acquis := collectAcquisitionConfig() for filename, content := range acquis { diff --git a/cmd/crowdsec-cli/utils.go b/cmd/crowdsec-cli/utils.go index b568c6eae..1ae8f9da2 100644 --- a/cmd/crowdsec-cli/utils.go +++ b/cmd/crowdsec-cli/utils.go @@ -25,6 +25,7 @@ func manageCliDecisionAlerts(ip *string, ipRange *string, scope *string, value * return fmt.Errorf("%s isn't a valid range", *ipRange) } } + if *ip != "" { ipRepr := net.ParseIP(*ip) if ipRepr == nil { @@ -32,7 +33,7 @@ func manageCliDecisionAlerts(ip *string, ipRange *string, scope *string, value * } } - //avoid confusion on scope (ip vs Ip and range vs Range) + // avoid confusion on scope (ip vs Ip and range vs Range) switch strings.ToLower(*scope) { case "ip": *scope = types.Ip @@ -43,6 +44,7 @@ func manageCliDecisionAlerts(ip *string, ipRange *string, scope *string, value * case "as": *scope = types.AS } + return nil } diff --git a/pkg/csconfig/api.go b/pkg/csconfig/api.go index cdff39e70..de8ee4934 100644 --- a/pkg/csconfig/api.go +++ b/pkg/csconfig/api.go @@ -178,6 +178,7 @@ func (l *LocalApiClientCfg) Load() error { func (lapiCfg *LocalApiServerCfg) GetTrustedIPs() ([]net.IPNet, error) { trustedIPs := make([]net.IPNet, 0) + for _, ip := range lapiCfg.TrustedIPs { cidr := toValidCIDR(ip) @@ -265,7 +266,7 @@ func (c *Config) LoadAPIServer(inCli bool) error { return fmt.Errorf("no listen_uri specified") } - //inherit log level from common, then api->server + // inherit log level from common, then api->server var logLevel log.Level if c.API.Server.LogLevel != nil { logLevel = *c.API.Server.LogLevel diff --git a/pkg/csconfig/config.go b/pkg/csconfig/config.go index a70441495..2dc7ecc7d 100644 --- a/pkg/csconfig/config.go +++ b/pkg/csconfig/config.go @@ -25,7 +25,7 @@ var globalConfig = Config{} // Config contains top-level defaults -> overridden by configuration file -> overridden by CLI flags type Config struct { - //just a path to ourselves :p + // just a path to ourselves :p FilePath *string `yaml:"-"` Self []byte `yaml:"-"` Common *CommonCfg `yaml:"common,omitempty"` @@ -44,10 +44,12 @@ type Config struct { func NewConfig(configFile string, disableAgent bool, disableAPI bool, inCli bool) (*Config, string, error) { patcher := yamlpatch.NewPatcher(configFile, ".local") patcher.SetQuiet(inCli) + fcontent, err := patcher.MergedPatchContent() if err != nil { return nil, "", err } + configData := csstring.StrictExpand(string(fcontent), os.LookupEnv) cfg := Config{ FilePath: &configFile, diff --git a/test/bats/97_ipv6_single.bats b/test/bats/97_ipv6_single.bats index ffbfc125b..982976d70 100644 --- a/test/bats/97_ipv6_single.bats +++ b/test/bats/97_ipv6_single.bats @@ -19,7 +19,7 @@ teardown_file() { setup() { load "../lib/setup.sh" - if is_db_mysql; then sleep 0.3; fi + if is_db_mysql; then sleep 0.5; fi } api() {