functional tests, minor refactoring and lint/cleanup (#1570)
* cmd/crowdsec: removed log.Fatal()s, added tests and print error for unrecognized argument * updated golangci-lint to v1.46 * lint/deadcode: fix existing issues * tests: cscli config backup/restore * tests: cscli completion powershell/fish * err check: pflags MarkHidden() * empty .dockerignore (and explain the reason) * tests, errors.Wrap * test for CS_LAPI_SECRET and minor refactoring * minor style changes * log cleanup
This commit is contained in:
parent
df7c51f34e
commit
799cc82bb5
48 changed files with 388 additions and 278 deletions
3
.dockerignore
Normal file
3
.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
# We include .git in the build context because excluding it would break the
|
||||
# "make release" target, which uses git to retrieve the build version and tag.
|
||||
#.git
|
|
@ -19,12 +19,12 @@ jobs:
|
|||
name: lint-windows
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
version: v1.45.2
|
||||
version: v1.46
|
||||
# Optional: golangci-lint command line arguments.
|
||||
args: --issues-exit-code=0 --timeout 10m
|
||||
only-new-issues: true
|
||||
|
|
3
.github/workflows/ci_golangci-lint.yml
vendored
3
.github/workflows/ci_golangci-lint.yml
vendored
|
@ -19,13 +19,12 @@ jobs:
|
|||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
||||
version: v1.45
|
||||
version: v1.46
|
||||
# Optional: golangci-lint command line arguments.
|
||||
args: --issues-exit-code=1 --timeout 5m
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
|
|
|
@ -38,10 +38,11 @@ linters:
|
|||
#
|
||||
# DEPRECATED by golangi-lint
|
||||
#
|
||||
- golint # [deprecated]: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||
- interfacer # [deprecated]: Linter that suggests narrower interface types
|
||||
- maligned # [deprecated]: Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- scopelint # [deprecated]: Scopelint checks for unpinned variables in go programs
|
||||
- exhaustivestruct # The owner seems to have abandoned the linter. Replaced by exhaustruct.
|
||||
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||
- interfacer # Linter that suggests narrower interface types
|
||||
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted
|
||||
- scopelint # Scopelint checks for unpinned variables in go programs
|
||||
|
||||
#
|
||||
# Enabled
|
||||
|
@ -96,6 +97,8 @@ linters:
|
|||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
||||
- nilerr # Finds the code that returns nil even if it checks that the error is not nil.
|
||||
- nonamedreturns # Reports all named returns
|
||||
- nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL.
|
||||
- predeclared # find code that shadows one of Go's predeclared identifiers
|
||||
- promlinter # Check Prometheus metrics naming via promlint
|
||||
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
|
||||
|
@ -148,13 +151,14 @@ linters:
|
|||
- testpackage # linter that makes you use a separate _test package
|
||||
|
||||
#
|
||||
# Too strict (for now?)
|
||||
# Too strict / too many false positives (for now?)
|
||||
#
|
||||
- execinquery # execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds
|
||||
- forbidigo # Forbids identifiers
|
||||
- tagliatelle # Checks the struct tags.
|
||||
- varnamelen # checks that the length of a variable's name matches its scope
|
||||
- gochecknoglobals # check that no global variables exist
|
||||
- exhaustivestruct # Checks if all struct's fields are initialized
|
||||
- exhaustruct # Checks if all structure fields are initialized
|
||||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- stylecheck # Stylecheck is a replacement for golint
|
||||
|
||||
|
@ -228,16 +232,6 @@ issues:
|
|||
- gosimple
|
||||
text: "S1028: should use .* instead of .*"
|
||||
|
||||
#
|
||||
# deadcode
|
||||
#
|
||||
|
||||
- linters:
|
||||
- deadcode
|
||||
- unused
|
||||
- structcheck
|
||||
text: ".* is unused"
|
||||
|
||||
#
|
||||
# ineffassign
|
||||
#
|
||||
|
|
|
@ -103,7 +103,9 @@ func NewCapiCmd() *cobra.Command {
|
|||
}
|
||||
cmdCapiRegister.Flags().StringVarP(&outputFile, "file", "f", "", "output file destination")
|
||||
cmdCapiRegister.Flags().StringVar(&capiUserPrefix, "schmilblick", "", "set a schmilblick (use in tests only)")
|
||||
cmdCapiRegister.Flags().MarkHidden("schmilblick")
|
||||
if err := cmdCapiRegister.Flags().MarkHidden("schmilblick"); err != nil {
|
||||
log.Fatalf("failed to hide flag: %s", err)
|
||||
}
|
||||
cmdCapi.AddCommand(cmdCapiRegister)
|
||||
|
||||
var cmdCapiStatus = &cobra.Command{
|
||||
|
@ -131,11 +133,11 @@ func NewCapiCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to load hub index : %s", err)
|
||||
}
|
||||
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
||||
|
|
|
@ -21,7 +21,7 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
DisableAutoGenTag: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if csConfig.Hub == nil {
|
||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||
|
@ -32,8 +32,8 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -60,11 +60,10 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
for _, name := range args {
|
||||
if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, forceAction, downloadOnly); err != nil {
|
||||
if ignoreError {
|
||||
log.Errorf("Error while installing '%s': %s", name, err)
|
||||
} else {
|
||||
if !ignoreError {
|
||||
log.Fatalf("Error while installing '%s': %s", name, err)
|
||||
}
|
||||
log.Errorf("Error while installing '%s': %s", name, err)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -91,7 +90,7 @@ func NewCollectionsCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
log.Fatalf("Specify at least one collection to remove or '--all' flag.")
|
||||
log.Fatal("Specify at least one collection to remove or '--all' flag.")
|
||||
}
|
||||
|
||||
for _, name := range args {
|
||||
|
|
|
@ -47,13 +47,13 @@ func backupConfigToDirectory(dirPath string) error {
|
|||
}
|
||||
|
||||
if err = os.Mkdir(dirPath, 0700); err != nil {
|
||||
return fmt.Errorf("error while creating %s : %s", dirPath, err)
|
||||
return errors.Wrapf(err, "while creating %s", dirPath)
|
||||
}
|
||||
|
||||
if csConfig.ConfigPaths.SimulationFilePath != "" {
|
||||
backupSimulation := filepath.Join(dirPath, "simulation.yaml")
|
||||
if err = types.CopyFile(csConfig.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
|
||||
return fmt.Errorf("failed copy %s to %s : %s", csConfig.ConfigPaths.SimulationFilePath, backupSimulation, err)
|
||||
return errors.Wrapf(err, "failed copy %s to %s", csConfig.ConfigPaths.SimulationFilePath, backupSimulation)
|
||||
}
|
||||
log.Infof("Saved simulation to %s", backupSimulation)
|
||||
}
|
||||
|
@ -437,11 +437,11 @@ func NewConfigCmd() *cobra.Command {
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
if err = backupConfigToDirectory(args[0]); err != nil {
|
||||
log.Fatalf("Failed to backup configurations: %s", err)
|
||||
|
@ -466,11 +466,11 @@ func NewConfigCmd() *cobra.Command {
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
var err error
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
if err := restoreConfigFromDirectory(args[0]); err != nil {
|
||||
log.Fatalf("failed restoring configurations from %s : %s", args[0], err)
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// +build linux freebsd netbsd openbsd solaris !windows
|
||||
|
||||
package main
|
||||
|
||||
const DefaultConfigFile = "/etc/crowdsec/config.yaml"
|
|
@ -1,6 +0,0 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
const DefaultConfigFile = "C:\\ProgramData\\CrowdSec\\config\\config.yaml"
|
|
@ -78,12 +78,12 @@ After running this command your will need to validate the enrollment in the weba
|
|||
}
|
||||
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Fatalf("Failed to load hub index : %s", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
|
||||
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
||||
|
|
|
@ -44,11 +44,11 @@ cscli hub update # Download list of available configurations from the hub
|
|||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
//use LocalSync to get warnings about tainted / outdated items
|
||||
_, warn := cwhub.LocalSync(csConfig.Hub)
|
||||
|
@ -84,7 +84,7 @@ Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.inde
|
|||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
|
@ -118,11 +118,11 @@ Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if
|
|||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
|
||||
log.Infof("Upgrading collections")
|
||||
|
|
|
@ -134,12 +134,12 @@ Keep in mind the machine needs to be validated by an administrator on LAPI side
|
|||
log.Fatalf("parsing api url ('%s'): %s", apiurl, err)
|
||||
}
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to load hub index : %s", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
||||
if err != nil {
|
||||
|
|
|
@ -155,7 +155,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
|||
|
||||
rootCmd.PersistentFlags().StringVar(&cwhub.HubBranch, "branch", "", "Override hub branch on github")
|
||||
if err := rootCmd.PersistentFlags().MarkHidden("branch"); err != nil {
|
||||
log.Fatalf("failed to make branch hidden : %s", err)
|
||||
log.Fatalf("failed to hide flag: %s", err)
|
||||
}
|
||||
|
||||
if len(os.Args) > 1 && os.Args[1] != "completion" && os.Args[1] != "version" && os.Args[1] != "help" {
|
||||
|
|
|
@ -5,24 +5,19 @@ import (
|
|||
"runtime"
|
||||
)
|
||||
|
||||
const (
|
||||
ReloadMessageFormat = `Run '%s' for the new configuration to be effective.`
|
||||
ReloadCmdLinux = `sudo systemctl reload crowdsec`
|
||||
ReloadCmdFreebsd = `sudo service crowdsec reload`
|
||||
)
|
||||
|
||||
// ReloadMessage returns a description of the task required to reload
|
||||
// the crowdsec configuration, according to the operating system.
|
||||
func ReloadMessage() string {
|
||||
|
||||
var reloadCmd string
|
||||
var msg string
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
return "Please restart the crowdsec service for the new configuration to be effective."
|
||||
msg = "Please restart the crowdsec service"
|
||||
case "freebsd":
|
||||
reloadCmd = ReloadCmdFreebsd
|
||||
msg = `Run 'sudo service crowdsec reload'`
|
||||
default:
|
||||
reloadCmd = ReloadCmdLinux
|
||||
msg = `Run 'sudo systemctl reload crowdsec'`
|
||||
}
|
||||
|
||||
return fmt.Sprintf(ReloadMessageFormat, reloadCmd)
|
||||
return fmt.Sprintf("%s for the new configuration to be effective.", msg)
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ cscli parsers remove crowdsecurity/sshd-logs
|
|||
DisableAutoGenTag: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if csConfig.Hub == nil {
|
||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||
|
@ -36,8 +36,8 @@ cscli parsers remove crowdsecurity/sshd-logs
|
|||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
|
|
@ -24,7 +24,7 @@ func NewPostOverflowsCmd() *cobra.Command {
|
|||
DisableAutoGenTag: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if csConfig.Hub == nil {
|
||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||
|
@ -35,8 +35,8 @@ func NewPostOverflowsCmd() *cobra.Command {
|
|||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
|
|
@ -27,7 +27,7 @@ cscli scenarios remove crowdsecurity/ssh-bf
|
|||
DisableAutoGenTag: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if csConfig.Hub == nil {
|
||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
||||
|
@ -38,7 +38,7 @@ cscli scenarios remove crowdsecurity/ssh-bf
|
|||
}
|
||||
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -134,11 +134,11 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
DisableAutoGenTag: true,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||
log.Info("Run 'sudo cscli hub update' to get the hub index")
|
||||
log.Fatalf("Failed to get Hub index : %v", err)
|
||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
||||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
|
@ -153,7 +153,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
}
|
||||
isExcluded := inSlice(scenario, csConfig.Cscli.SimulationConfig.Exclusions)
|
||||
if *csConfig.Cscli.SimulationConfig.Simulation && !isExcluded {
|
||||
log.Warningf("global simulation is already enabled")
|
||||
log.Warning("global simulation is already enabled")
|
||||
continue
|
||||
}
|
||||
if !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||
|
@ -162,13 +162,13 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
}
|
||||
if *csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||
if err := removeFromExclusion(scenario); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("simulation enabled for '%s'", scenario)
|
||||
continue
|
||||
}
|
||||
if err := addToExclusion(scenario); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("simulation mode for '%s' enabled", scenario)
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
}
|
||||
if !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||
if err := removeFromExclusion(scenario); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("simulation mode for '%s' disabled", scenario)
|
||||
continue
|
||||
|
@ -212,7 +212,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
continue
|
||||
}
|
||||
if err := addToExclusion(scenario); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("simulation mode for '%s' disabled", scenario)
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
|||
DisableAutoGenTag: true,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := simulationStatus(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||
|
|
|
@ -51,7 +51,7 @@ func indexOf(s string, slice []string) int {
|
|||
|
||||
func LoadHub() error {
|
||||
if err := csConfig.LoadHub(); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
if csConfig.Hub == nil {
|
||||
return fmt.Errorf("unable to load hub")
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/apiserver"
|
||||
|
@ -21,17 +20,17 @@ func initAPIServer(cConfig *csconfig.Config) (*apiserver.APIServer, error) {
|
|||
log.Info("initiating plugin broker")
|
||||
//On windows, the plugins are always run as medium-integrity processes, so we don't care about plugin_config
|
||||
if cConfig.PluginConfig == nil && runtime.GOOS != "windows" {
|
||||
return nil, fmt.Errorf("plugins are enabled, but the plugin_config section is missing in the configuration")
|
||||
return nil, errors.New("plugins are enabled, but the plugin_config section is missing in the configuration")
|
||||
}
|
||||
if cConfig.ConfigPaths.NotificationDir == "" {
|
||||
return nil, fmt.Errorf("plugins are enabled, but config_paths.notification_dir is not defined")
|
||||
return nil, errors.New("plugins are enabled, but config_paths.notification_dir is not defined")
|
||||
}
|
||||
if cConfig.ConfigPaths.PluginDir == "" {
|
||||
return nil, fmt.Errorf("plugins are enabled, but config_paths.plugin_dir is not defined")
|
||||
return nil, errors.New("plugins are enabled, but config_paths.plugin_dir is not defined")
|
||||
}
|
||||
err = pluginBroker.Init(cConfig.PluginConfig, cConfig.API.Server.Profiles, cConfig.ConfigPaths)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to run local API: %s", err)
|
||||
return nil, errors.Wrap(err, "unable to run local API")
|
||||
}
|
||||
log.Info("initiated plugin broker")
|
||||
apiServer.AttachPluginBroker(&pluginBroker)
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// +build linux freebsd netbsd openbsd solaris !windows
|
||||
|
||||
package main
|
||||
|
||||
const DefaultConfigFile = "/etc/crowdsec/config.yaml"
|
|
@ -1,3 +0,0 @@
|
|||
package main
|
||||
|
||||
const DefaultConfigFile = "C:\\ProgramData\\CrowdSec\\config\\config.yaml"
|
|
@ -10,6 +10,7 @@ import (
|
|||
_ "net/http/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/confluentinc/bincover"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||
|
@ -196,7 +197,6 @@ func (f *Flags) Parse() {
|
|||
|
||||
// LoadConfig returns a configuration parsed from configuration file
|
||||
func LoadConfig(cConfig *csconfig.Config) error {
|
||||
|
||||
if dumpFolder != "" {
|
||||
parser.ParseDump = true
|
||||
parser.DumpFolder = dumpFolder
|
||||
|
@ -217,11 +217,11 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
}
|
||||
|
||||
if !cConfig.DisableAgent && (cConfig.API == nil || cConfig.API.Client == nil || cConfig.API.Client.Credentials == nil) {
|
||||
log.Fatalf("missing local API credentials for crowdsec agent, abort")
|
||||
return errors.New("missing local API credentials for crowdsec agent, abort")
|
||||
}
|
||||
|
||||
if cConfig.DisableAPI && cConfig.DisableAgent {
|
||||
log.Fatalf("You must run at least the API Server or crowdsec")
|
||||
return errors.New("You must run at least the API Server or crowdsec")
|
||||
}
|
||||
|
||||
if flags.DebugLevel {
|
||||
|
@ -260,8 +260,26 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// This must be called right before the program termination, to allow
|
||||
// measuring functional test coverage in case of abnormal exit.
|
||||
//
|
||||
// without bincover: log error and exit with code
|
||||
// with bincover: log error and tell bincover the exit code, then return
|
||||
func exitWithCode(exitCode int, err error) {
|
||||
if err != nil {
|
||||
// this method of logging a fatal error does not
|
||||
// trigger a program exit (as stated by the authors, it
|
||||
// is not going to change in logrus to keep backward
|
||||
// compatibility), and allows us to report coverage.
|
||||
log.NewEntry(log.StandardLogger()).Log(log.FatalLevel, err)
|
||||
}
|
||||
if bincoverTesting == "" {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
bincover.ExitCode = exitCode
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer types.CatchPanic("crowdsec/main")
|
||||
|
||||
log.Debugf("os.Args: %v", os.Args)
|
||||
|
@ -269,9 +287,25 @@ func main() {
|
|||
// Handle command line arguments
|
||||
flags = &Flags{}
|
||||
flags.Parse()
|
||||
|
||||
if len(flag.Args()) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "argument provided but not defined: %s\n", flag.Args()[0])
|
||||
flag.Usage()
|
||||
// the flag package exits with 2 in case of unknown flag
|
||||
exitWithCode(2, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if flags.PrintVersion {
|
||||
cwversion.Show()
|
||||
os.Exit(0)
|
||||
exitWithCode(0, nil)
|
||||
return
|
||||
}
|
||||
StartRunSvc()
|
||||
|
||||
exitCode := 0
|
||||
err := StartRunSvc()
|
||||
if err != nil {
|
||||
exitCode = 1
|
||||
}
|
||||
exitWithCode(exitCode, err)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ package main
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/confluentinc/bincover"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
|
@ -14,7 +13,7 @@ import (
|
|||
"github.com/sirupsen/logrus/hooks/writer"
|
||||
)
|
||||
|
||||
func StartRunSvc() {
|
||||
func StartRunSvc() error {
|
||||
var (
|
||||
cConfig *csconfig.Config
|
||||
err error
|
||||
|
@ -30,10 +29,10 @@ func StartRunSvc() {
|
|||
|
||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
// Configure logging
|
||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||
|
@ -51,18 +50,5 @@ func StartRunSvc() {
|
|||
if cConfig.Prometheus != nil {
|
||||
go registerPrometheus(cConfig.Prometheus)
|
||||
}
|
||||
|
||||
if exitCode, err := Serve(cConfig); err != nil {
|
||||
if err != nil {
|
||||
// this method of logging a fatal error does not
|
||||
// trigger a program exit (as stated by the authors, it
|
||||
// is not going to change in logrus to keep backward
|
||||
// compatibility), and allows us to report coverage.
|
||||
log.NewEntry(log.StandardLogger()).Log(log.FatalLevel, err)
|
||||
if bincoverTesting == "" {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
bincover.ExitCode = exitCode
|
||||
}
|
||||
}
|
||||
return Serve(cConfig)
|
||||
}
|
||||
|
|
|
@ -1,61 +1,59 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/confluentinc/bincover"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/sirupsen/logrus/hooks/writer"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
func StartRunSvc() {
|
||||
|
||||
func StartRunSvc() error {
|
||||
const svcName = "CrowdSec"
|
||||
const svcDescription = "Crowdsec IPS/IDS"
|
||||
|
||||
isRunninginService, err := svc.IsWindowsService()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to determine if we are running in windows service mode: %v", err)
|
||||
return errors.Wrap(err, "failed to determine if we are running in windows service mode")
|
||||
}
|
||||
if isRunninginService {
|
||||
runService(svcName)
|
||||
return
|
||||
return runService(svcName)
|
||||
}
|
||||
|
||||
if flags.WinSvc == "Install" {
|
||||
err = installService(svcName, svcDescription)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to %s %s: %v", flags.WinSvc, svcName, err)
|
||||
return errors.Wrapf(err, "failed to %s %s", flags.WinSvc, svcName)
|
||||
}
|
||||
} else if flags.WinSvc == "Remove" {
|
||||
err = removeService(svcName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to %s %s: %v", flags.WinSvc, svcName, err)
|
||||
return errors.Wrapf(err, "failed to %s %s", flags.WinSvc, svcName)
|
||||
}
|
||||
} else if flags.WinSvc == "Start" {
|
||||
err = startService(svcName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to %s %s: %v", flags.WinSvc, svcName, err)
|
||||
return errors.Wrapf(err, "failed to %s %s", flags.WinSvc, svcName)
|
||||
}
|
||||
} else if flags.WinSvc == "Stop" {
|
||||
err = controlService(svcName, svc.Stop, svc.Stopped)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to %s %s: %v", flags.WinSvc, svcName, err)
|
||||
return errors.Wrapf(err, "failed to %s %s", flags.WinSvc, svcName)
|
||||
}
|
||||
} else if flags.WinSvc == "" {
|
||||
WindowsRun()
|
||||
return WindowsRun()
|
||||
} else {
|
||||
log.Fatalf("Invalid value for winsvc parameter: %s", flags.WinSvc)
|
||||
return fmt.Errorf("Invalid value for winsvc parameter: %s", flags.WinSvc)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WindowsRun() {
|
||||
|
||||
func WindowsRun() error {
|
||||
var (
|
||||
cConfig *csconfig.Config
|
||||
err error
|
||||
|
@ -71,15 +69,15 @@ func WindowsRun() {
|
|||
|
||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
// Configure logging
|
||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles, cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Crowdsec %s", cwversion.VersionStr())
|
||||
|
@ -92,18 +90,5 @@ func WindowsRun() {
|
|||
if cConfig.Prometheus != nil {
|
||||
go registerPrometheus(cConfig.Prometheus)
|
||||
}
|
||||
|
||||
if exitCode, err := Serve(cConfig); err != nil {
|
||||
if err != nil {
|
||||
// this method of logging a fatal error does not
|
||||
// trigger a program exit (as stated by the authors, it
|
||||
// is not going to change in logrus to keep backward
|
||||
// compatibility), and allows us to report coverage.
|
||||
log.NewEntry(log.StandardLogger()).Log(log.FatalLevel, err)
|
||||
if bincoverTesting != "" {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
bincover.ExitCode = exitCode
|
||||
}
|
||||
}
|
||||
return Serve(cConfig)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
@ -18,7 +17,7 @@ import (
|
|||
//"github.com/sevlyar/go-daemon"
|
||||
)
|
||||
|
||||
// debugHandler is kept as a dev convenience : it shuts down and serialize internal state
|
||||
//nolint: deadcode,unused // debugHandler is kept as a dev convenience : it shuts down and serialize internal state
|
||||
func debugHandler(sig os.Signal, cConfig *csconfig.Config) error {
|
||||
var tmpFile string
|
||||
var err error
|
||||
|
@ -53,22 +52,22 @@ func reloadHandler(sig os.Signal, cConfig *csconfig.Config) error {
|
|||
|
||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
// Configure logging
|
||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles, cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if !cConfig.DisableAPI {
|
||||
apiServer, err := initAPIServer(cConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to init api server: %s", err)
|
||||
return errors.Wrap(err, "unable to init api server")
|
||||
}
|
||||
|
||||
serveAPIServer(apiServer)
|
||||
|
@ -77,7 +76,7 @@ func reloadHandler(sig os.Signal, cConfig *csconfig.Config) error {
|
|||
if !cConfig.DisableAgent {
|
||||
csParsers, err := initCrowdsec(cConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to init crowdsec: %s", err)
|
||||
return errors.Wrap(err, "unable to init crowdsec")
|
||||
}
|
||||
//restore bucket state
|
||||
if tmpFile != "" {
|
||||
|
@ -164,20 +163,18 @@ func shutdownCrowdsec() error {
|
|||
func shutdown(sig os.Signal, cConfig *csconfig.Config) error {
|
||||
if !cConfig.DisableAgent {
|
||||
if err := shutdownCrowdsec(); err != nil {
|
||||
log.Errorf("Failed to shut down crowdsec: %s", err)
|
||||
return err
|
||||
return errors.Wrap(err, "Failed to shut down crowdsec")
|
||||
}
|
||||
}
|
||||
if !cConfig.DisableAPI {
|
||||
if err := shutdownAPI(); err != nil {
|
||||
log.Errorf("Failed to shut down api routines: %s", err)
|
||||
return err
|
||||
return errors.Wrap(err, "Failed to shut down api routines")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func HandleSignals(cConfig *csconfig.Config) int {
|
||||
func HandleSignals(cConfig *csconfig.Config) error {
|
||||
signalChan := make(chan os.Signal, 1)
|
||||
//We add os.Interrupt mostly to ease windows dev, it allows to simulate a clean shutdown when running in the console
|
||||
signal.Notify(signalChan,
|
||||
|
@ -185,9 +182,10 @@ func HandleSignals(cConfig *csconfig.Config) int {
|
|||
syscall.SIGTERM,
|
||||
os.Interrupt)
|
||||
|
||||
exitChan := make(chan int)
|
||||
exitChan := make(chan error)
|
||||
go func() {
|
||||
defer types.CatchPanic("crowdsec/HandleSignals")
|
||||
Loop:
|
||||
for {
|
||||
s := <-signalChan
|
||||
switch s {
|
||||
|
@ -195,28 +193,33 @@ func HandleSignals(cConfig *csconfig.Config) int {
|
|||
case syscall.SIGHUP:
|
||||
log.Warningf("SIGHUP received, reloading")
|
||||
if err := shutdown(s, cConfig); err != nil {
|
||||
log.Fatalf("failed shutdown : %s", err)
|
||||
exitChan <- errors.Wrap(err, "failed shutdown")
|
||||
break Loop
|
||||
}
|
||||
if err := reloadHandler(s, cConfig); err != nil {
|
||||
log.Fatalf("Reload handler failure : %s", err)
|
||||
exitChan <- errors.Wrap(err, "reload handler failure")
|
||||
break Loop
|
||||
}
|
||||
// ctrl+C, kill -SIGINT XXXX, kill -SIGTERM XXXX
|
||||
case os.Interrupt, syscall.SIGTERM:
|
||||
log.Warningf("SIGTERM received, shutting down")
|
||||
if err := shutdown(s, cConfig); err != nil {
|
||||
log.Fatalf("failed shutdown : %s", err)
|
||||
exitChan <- errors.Wrap(err, "failed shutdown")
|
||||
break Loop
|
||||
}
|
||||
exitChan <- 0
|
||||
exitChan <- nil
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
code := <-exitChan
|
||||
log.Warningf("Crowdsec service shutting down")
|
||||
return code
|
||||
err := <-exitChan
|
||||
if err == nil {
|
||||
log.Warningf("Crowdsec service shutting down")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func Serve(cConfig *csconfig.Config) (int, error) {
|
||||
func Serve(cConfig *csconfig.Config) error {
|
||||
acquisTomb = tomb.Tomb{}
|
||||
parsersTomb = tomb.Tomb{}
|
||||
bucketsTomb = tomb.Tomb{}
|
||||
|
@ -227,7 +230,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
|||
if !cConfig.DisableAPI {
|
||||
apiServer, err := initAPIServer(cConfig)
|
||||
if err != nil {
|
||||
return 1, errors.Wrap(err, "api server init")
|
||||
return errors.Wrap(err, "api server init")
|
||||
}
|
||||
if !flags.TestMode {
|
||||
serveAPIServer(apiServer)
|
||||
|
@ -237,7 +240,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
|||
if !cConfig.DisableAgent {
|
||||
csParsers, err := initCrowdsec(cConfig)
|
||||
if err != nil {
|
||||
return 1, errors.Wrap(err, "crowdsec init")
|
||||
return errors.Wrap(err, "crowdsec init")
|
||||
}
|
||||
/* if it's just linting, we're done */
|
||||
if !flags.TestMode {
|
||||
|
@ -256,7 +259,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
|||
log.Errorf("Failed to notify(sent: %v): %v", sent, err)
|
||||
}
|
||||
/*wait for signals*/
|
||||
return HandleSignals(cConfig), nil
|
||||
return HandleSignals(cConfig)
|
||||
}
|
||||
|
||||
for {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
@ -61,27 +62,29 @@ loop:
|
|||
return
|
||||
}
|
||||
|
||||
func runService(name string) {
|
||||
func runService(name string) error {
|
||||
cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
return err
|
||||
}
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
// Configure logging
|
||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles, cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
log.Infof("starting %s service", name)
|
||||
|
||||
if err := LoadConfig(cConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Configure logging
|
||||
if err := types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles, cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("starting %s service", name)
|
||||
winsvc := crowdsec_winservice{config: cConfig}
|
||||
|
||||
err = svc.Run(name, &winsvc)
|
||||
if err != nil {
|
||||
log.Errorf("%s service failed: %s", name, err)
|
||||
return
|
||||
if err := svc.Run(name, &winsvc); err != nil {
|
||||
return errors.Wrapf(err, "%s service failed", name)
|
||||
}
|
||||
|
||||
log.Infof("%s service stopped", name)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -493,6 +493,7 @@ READLOOP:
|
|||
}
|
||||
}
|
||||
|
||||
//nolint: structcheck,unused
|
||||
type MockSourceByDSN struct {
|
||||
configuration.DataSourceCommonCfg `yaml:",inline"`
|
||||
Toto string `yaml:"toto"`
|
||||
|
|
|
@ -137,14 +137,14 @@ func (f *FileSource) ConfigureByDSN(dsn string, labels map[string]string, logger
|
|||
if len(args) == 2 && len(args[1]) != 0 {
|
||||
params, err := url.ParseQuery(args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse file args : %s", err)
|
||||
return errors.Wrap(err, "could not parse file args")
|
||||
}
|
||||
for key, value := range params {
|
||||
if key != "log_level" {
|
||||
return fmt.Errorf("unsupported key %s in file DSN", key)
|
||||
}
|
||||
if len(value) != 1 {
|
||||
return fmt.Errorf("expected zero or one value for 'log_level'")
|
||||
return errors.New("expected zero or one value for 'log_level'")
|
||||
}
|
||||
lvl, err := log.ParseLevel(value[0])
|
||||
if err != nil {
|
||||
|
@ -351,7 +351,6 @@ func (f *FileSource) tailFile(out chan types.Event, t *tomb.Tomb, tail *tail.Tai
|
|||
logger := f.logger.WithField("tail", tail.Filename)
|
||||
logger.Debugf("-> Starting tail of %s", tail.Filename)
|
||||
for {
|
||||
l := types.Line{}
|
||||
select {
|
||||
case <-t.Dying():
|
||||
logger.Infof("File datasource %s stopping", tail.Filename)
|
||||
|
@ -377,19 +376,22 @@ func (f *FileSource) tailFile(out chan types.Event, t *tomb.Tomb, tail *tail.Tai
|
|||
continue
|
||||
}
|
||||
linesRead.With(prometheus.Labels{"source": tail.Filename}).Inc()
|
||||
l.Raw = trimLine(line.Text)
|
||||
l.Labels = f.config.Labels
|
||||
l.Time = line.Time
|
||||
l.Src = tail.Filename
|
||||
l.Process = true
|
||||
l.Module = f.GetName()
|
||||
l := types.Line{
|
||||
Raw: trimLine(line.Text),
|
||||
Labels: f.config.Labels,
|
||||
Time: line.Time,
|
||||
Src: tail.Filename,
|
||||
Process: true,
|
||||
Module: f.GetName(),
|
||||
}
|
||||
//we're tailing, it must be real time logs
|
||||
logger.Debugf("pushing %+v", l)
|
||||
if !f.config.UseTimeMachine {
|
||||
out <- types.Event{Line: l, Process: true, Type: types.LOG, ExpectMode: leaky.LIVE}
|
||||
} else {
|
||||
out <- types.Event{Line: l, Process: true, Type: types.LOG, ExpectMode: leaky.TIMEMACHINE}
|
||||
|
||||
expectMode := leaky.LIVE
|
||||
if f.config.UseTimeMachine {
|
||||
expectMode = leaky.TIMEMACHINE
|
||||
}
|
||||
out <- types.Event{Line: l, Process: true, Type: types.LOG, ExpectMode: expectMode}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -421,14 +423,15 @@ func (f *FileSource) readFile(filename string, out chan types.Event, t *tomb.Tom
|
|||
if scanner.Text() == "" {
|
||||
continue
|
||||
}
|
||||
logger.Debugf("line %s", scanner.Text())
|
||||
l := types.Line{}
|
||||
l.Raw = scanner.Text()
|
||||
l.Time = time.Now().UTC()
|
||||
l.Src = filename
|
||||
l.Labels = f.config.Labels
|
||||
l.Process = true
|
||||
l.Module = f.GetName()
|
||||
l := types.Line{
|
||||
Raw: scanner.Text(),
|
||||
Time: time.Now().UTC(),
|
||||
Src: filename,
|
||||
Labels: f.config.Labels,
|
||||
Process: true,
|
||||
Module: f.GetName(),
|
||||
}
|
||||
logger.Debugf("line %s", l.Raw)
|
||||
linesRead.With(prometheus.Labels{"source": filename}).Inc()
|
||||
|
||||
//we're reading logs at once, it must be time-machine buckets
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestAlertsListAsMachine(t *testing.T) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
defer teardown()
|
||||
|
@ -240,7 +240,7 @@ func TestAlertsGetAsMachine(t *testing.T) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
defer teardown()
|
||||
|
@ -431,7 +431,7 @@ func TestAlertsCreateAsMachine(t *testing.T) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
defer teardown()
|
||||
|
@ -475,7 +475,7 @@ func TestAlertsDeleteAsMachine(t *testing.T) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
defer teardown()
|
||||
|
|
|
@ -57,7 +57,7 @@ func TestWatcherAuth(t *testing.T) {
|
|||
client, err := NewClient(mycfg)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
_, err = client.Auth.AuthenticateWatcher(context.Background(), models.WatcherAuthRequest{
|
||||
|
@ -81,7 +81,7 @@ func TestWatcherAuth(t *testing.T) {
|
|||
client, err = NewClient(mycfg)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
_, err = client.Auth.AuthenticateWatcher(context.Background(), models.WatcherAuthRequest{
|
||||
|
@ -171,7 +171,7 @@ func TestWatcherUnregister(t *testing.T) {
|
|||
client, err := NewClient(mycfg)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
_, err = client.Auth.UnregisterWatcher(context.Background())
|
||||
if err != nil {
|
||||
|
@ -225,7 +225,7 @@ func TestWatcherEnroll(t *testing.T) {
|
|||
client, err := NewClient(mycfg)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
_, err = client.Auth.EnrollWatcher(context.Background(), "goodkey", "", []string{}, false)
|
||||
|
|
|
@ -41,7 +41,7 @@ func TestApiAuth(t *testing.T) {
|
|||
|
||||
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
alert := DecisionsListOpts{IPEquals: new(string)}
|
||||
|
|
|
@ -46,7 +46,7 @@ func TestDecisionsList(t *testing.T) {
|
|||
|
||||
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
tduration := "3h59m55.756182786s"
|
||||
|
@ -77,7 +77,7 @@ func TestDecisionsList(t *testing.T) {
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(*decisions, *expected) {
|
||||
t.Fatalf("returned %+v, want %+v", resp, expected)
|
||||
|
@ -137,7 +137,7 @@ func TestDecisionsStream(t *testing.T) {
|
|||
|
||||
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
tduration := "3h59m55.756182786s"
|
||||
|
@ -168,7 +168,7 @@ func TestDecisionsStream(t *testing.T) {
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
if !reflect.DeepEqual(*decisions, *expected) {
|
||||
t.Fatalf("returned %+v, want %+v", resp, expected)
|
||||
|
@ -220,7 +220,7 @@ func TestDeleteDecisions(t *testing.T) {
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("new api client: %s", err.Error())
|
||||
log.Fatalf("new api client: %s", err)
|
||||
}
|
||||
|
||||
filters := DecisionsDeleteOpts{IPEquals: new(string)}
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestAPIKey(t *testing.T) {
|
|||
|
||||
APIKey, err := CreateTestBouncer(config.API.Server.DbConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("%s", err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Login with empty token
|
||||
w := httptest.NewRecorder()
|
||||
|
|
|
@ -276,11 +276,11 @@ func (s *APIServer) Run() error {
|
|||
go func() {
|
||||
if s.TLS != nil && s.TLS.CertFilePath != "" && s.TLS.KeyFilePath != "" {
|
||||
if err := s.httpServer.ListenAndServeTLS(s.TLS.CertFilePath, s.TLS.KeyFilePath); err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
if err := s.httpServer.ListenAndServe(); err != http.ErrServerClosed {
|
||||
log.Fatalf(err.Error())
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -38,7 +38,7 @@ func TestCreateMachine(t *testing.T) {
|
|||
// Create machine
|
||||
b, err := json.Marshal(MachineTest)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to marshal MachineTest")
|
||||
log.Fatal("unable to marshal MachineTest")
|
||||
}
|
||||
body := string(b)
|
||||
|
||||
|
@ -61,7 +61,7 @@ func TestCreateMachineWithForwardedFor(t *testing.T) {
|
|||
// Create machine
|
||||
b, err := json.Marshal(MachineTest)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to marshal MachineTest")
|
||||
log.Fatal("unable to marshal MachineTest")
|
||||
}
|
||||
body := string(b)
|
||||
|
||||
|
@ -90,7 +90,7 @@ func TestCreateMachineWithForwardedForNoConfig(t *testing.T) {
|
|||
// Create machine
|
||||
b, err := json.Marshal(MachineTest)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to marshal MachineTest")
|
||||
log.Fatal("unable to marshal MachineTest")
|
||||
}
|
||||
body := string(b)
|
||||
|
||||
|
@ -121,7 +121,7 @@ func TestCreateMachineWithoutForwardedFor(t *testing.T) {
|
|||
// Create machine
|
||||
b, err := json.Marshal(MachineTest)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to marshal MachineTest")
|
||||
log.Fatal("unable to marshal MachineTest")
|
||||
}
|
||||
body := string(b)
|
||||
|
||||
|
|
|
@ -138,29 +138,42 @@ func Unauthorized(c *gin.Context, code int, message string) {
|
|||
})
|
||||
}
|
||||
|
||||
func randomSecret() ([]byte, error) {
|
||||
size := 64
|
||||
secret := make([]byte, size)
|
||||
|
||||
n, err := rand.Read(secret)
|
||||
if err != nil {
|
||||
return nil, errors.New("unable to generate a new random seed for JWT generation")
|
||||
}
|
||||
|
||||
if n != size {
|
||||
return nil, errors.New("not enough entropy at random seed generation for JWT generation")
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func NewJWT(dbClient *database.Client) (*JWT, error) {
|
||||
// Get secret from environment variable "SECRET"
|
||||
var (
|
||||
secret []byte
|
||||
err error
|
||||
)
|
||||
|
||||
//Please be aware that brute force HS256 is possible.
|
||||
//PLEASE choose a STRONG secret
|
||||
secret_string := os.Getenv("CS_LAPI_SECRET")
|
||||
if secret_string == "" {
|
||||
secret = make([]byte, 64)
|
||||
if n, err := rand.Read(secret); err != nil {
|
||||
log.Fatalf("unable to generate a new random seed for JWT generation")
|
||||
} else {
|
||||
if n != 64 {
|
||||
log.Fatalf("not enough entropy at random seed generation for JWT generation")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
secret = []byte(secret_string)
|
||||
if len(secret) < 64 {
|
||||
log.Fatalf("secret not strong enough")
|
||||
// Please be aware that brute force HS256 is possible.
|
||||
// PLEASE choose a STRONG secret
|
||||
secretString := os.Getenv("CS_LAPI_SECRET")
|
||||
secret = []byte(secretString)
|
||||
|
||||
switch l := len(secret); {
|
||||
case l == 0:
|
||||
secret, err = randomSecret()
|
||||
if err != nil {
|
||||
return &JWT{}, err
|
||||
}
|
||||
case l < 64:
|
||||
return &JWT{}, errors.New("CS_LAPI_SECRET not strong enough")
|
||||
}
|
||||
|
||||
jwtMiddleware := &JWT{
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
//go:build !windows
|
||||
|
||||
package apiserver
|
||||
|
||||
import "os"
|
||||
|
||||
func cleanFile(path string) {
|
||||
os.Remove(path)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package apiserver
|
||||
|
||||
import "os"
|
||||
|
||||
func cleanFile(path string) {
|
||||
os.Remove(path)
|
||||
}
|
|
@ -114,7 +114,7 @@ func (c *Config) LoadCrowdsec() error {
|
|||
return fmt.Errorf("loading api client: %s", err.Error())
|
||||
}
|
||||
if err := c.LoadHub(); err != nil {
|
||||
return fmt.Errorf("loading hub: %s", err)
|
||||
return errors.Wrap(err, "while loading hub")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,22 +12,22 @@ import (
|
|||
func TestLoadHub(t *testing.T) {
|
||||
hubFullPath, err := filepath.Abs("./hub")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dataFullPath, err := filepath.Abs("./data")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
configDirFullPath, err := filepath.Abs("./tests")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
hubIndexFileFullPath, err := filepath.Abs("./hub/.index.json")
|
||||
if err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
|
|
|
@ -133,7 +133,6 @@ func TestGetters(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIndexDownload(t *testing.T) {
|
||||
|
||||
cfg := test_prepenv()
|
||||
|
||||
err := UpdateHubIdx(cfg.Hub)
|
||||
|
|
|
@ -295,7 +295,7 @@ func testSubSet(testSet TestFile, pctx UnixParserCtx, nodes []Node) (bool, error
|
|||
only the keys of the expected part are checked against result
|
||||
*/
|
||||
if len(testSet.Results) == 0 && len(results) == 0 {
|
||||
log.Fatalf("No results, no tests, abort.")
|
||||
log.Fatal("No results, no tests, abort.")
|
||||
return false, fmt.Errorf("no tests, no results")
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ func (n *Node) ProcessStatics(statics []types.ExtraField, event *types.Event) er
|
|||
clog.Debugf("%s = '%s'", static.TargetByName, value)
|
||||
}
|
||||
} else {
|
||||
clog.Fatalf("unable to process static : unknown tartget")
|
||||
clog.Fatal("unable to process static : unknown target")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ teardown_file() {
|
|||
|
||||
setup() {
|
||||
load "../lib/setup.sh"
|
||||
load "../lib/bats-file/load.bash"
|
||||
./instance-data load
|
||||
./instance-crowdsec start
|
||||
}
|
||||
|
@ -139,15 +140,45 @@ declare stderr
|
|||
assert_output "127.0.0.1:8080"
|
||||
}
|
||||
|
||||
@test "${FILE} cscli config backup" {
|
||||
@test "${FILE} cscli config backup / restore" {
|
||||
# test that we need a valid path
|
||||
# disabled because in CI, the empty string is not passed as a parameter
|
||||
## run -1 --separate-stderr cscli config backup ""
|
||||
## run -0 echo "${stderr}"
|
||||
## assert_output --partial "Failed to backup configurations: directory path can't be empty"
|
||||
|
||||
run -1 --separate-stderr cscli config backup "/dev/null/blah"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "Failed to backup configurations: while creating /dev/null/blah: mkdir /dev/null/blah: not a directory"
|
||||
|
||||
# pick a dirpath
|
||||
backupdir=$(TMPDIR="${BATS_TEST_TMPDIR}" mktemp -u)
|
||||
|
||||
# succeed the first time
|
||||
run -0 cscli config backup "${backupdir}"
|
||||
assert_output --partial "Starting configuration backup"
|
||||
run -1 --separate-stderr cscli config backup "${backupdir}"
|
||||
|
||||
# don't overwrite an existing backup
|
||||
run -1 --separate-stderr cscli config backup "${backupdir}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "Failed to backup configurations"
|
||||
assert_output --partial "file exists"
|
||||
|
||||
SIMULATION_YAML="$(config_yq '.config_paths.simulation_path')"
|
||||
|
||||
# restore
|
||||
rm "${SIMULATION_YAML}"
|
||||
run -0 cscli config restore "${backupdir}"
|
||||
assert_file_exist "${SIMULATION_YAML}"
|
||||
|
||||
# cleanup
|
||||
rm -rf -- "${backupdir:?}"
|
||||
|
||||
# backup: detect missing files
|
||||
rm "${SIMULATION_YAML}"
|
||||
run -1 --separate-stderr cscli config backup "${backupdir}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --regexp "Failed to backup configurations: failed copy .* to .*: stat .*: no such file or directory"
|
||||
rm -rf -- "${backupdir:?}"
|
||||
}
|
||||
|
||||
|
@ -244,12 +275,14 @@ declare stderr
|
|||
assert_output --partial "# bash completion for cscli"
|
||||
run -0 cscli completion zsh
|
||||
assert_output --partial "# zsh completion for cscli"
|
||||
run -0 cscli completion powershell
|
||||
assert_output --partial "# powershell completion for cscli"
|
||||
run -0 cscli completion fish
|
||||
assert_output --partial "# fish completion for cscli"
|
||||
|
||||
rm "${CONFIG_YAML}"
|
||||
run -0 cscli completion bash
|
||||
assert_output --partial "# bash completion for cscli"
|
||||
run -0 cscli completion zsh
|
||||
assert_output --partial "# zsh completion for cscli"
|
||||
}
|
||||
|
||||
@test "${FILE} cscli hub list" {
|
||||
|
|
57
tests/bats/01_crowdsec.bats
Normal file
57
tests/bats/01_crowdsec.bats
Normal file
|
@ -0,0 +1,57 @@
|
|||
#!/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"
|
||||
./instance-data load
|
||||
}
|
||||
|
||||
teardown() {
|
||||
./instance-crowdsec stop
|
||||
}
|
||||
|
||||
# to silence shellcheck
|
||||
declare stderr
|
||||
|
||||
#----------
|
||||
|
||||
@test "${FILE} crowdsec (usage)" {
|
||||
run -0 --separate-stderr timeout 2s "${CROWDSEC}" -h
|
||||
run -0 echo "${stderr}"
|
||||
assert_line --regexp "Usage of .*:"
|
||||
|
||||
run -0 --separate-stderr timeout 2s "${CROWDSEC}" --help
|
||||
run -0 echo "${stderr}"
|
||||
assert_line --regexp "Usage of .*:"
|
||||
}
|
||||
|
||||
@test "${FILE} crowdsec (unknown flag)" {
|
||||
run -2 --separate-stderr timeout 2s "${CROWDSEC}" --foobar
|
||||
run -0 echo "${stderr}"
|
||||
assert_line "flag provided but not defined: -foobar"
|
||||
assert_line --regexp "Usage of .*"
|
||||
}
|
||||
|
||||
@test "${FILE} crowdsec (unknown argument)" {
|
||||
run -2 --separate-stderr timeout 2s "${CROWDSEC}" trololo
|
||||
run -0 echo "${stderr}"
|
||||
assert_line "argument provided but not defined: trololo"
|
||||
assert_line --regexp "Usage of .*"
|
||||
}
|
||||
|
||||
@test "${FILE} crowdsec (no api and no agent)" {
|
||||
run -1 --separate-stderr timeout 2s "${CROWDSEC}" -no-api -no-cs
|
||||
run -0 echo "${stderr}"
|
||||
assert_line --partial "You must run at least the API Server or crowdsec"
|
||||
}
|
||||
|
|
@ -34,3 +34,8 @@ declare stderr
|
|||
assert_output --partial "api server init: unable to run local API: unable to init database client: unknown database type 'meh'"
|
||||
}
|
||||
|
||||
@test "${FILE} CS_LAPI_SECRET not strong enough" {
|
||||
CS_LAPI_SECRET=foo run -1 --separate-stderr timeout 2s "${CROWDSEC}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "api server init: unable to run local API: CS_LAPI_SECRET not strong enough"
|
||||
}
|
||||
|
|
|
@ -86,3 +86,35 @@ teardown() {
|
|||
assert_output --partial "api server init: unable to run local API: while loading plugin: plugin at ${PLUGIN_DIR}/notification-http is world writable, world writable plugins are invalid"
|
||||
}
|
||||
|
||||
@test "${FILE} config.yaml: missing .plugin_config section" {
|
||||
yq e 'del(.plugin_config)' -i "${CONFIG_YAML}"
|
||||
yq e '.notifications=["http_default"]' -i "${PROFILES_PATH}"
|
||||
run -1 --separate-stderr timeout 2s "${CROWDSEC}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "api server init: plugins are enabled, but the plugin_config section is missing in the configuration"
|
||||
}
|
||||
|
||||
@test "${FILE} config.yaml: missing config_paths.notification_dir" {
|
||||
yq e 'del(.config_paths.notification_dir)' -i "${CONFIG_YAML}"
|
||||
yq e '.notifications=["http_default"]' -i "${PROFILES_PATH}"
|
||||
run -1 --separate-stderr timeout 2s "${CROWDSEC}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "api server init: plugins are enabled, but config_paths.notification_dir is not defined"
|
||||
}
|
||||
|
||||
@test "${FILE} config.yaml: missing config_paths.plugin_dir" {
|
||||
yq e 'del(.config_paths.plugin_dir)' -i "${CONFIG_YAML}"
|
||||
yq e '.notifications=["http_default"]' -i "${PROFILES_PATH}"
|
||||
run -1 --separate-stderr timeout 2s "${CROWDSEC}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "api server init: plugins are enabled, but config_paths.plugin_dir is not defined"
|
||||
}
|
||||
|
||||
@test "${FILE} unable to run local API: while reading plugin config" {
|
||||
yq e '.config_paths.notification_dir="/this/path/does/not/exist"' -i "${CONFIG_YAML}"
|
||||
yq e '.notifications=["http_default"]' -i "${PROFILES_PATH}"
|
||||
run -1 --separate-stderr timeout 2s "${CROWDSEC}"
|
||||
run -0 echo "${stderr}"
|
||||
assert_output --partial "api server init: unable to run local API: while loading plugin config: open /this/path/does/not/exist: no such file or directory"
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue