From 5cb7013575ce9709b4cd66c53f62228f6a3fd8ee Mon Sep 17 00:00:00 2001 From: mmetc <92726601+mmetc@users.noreply.github.com> Date: Thu, 27 Jul 2023 17:02:20 +0200 Subject: [PATCH] Check cscli preconditions with crowdsec-cli/require package (#2388) --- cmd/crowdsec-cli/alerts.go | 6 +- cmd/crowdsec-cli/bouncers.go | 7 ++- cmd/crowdsec-cli/capi.go | 18 +++--- cmd/crowdsec-cli/config_show.go | 14 ++++- cmd/crowdsec-cli/console.go | 26 +++------ cmd/crowdsec-cli/dashboard.go | 21 ++++--- cmd/crowdsec-cli/machines.go | 9 ++- cmd/crowdsec-cli/notifications.go | 20 ++++--- cmd/crowdsec-cli/papi.go | 15 ++--- cmd/crowdsec-cli/require/require.go | 85 +++++++++++++++++++++++++++++ cmd/crowdsec/main.go | 6 +- docker/docker_start.sh | 19 ++++--- pkg/csconfig/api.go | 30 +++++----- pkg/csconfig/api_test.go | 1 + test/bats/02_nolapi.bats | 19 +++++-- test/bats/03_noagent.bats | 10 +++- test/bats/04_capi.bats | 8 ++- test/bats/04_nocapi.bats | 2 +- test/bats/07_setup.bats | 2 +- test/bats/12_notifications.bats | 39 +++++++++++++ test/lib/setup_file.sh | 8 ++- 21 files changed, 260 insertions(+), 105 deletions(-) create mode 100644 cmd/crowdsec-cli/require/require.go create mode 100644 test/bats/12_notifications.bats diff --git a/cmd/crowdsec-cli/alerts.go b/cmd/crowdsec-cli/alerts.go index 6abe3db5a..a087a06a5 100644 --- a/cmd/crowdsec-cli/alerts.go +++ b/cmd/crowdsec-cli/alerts.go @@ -25,6 +25,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/database" "github.com/crowdsecurity/crowdsec/pkg/models" "github.com/crowdsecurity/crowdsec/pkg/types" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) func DecisionsFromAlert(alert *models.Alert) string { @@ -525,8 +527,8 @@ func NewAlertsFlushCmd() *cobra.Command { DisableAutoGenTag: true, RunE: func(cmd *cobra.Command, args []string) error { var err error - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - return fmt.Errorf("local API is disabled, please run this command on the local API machine") + if err := require.LAPI(csConfig); err != nil { + return err } dbClient, err = database.NewClient(csConfig.DbConfig) if err != nil { diff --git a/cmd/crowdsec-cli/bouncers.go b/cmd/crowdsec-cli/bouncers.go index 96fc8c5a2..e5ad5973b 100644 --- a/cmd/crowdsec-cli/bouncers.go +++ b/cmd/crowdsec-cli/bouncers.go @@ -16,6 +16,8 @@ import ( middlewares "github.com/crowdsecurity/crowdsec/pkg/apiserver/middlewares/v1" "github.com/crowdsecurity/crowdsec/pkg/database" "github.com/crowdsecurity/crowdsec/pkg/types" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) func getBouncers(out io.Writer, dbClient *database.Client) error { @@ -200,9 +202,10 @@ Note: This command requires database direct access, so is intended to be run on DisableAutoGenTag: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { var err error - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - return fmt.Errorf("local API is disabled, please run this command on the local API machine") + if err = require.LAPI(csConfig); err != nil { + return err } + dbClient, err = database.NewClient(csConfig.DbConfig) if err != nil { return fmt.Errorf("unable to create new database client: %s", err) diff --git a/cmd/crowdsec-cli/capi.go b/cmd/crowdsec-cli/capi.go index af6e9c2e8..a3ab00ebb 100644 --- a/cmd/crowdsec-cli/capi.go +++ b/cmd/crowdsec-cli/capi.go @@ -19,6 +19,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/fflag" "github.com/crowdsecurity/crowdsec/pkg/models" "github.com/crowdsecurity/crowdsec/pkg/types" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) const CAPIBaseURL string = "https://api.crowdsec.net/" @@ -31,14 +33,12 @@ func NewCapiCmd() *cobra.Command { Args: cobra.MinimumNArgs(1), DisableAutoGenTag: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - if err := csConfig.LoadAPIServer(); err != nil { - return fmt.Errorf("local API is disabled, please run this command on the local API machine: %w", err) + if err := require.LAPI(csConfig); err != nil { + return err } - if csConfig.DisableAPI { - return nil - } - if csConfig.API.Server.OnlineClient == nil { - log.Fatalf("no configuration for Central API in '%s'", *csConfig.FilePath) + + if err := require.CAPI(csConfig); err != nil { + return err } return nil @@ -134,10 +134,6 @@ func NewCapiStatusCmd() *cobra.Command { Args: cobra.MinimumNArgs(0), DisableAutoGenTag: true, Run: func(cmd *cobra.Command, args []string) { - var err error - if csConfig.API.Server == nil { - log.Fatal("There is no configuration on 'api.server:'") - } if csConfig.API.Server.OnlineClient == nil { log.Fatalf("Please provide credentials for the Central API (CAPI) in '%s'", csConfig.API.Server.OnlineClient.CredentialsFilePath) } diff --git a/cmd/crowdsec-cli/config_show.go b/cmd/crowdsec-cli/config_show.go index 2e1fc7092..b7675faff 100644 --- a/cmd/crowdsec-cli/config_show.go +++ b/cmd/crowdsec-cli/config_show.go @@ -71,7 +71,7 @@ var configShowTemplate = `Global: {{- end }} {{- if .Crowdsec }} -Crowdsec: +Crowdsec{{if and .Crowdsec.Enable (not (ValueBool .Crowdsec.Enable))}} (disabled){{end}}: - Acquisition File : {{.Crowdsec.AcquisitionFilePath}} - Parsers routines : {{.Crowdsec.ParserRoutinesCount}} {{- if .Crowdsec.AcquisitionDirPath }} @@ -97,7 +97,7 @@ API Client: {{- end }} {{- if .API.Server }} -Local API Server: +Local API Server{{if and .API.Server.Enable (not (ValueBool .API.Server.Enable))}} (disabled){{end}}: - Listen URL : {{.API.Server.ListenURI}} - Profile File : {{.API.Server.ProfilesPath}} @@ -194,7 +194,15 @@ func runConfigShow(cmd *cobra.Command, args []string) error { switch csConfig.Cscli.Output { case "human": - tmp, err := template.New("config").Parse(configShowTemplate) + // The tests on .Enable look funny because the option has a true default which has + // not been set yet (we don't really load the LAPI) and go templates don't dereference + // pointers in boolean tests. Prefix notation is the cherry on top. + funcs := template.FuncMap{ + // can't use generics here + "ValueBool": func(b *bool) bool { return b!=nil && *b }, + } + + tmp, err := template.New("config").Funcs(funcs).Parse(configShowTemplate) if err != nil { return err } diff --git a/cmd/crowdsec-cli/console.go b/cmd/crowdsec-cli/console.go index 83886267d..24e5a43fc 100644 --- a/cmd/crowdsec-cli/console.go +++ b/cmd/crowdsec-cli/console.go @@ -4,9 +4,7 @@ import ( "context" "encoding/csv" "encoding/json" - "errors" "fmt" - "io/fs" "net/url" "os" @@ -24,6 +22,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/cwhub" "github.com/crowdsecurity/crowdsec/pkg/fflag" "github.com/crowdsecurity/crowdsec/pkg/types" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) func NewConsoleCmd() *cobra.Command { @@ -33,24 +33,14 @@ func NewConsoleCmd() *cobra.Command { Args: cobra.MinimumNArgs(1), DisableAutoGenTag: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - var fdErr *fs.PathError - if errors.As(err, &fdErr) { - log.Fatalf("Unable to load Local API : %s", fdErr) - } - if err != nil { - log.Fatalf("Unable to load required Local API Configuration : %s", err) - } - log.Fatal("Local API is disabled, please run this command on the local API machine") + if err := require.LAPI(csConfig); err != nil { + return err } - if csConfig.DisableAPI { - log.Fatal("Local API is disabled, please run this command on the local API machine") + if err := require.CAPI(csConfig); err != nil { + return err } - if csConfig.API.Server.OnlineClient == nil { - log.Fatalf("No configuration for Central API (CAPI) in '%s'", *csConfig.FilePath) - } - if csConfig.API.Server.OnlineClient.Credentials == nil { - log.Fatal("You must configure Central API (CAPI) with `cscli capi register` before accessing console features.") + if err := require.Enrolled(csConfig); err != nil { + return err } return nil }, diff --git a/cmd/crowdsec-cli/dashboard.go b/cmd/crowdsec-cli/dashboard.go index f1e7458aa..fbf053876 100644 --- a/cmd/crowdsec-cli/dashboard.go +++ b/cmd/crowdsec-cli/dashboard.go @@ -17,6 +17,8 @@ import ( "github.com/spf13/cobra" "github.com/crowdsecurity/crowdsec/pkg/metabase" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) var ( @@ -54,23 +56,23 @@ cscli dashboard start cscli dashboard stop cscli dashboard remove `, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - if err := metabase.TestAvailability(); err != nil { - log.Fatalf("%s", err) + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if err := require.LAPI(csConfig); err != nil { + return err } - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - log.Fatal("Local API is disabled, please run this command on the local API machine") + if err := metabase.TestAvailability(); err != nil { + return err } metabaseConfigFolderPath := filepath.Join(csConfig.ConfigPaths.ConfigDir, metabaseConfigFolder) metabaseConfigPath = filepath.Join(metabaseConfigFolderPath, metabaseConfigFile) if err := os.MkdirAll(metabaseConfigFolderPath, os.ModePerm); err != nil { - log.Fatal(err) + return err } - if err := csConfig.LoadDBConfig(); err != nil { - log.Errorf("This command requires direct database access (must be run on the local API machine)") - log.Fatal(err) + + if err := require.DB(csConfig); err != nil { + return err } /* @@ -84,6 +86,7 @@ cscli dashboard remove metabaseContainerID = oldContainerID } } + return nil }, } diff --git a/cmd/crowdsec-cli/machines.go b/cmd/crowdsec-cli/machines.go index 215943102..a3cfc33bc 100644 --- a/cmd/crowdsec-cli/machines.go +++ b/cmd/crowdsec-cli/machines.go @@ -26,6 +26,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/database" "github.com/crowdsecurity/crowdsec/pkg/database/ent" "github.com/crowdsecurity/crowdsec/pkg/types" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) var ( @@ -411,11 +413,8 @@ Note: This command requires database direct access, so is intended to be run on DisableAutoGenTag: true, Aliases: []string{"machine"}, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - if err != nil { - log.Errorf("local api : %s", err) - } - return fmt.Errorf("local API is disabled, please run this command on the local API machine") + if err := require.LAPI(csConfig); err != nil { + return err } return nil diff --git a/cmd/crowdsec-cli/notifications.go b/cmd/crowdsec-cli/notifications.go index fe4c14f27..ac9684ceb 100644 --- a/cmd/crowdsec-cli/notifications.go +++ b/cmd/crowdsec-cli/notifications.go @@ -25,6 +25,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/csconfig" "github.com/crowdsecurity/crowdsec/pkg/csplugin" "github.com/crowdsecurity/crowdsec/pkg/csprofiles" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) type NotificationsCfg struct { @@ -41,16 +43,18 @@ func NewNotificationsCmd() *cobra.Command { Args: cobra.MinimumNArgs(1), Aliases: []string{"notifications", "notification"}, DisableAutoGenTag: true, - PersistentPreRun: func(cmd *cobra.Command, args []string) { - var ( - err error - ) - if err = csConfig.API.Server.LoadProfiles(); err != nil { - log.Fatal(err) + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if err := require.LAPI(csConfig); err != nil { + return err } - if csConfig.ConfigPaths.NotificationDir == "" { - log.Fatalf("config_paths.notification_dir is not set in crowdsec config") + if err := require.Profiles(csConfig); err != nil { + return err } + if err := require.Notifications(csConfig); err != nil { + return err + } + + return nil }, } diff --git a/cmd/crowdsec-cli/papi.go b/cmd/crowdsec-cli/papi.go index d38da0df9..cdb66c4a4 100644 --- a/cmd/crowdsec-cli/papi.go +++ b/cmd/crowdsec-cli/papi.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "time" log "github.com/sirupsen/logrus" @@ -12,6 +11,8 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/apiserver" "github.com/crowdsecurity/crowdsec/pkg/database" + + "github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require" ) func NewPapiCmd() *cobra.Command { @@ -21,14 +22,14 @@ func NewPapiCmd() *cobra.Command { Args: cobra.MinimumNArgs(1), DisableAutoGenTag: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI { - return fmt.Errorf("Local API is disabled, please run this command on the local API machine: %w", err) + if err := require.LAPI(csConfig); err != nil { + return err } - if csConfig.API.Server.OnlineClient == nil { - log.Fatalf("no configuration for Central API in '%s'", *csConfig.FilePath) + if err := require.CAPI(csConfig); err != nil { + return err } - if csConfig.API.Server.OnlineClient.Credentials.PapiURL == "" { - log.Fatalf("no PAPI URL in configuration") + if err := require.PAPI(csConfig); err != nil { + return err } return nil }, diff --git a/cmd/crowdsec-cli/require/require.go b/cmd/crowdsec-cli/require/require.go new file mode 100644 index 000000000..6daf397c8 --- /dev/null +++ b/cmd/crowdsec-cli/require/require.go @@ -0,0 +1,85 @@ +package require + +import ( + "fmt" + + "github.com/crowdsecurity/crowdsec/pkg/csconfig" +) + +func LAPI(c *csconfig.Config) error { + if err := c.LoadAPIServer(); err != nil { + return fmt.Errorf("failed to load Local API: %w", err) + } + + if c.DisableAPI { + return fmt.Errorf("local API is disabled -- this command must be run on the local API machine") + } + + return nil +} + +func CAPI(c *csconfig.Config) error { + if c.API.Server.OnlineClient == nil { + return fmt.Errorf("no configuration for Central API (CAPI) in '%s'", *c.FilePath) + } + return nil +} + +func PAPI(c *csconfig.Config) error { + if err := LAPI(c); err != nil { + return err + } + + if err := CAPI(c); err != nil { + return err + } + + if c.API.Server.OnlineClient.Credentials.PapiURL == "" { + return fmt.Errorf("no PAPI URL in configuration") + } + return nil +} + +func Enrolled(c *csconfig.Config) error { + if err := CAPI(c); err != nil { + return err + } + + if c.API.Server.OnlineClient.Credentials == nil { + return fmt.Errorf("the Central API (CAPI) must be configured with 'cscli capi register'") + } + + return nil +} + +func DB(c *csconfig.Config) error { + if err := c.LoadDBConfig(); err != nil { + return fmt.Errorf("this command requires direct database access (must be run on the local API machine): %w", err) + } + return nil +} + +func Profiles(c *csconfig.Config) error { + if err := LAPI(c); err != nil { + return err + } + + if err := c.API.Server.LoadProfiles(); err != nil { + return fmt.Errorf("while loading profiles: %w", err) + } + + return nil +} + +func Notifications(c *csconfig.Config) error { + if err := LAPI(c); err != nil { + return err + } + + if c.ConfigPaths.NotificationDir == "" { + return fmt.Errorf("config_paths.notification_dir is not set in crowdsec config") + } + + return nil +} + diff --git a/cmd/crowdsec/main.go b/cmd/crowdsec/main.go index 5c50884b5..273ef6fb8 100644 --- a/cmd/crowdsec/main.go +++ b/cmd/crowdsec/main.go @@ -249,13 +249,13 @@ func LoadConfig(configFile string, disableAgent bool, disableAPI bool, quiet boo return nil, err } - if !flags.DisableAgent { + if !cConfig.DisableAgent { if err := cConfig.LoadCrowdsec(); err != nil { return nil, err } } - if !flags.DisableAPI { + if !cConfig.DisableAPI { if err := cConfig.LoadAPIServer(); err != nil { return nil, err } @@ -290,7 +290,7 @@ func LoadConfig(configFile string, disableAgent bool, disableAPI bool, quiet boo cConfig.API.Server.OnlineClient = nil } /*if the api is disabled as well, just read file and exit, don't daemonize*/ - if flags.DisableAPI { + if cConfig.DisableAPI { cConfig.Common.Daemonize = false } log.Infof("single file mode : log_media=%s daemonize=%t", cConfig.Common.LogMedia, cConfig.Common.Daemonize) diff --git a/docker/docker_start.sh b/docker/docker_start.sh index 21b42dcb0..9d1076deb 100755 --- a/docker/docker_start.sh +++ b/docker/docker_start.sh @@ -243,7 +243,7 @@ if istrue "$DISABLE_ONLINE_API"; then fi # registration to online API for signal push -if isfalse "$DISABLE_ONLINE_API" ; then +if isfalse "$DISABLE_LOCAL_API" && isfalse "$DISABLE_ONLINE_API" ; then CONFIG_DIR=$(conf_get '.config_paths.config_dir') export CONFIG_DIR config_exists=$(conf_get '.api.server.online_client | has("credentials_path")') @@ -255,7 +255,7 @@ if isfalse "$DISABLE_ONLINE_API" ; then fi # Enroll instance if enroll key is provided -if isfalse "$DISABLE_ONLINE_API" && [ "$ENROLL_KEY" != "" ]; then +if isfalse "$DISABLE_LOCAL_API" && isfalse "$DISABLE_ONLINE_API" && [ "$ENROLL_KEY" != "" ]; then enroll_args="" if [ "$ENROLL_INSTANCE_NAME" != "" ]; then enroll_args="--name $ENROLL_INSTANCE_NAME" @@ -278,8 +278,7 @@ if [ "$GID" != "" ]; then fi fi -# XXX only with LAPI -if istrue "$USE_TLS"; then +if isfalse "$DISABLE_LOCAL_API" && istrue "$USE_TLS"; then agents_allowed_yaml=$(csv2yaml "$AGENTS_ALLOWED_OU") export agents_allowed_yaml bouncers_allowed_yaml=$(csv2yaml "$BOUNCERS_ALLOWED_OU") @@ -358,7 +357,7 @@ shopt -s nullglob extglob for BOUNCER in /run/secrets/@(bouncer_key|BOUNCER_KEY)* ; do KEY=$(cat "${BOUNCER}") NAME=$(echo "${BOUNCER}" | awk -F "/" '{printf $NF}' | cut -d_ -f2-) - if [[ -n $KEY ]] && [[ -n $NAME ]]; then + if [[ -n $KEY ]] && [[ -n $NAME ]]; then register_bouncer "$NAME" "$KEY" fi done @@ -369,6 +368,12 @@ shopt -u nullglob extglob conf_set_if "$CAPI_WHITELISTS_PATH" '.api.server.capi_whitelists_path = strenv(CAPI_WHITELISTS_PATH)' conf_set_if "$METRICS_PORT" '.prometheus.listen_port=env(METRICS_PORT)' +if istrue "$DISABLE_LOCAL_API"; then + conf_set '.api.server.enable=false' +else + conf_set '.api.server.enable=true' +fi + ARGS="" if [ "$CONFIG_FILE" != "" ]; then ARGS="-c $CONFIG_FILE" @@ -390,10 +395,6 @@ if istrue "$DISABLE_AGENT"; then ARGS="$ARGS -no-cs" fi -if istrue "$DISABLE_LOCAL_API"; then - ARGS="$ARGS -no-api" -fi - if istrue "$LEVEL_TRACE"; then ARGS="$ARGS -trace" fi diff --git a/pkg/csconfig/api.go b/pkg/csconfig/api.go index 06d6a9712..00792f47c 100644 --- a/pkg/csconfig/api.go +++ b/pkg/csconfig/api.go @@ -234,6 +234,21 @@ func (c *Config) LoadAPIServer() error { return nil } + if c.API.Server.Enable == nil { + // if the option is not present, it is enabled by default + c.API.Server.Enable = ptr.Of(true) + } + + if !*c.API.Server.Enable { + log.Warning("crowdsec local API is disabled because 'enable' is set to false") + c.DisableAPI = true + return nil + } + + if c.DisableAPI { + return nil + } + //inherit log level from common, then api->server var logLevel log.Level if c.API.Server.LogLevel != nil { @@ -268,21 +283,6 @@ func (c *Config) LoadAPIServer() error { log.Infof("loaded capi whitelist from %s: %d IPs, %d CIDRs", c.API.Server.CapiWhitelistsPath, len(c.API.Server.CapiWhitelists.Ips), len(c.API.Server.CapiWhitelists.Cidrs)) } - if c.API.Server.Enable == nil { - // if the option is not present, it is enabled by default - c.API.Server.Enable = ptr.Of(true) - } - - if !*c.API.Server.Enable { - log.Warning("crowdsec local API is disabled because 'enable' is set to false") - c.DisableAPI = true - return nil - } - - if c.DisableAPI { - return nil - } - if err := c.LoadCommon(); err != nil { return fmt.Errorf("loading common configuration: %s", err) } diff --git a/pkg/csconfig/api_test.go b/pkg/csconfig/api_test.go index 7450800e9..f206db495 100644 --- a/pkg/csconfig/api_test.go +++ b/pkg/csconfig/api_test.go @@ -234,6 +234,7 @@ func TestLoadAPIServer(t *testing.T) { DisableAPI: false, }, expected: &LocalApiServerCfg{ + Enable: ptr.Of(true), PapiLogLevel: &logLevel, }, expectedErr: "no database configuration provided", diff --git a/test/bats/02_nolapi.bats b/test/bats/02_nolapi.bats index c457900ee..a434e8a6d 100644 --- a/test/bats/02_nolapi.bats +++ b/test/bats/02_nolapi.bats @@ -45,16 +45,23 @@ teardown() { config_disable_lapi rune -1 cscli capi status assert_stderr --partial "crowdsec local API is disabled" - assert_stderr --partial "There is no configuration on 'api.server:'" + assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" } -@test "cscli config show -o human" { - config_disable_lapi +@test "no lapi: cscli config show -o human" { + config_set '.api.server.enable=false' rune -0 cscli config show -o human assert_output --partial "Global:" assert_output --partial "Crowdsec:" assert_output --partial "cscli:" - refute_output --partial "Local API Server:" + assert_output --partial "Local API Server (disabled):" + + config_set 'del(.api.server)' + rune -0 cscli config show -o human + assert_output --partial "Global:" + assert_output --partial "Crowdsec:" + assert_output --partial "cscli:" + refute_output --partial "Local API Server" } @test "cscli config backup" { @@ -73,7 +80,7 @@ teardown() { config_disable_lapi ./instance-crowdsec start || true rune -1 cscli machines list - assert_stderr --partial "local API is disabled, please run this command on the local API machine" + assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" } @test "cscli metrics" { @@ -85,5 +92,5 @@ teardown() { assert_output --partial "/v1/watchers/login" assert_stderr --partial "crowdsec local API is disabled" - assert_stderr --partial "local API is disabled, please run this command on the local API machine" + assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" } diff --git a/test/bats/03_noagent.bats b/test/bats/03_noagent.bats index 12c66d2c0..a91737f99 100644 --- a/test/bats/03_noagent.bats +++ b/test/bats/03_noagent.bats @@ -40,13 +40,19 @@ teardown() { } @test "no agent: cscli config show" { - config_disable_agent + config_set '.crowdsec_service.enable=false' rune -0 cscli config show -o human assert_output --partial "Global:" assert_output --partial "cscli:" assert_output --partial "Local API Server:" + assert_output --partial "Crowdsec (disabled):" - refute_output --partial "Crowdsec:" + config_set 'del(.crowdsec_service)' + rune -0 cscli config show -o human + assert_output --partial "Global:" + assert_output --partial "cscli:" + assert_output --partial "Local API Server:" + refute_output --partial "Crowdsec" } @test "no agent: cscli config backup" { diff --git a/test/bats/04_capi.bats b/test/bats/04_capi.bats index f4c9f49e0..2cfabc7b7 100644 --- a/test/bats/04_capi.bats +++ b/test/bats/04_capi.bats @@ -60,5 +60,11 @@ setup() { ONLINE_API_CREDENTIALS_YAML="$(config_get '.api.server.online_client.credentials_path')" rm "${ONLINE_API_CREDENTIALS_YAML}" rune -1 cscli capi status - assert_stderr --partial "local API is disabled, please run this command on the local API machine: loading online client credentials: failed to read api server credentials configuration file '${ONLINE_API_CREDENTIALS_YAML}': open ${ONLINE_API_CREDENTIALS_YAML}: no such file or directory" + assert_stderr --partial "failed to load Local API: loading online client credentials: failed to read api server credentials configuration file '${ONLINE_API_CREDENTIALS_YAML}': open ${ONLINE_API_CREDENTIALS_YAML}: no such file or directory" +} + +@test "capi register must be run from lapi" { + config_disable_lapi + rune -1 cscli capi register --schmilblick githubciXXXXXXXXXXXXXXXXXXXXXXXX + assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" } diff --git a/test/bats/04_nocapi.bats b/test/bats/04_nocapi.bats index 388277cca..23994c43e 100644 --- a/test/bats/04_nocapi.bats +++ b/test/bats/04_nocapi.bats @@ -41,7 +41,7 @@ teardown() { config_disable_capi ./instance-crowdsec start rune -1 cscli capi status - assert_stderr --partial "no configuration for Central API in " + assert_stderr --partial "no configuration for Central API (CAPI) in " } @test "no capi: cscli config show" { diff --git a/test/bats/07_setup.bats b/test/bats/07_setup.bats index c63f07024..c31120376 100644 --- a/test/bats/07_setup.bats +++ b/test/bats/07_setup.bats @@ -311,7 +311,7 @@ update-notifier-motd.timer enabled enabled @test "cscli setup detect (process)" { # This is harder to mock, because gopsutil requires proc/ to be a mount # point. So we pick a process that exists for sure. - expected_process=$(basename "$SHELL") + expected_process=cscli cat <<-EOT >"${DETECT_YAML}" version: 1.0 diff --git a/test/bats/12_notifications.bats b/test/bats/12_notifications.bats new file mode 100644 index 000000000..86032bf82 --- /dev/null +++ b/test/bats/12_notifications.bats @@ -0,0 +1,39 @@ +#!/usr/bin/env bats +# vim: ft=bats:list:ts=8:sts=4:sw=4:et:ai:si: + +set -u + +setup_file() { + load "../lib/setup_file.sh" +} + +teardown_file() { + load "../lib/teardown_file.sh" +} + +setup() { + load "../lib/setup.sh" + load "../lib/bats-file/load.bash" + ./instance-data load + ./instance-crowdsec start +} + +teardown() { + cd "$TEST_DIR" || exit 1 + ./instance-crowdsec stop +} + +#---------- + +@test "cscli notifications list" { + rune -0 cscli notifications list + assert_output --partial "Name" + assert_output --partial "Type" + assert_output --partial "Profile name" +} + +@test "cscli notifications must be run from lapi" { + config_disable_lapi + rune -1 cscli notifications list + assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" +} diff --git a/test/lib/setup_file.sh b/test/lib/setup_file.sh index a4231c98e..385e5f586 100755 --- a/test/lib/setup_file.sh +++ b/test/lib/setup_file.sh @@ -67,7 +67,9 @@ config_set() { export -f config_set config_disable_agent() { - config_set 'del(.crowdsec_service)' + config_set '.crowdsec_service.enable=false' + # this should be equivalent to: + # config_set 'del(.crowdsec_service)' } export -f config_disable_agent @@ -77,7 +79,9 @@ config_log_stderr() { export -f config_log_stderr config_disable_lapi() { - config_set 'del(.api.server)' + config_set '.api.server.enable=false' + # this should be equivalent to: + # config_set 'del(.api.server)' } export -f config_disable_lapi