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
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
|
name: lint-windows
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v2
|
uses: golangci/golangci-lint-action@v3
|
||||||
with:
|
with:
|
||||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
# 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.
|
# Optional: golangci-lint command line arguments.
|
||||||
args: --issues-exit-code=0 --timeout 10m
|
args: --issues-exit-code=0 --timeout 10m
|
||||||
only-new-issues: true
|
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
|
name: lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v3
|
||||||
with:
|
with:
|
||||||
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
|
# 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.
|
# Optional: golangci-lint command line arguments.
|
||||||
args: --issues-exit-code=1 --timeout 5m
|
args: --issues-exit-code=1 --timeout 5m
|
||||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
# 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
|
# DEPRECATED by golangi-lint
|
||||||
#
|
#
|
||||||
- golint # [deprecated]: Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
- exhaustivestruct # The owner seems to have abandoned the linter. Replaced by exhaustruct.
|
||||||
- interfacer # [deprecated]: Linter that suggests narrower interface types
|
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
|
||||||
- maligned # [deprecated]: Tool to detect Go structs that would take less memory if their fields were sorted
|
- interfacer # Linter that suggests narrower interface types
|
||||||
- scopelint # [deprecated]: Scopelint checks for unpinned variables in go programs
|
- 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
|
# Enabled
|
||||||
|
@ -96,6 +97,8 @@ linters:
|
||||||
- misspell # Finds commonly misspelled English words in comments
|
- misspell # Finds commonly misspelled English words in comments
|
||||||
- nakedret # Finds naked returns in functions greater than a specified function length
|
- 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.
|
- 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
|
- predeclared # find code that shadows one of Go's predeclared identifiers
|
||||||
- promlinter # Check Prometheus metrics naming via promlint
|
- promlinter # Check Prometheus metrics naming via promlint
|
||||||
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
|
- 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
|
- 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
|
- forbidigo # Forbids identifiers
|
||||||
- tagliatelle # Checks the struct tags.
|
- tagliatelle # Checks the struct tags.
|
||||||
- varnamelen # checks that the length of a variable's name matches its scope
|
- varnamelen # checks that the length of a variable's name matches its scope
|
||||||
- gochecknoglobals # check that no global variables exist
|
- 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
|
- goconst # Finds repeated strings that could be replaced by a constant
|
||||||
- stylecheck # Stylecheck is a replacement for golint
|
- stylecheck # Stylecheck is a replacement for golint
|
||||||
|
|
||||||
|
@ -228,16 +232,6 @@ issues:
|
||||||
- gosimple
|
- gosimple
|
||||||
text: "S1028: should use .* instead of .*"
|
text: "S1028: should use .* instead of .*"
|
||||||
|
|
||||||
#
|
|
||||||
# deadcode
|
|
||||||
#
|
|
||||||
|
|
||||||
- linters:
|
|
||||||
- deadcode
|
|
||||||
- unused
|
|
||||||
- structcheck
|
|
||||||
text: ".* is unused"
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# ineffassign
|
# ineffassign
|
||||||
#
|
#
|
||||||
|
|
|
@ -103,7 +103,9 @@ func NewCapiCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
cmdCapiRegister.Flags().StringVarP(&outputFile, "file", "f", "", "output file destination")
|
cmdCapiRegister.Flags().StringVarP(&outputFile, "file", "f", "", "output file destination")
|
||||||
cmdCapiRegister.Flags().StringVar(&capiUserPrefix, "schmilblick", "", "set a schmilblick (use in tests only)")
|
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)
|
cmdCapi.AddCommand(cmdCapiRegister)
|
||||||
|
|
||||||
var cmdCapiStatus = &cobra.Command{
|
var cmdCapiStatus = &cobra.Command{
|
||||||
|
@ -131,11 +133,11 @@ func NewCapiCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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)
|
log.Fatalf("Failed to load hub index : %s", err)
|
||||||
}
|
}
|
||||||
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
||||||
|
|
|
@ -21,7 +21,7 @@ func NewCollectionsCmd() *cobra.Command {
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if csConfig.Hub == nil {
|
if csConfig.Hub == nil {
|
||||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
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 {
|
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.Fatalf("Failed to get Hub index : %v", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -60,11 +60,10 @@ func NewCollectionsCmd() *cobra.Command {
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, forceAction, downloadOnly); err != nil {
|
if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, forceAction, downloadOnly); err != nil {
|
||||||
if ignoreError {
|
if !ignoreError {
|
||||||
log.Errorf("Error while installing '%s': %s", name, err)
|
|
||||||
} else {
|
|
||||||
log.Fatalf("Error while installing '%s': %s", name, err)
|
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 {
|
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 {
|
for _, name := range args {
|
||||||
|
|
|
@ -47,13 +47,13 @@ func backupConfigToDirectory(dirPath string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = os.Mkdir(dirPath, 0700); err != nil {
|
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 != "" {
|
if csConfig.ConfigPaths.SimulationFilePath != "" {
|
||||||
backupSimulation := filepath.Join(dirPath, "simulation.yaml")
|
backupSimulation := filepath.Join(dirPath, "simulation.yaml")
|
||||||
if err = types.CopyFile(csConfig.ConfigPaths.SimulationFilePath, backupSimulation); err != nil {
|
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)
|
log.Infof("Saved simulation to %s", backupSimulation)
|
||||||
}
|
}
|
||||||
|
@ -437,11 +437,11 @@ func NewConfigCmd() *cobra.Command {
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var err error
|
var err error
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.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 {
|
if err = backupConfigToDirectory(args[0]); err != nil {
|
||||||
log.Fatalf("Failed to backup configurations: %s", err)
|
log.Fatalf("Failed to backup configurations: %s", err)
|
||||||
|
@ -466,11 +466,11 @@ func NewConfigCmd() *cobra.Command {
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
var err error
|
var err error
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err = cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.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 {
|
if err := restoreConfigFromDirectory(args[0]); err != nil {
|
||||||
log.Fatalf("failed restoring configurations from %s : %s", args[0], err)
|
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 {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
||||||
log.Fatalf("Failed to load hub index : %s", err)
|
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()
|
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) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.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
|
//use LocalSync to get warnings about tainted / outdated items
|
||||||
_, warn := cwhub.LocalSync(csConfig.Hub)
|
_, 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) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
|
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
|
||||||
log.Fatalf("Failed to get Hub index : %v", err)
|
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) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.Fatalf("Failed to get Hub index : %v", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Upgrading collections")
|
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)
|
log.Fatalf("parsing api url ('%s'): %s", apiurl, err)
|
||||||
}
|
}
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.Fatalf("Failed to load hub index : %s", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
scenarios, err := cwhub.GetInstalledScenariosAsString()
|
||||||
if err != nil {
|
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")
|
rootCmd.PersistentFlags().StringVar(&cwhub.HubBranch, "branch", "", "Override hub branch on github")
|
||||||
if err := rootCmd.PersistentFlags().MarkHidden("branch"); err != nil {
|
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" {
|
if len(os.Args) > 1 && os.Args[1] != "completion" && os.Args[1] != "version" && os.Args[1] != "help" {
|
||||||
|
|
|
@ -5,24 +5,19 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// ReloadMessage returns a description of the task required to reload
|
||||||
ReloadMessageFormat = `Run '%s' for the new configuration to be effective.`
|
// the crowdsec configuration, according to the operating system.
|
||||||
ReloadCmdLinux = `sudo systemctl reload crowdsec`
|
|
||||||
ReloadCmdFreebsd = `sudo service crowdsec reload`
|
|
||||||
)
|
|
||||||
|
|
||||||
func ReloadMessage() string {
|
func ReloadMessage() string {
|
||||||
|
var msg string
|
||||||
var reloadCmd string
|
|
||||||
|
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
return "Please restart the crowdsec service for the new configuration to be effective."
|
msg = "Please restart the crowdsec service"
|
||||||
case "freebsd":
|
case "freebsd":
|
||||||
reloadCmd = ReloadCmdFreebsd
|
msg = `Run 'sudo service crowdsec reload'`
|
||||||
default:
|
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,
|
DisableAutoGenTag: true,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if csConfig.Hub == nil {
|
if csConfig.Hub == nil {
|
||||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
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 {
|
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.Fatalf("Failed to get Hub index : %v", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -24,7 +24,7 @@ func NewPostOverflowsCmd() *cobra.Command {
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if csConfig.Hub == nil {
|
if csConfig.Hub == nil {
|
||||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
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 {
|
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.Fatalf("Failed to get Hub index : %v", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,7 +27,7 @@ cscli scenarios remove crowdsecurity/ssh-bf
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if csConfig.Hub == nil {
|
if csConfig.Hub == nil {
|
||||||
return fmt.Errorf("you must configure cli before interacting with hub")
|
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 {
|
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)
|
log.Fatalf("Failed to get Hub index : %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,11 +134,11 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
|
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.Fatalf("Failed to get Hub index : %v", err)
|
||||||
log.Infoln("Run 'sudo cscli hub update' to get the hub index")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
|
@ -153,7 +153,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
||||||
}
|
}
|
||||||
isExcluded := inSlice(scenario, csConfig.Cscli.SimulationConfig.Exclusions)
|
isExcluded := inSlice(scenario, csConfig.Cscli.SimulationConfig.Exclusions)
|
||||||
if *csConfig.Cscli.SimulationConfig.Simulation && !isExcluded {
|
if *csConfig.Cscli.SimulationConfig.Simulation && !isExcluded {
|
||||||
log.Warningf("global simulation is already enabled")
|
log.Warning("global simulation is already enabled")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
if !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||||
|
@ -162,13 +162,13 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
||||||
}
|
}
|
||||||
if *csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
if *csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||||
if err := removeFromExclusion(scenario); err != nil {
|
if err := removeFromExclusion(scenario); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Printf("simulation enabled for '%s'", scenario)
|
log.Printf("simulation enabled for '%s'", scenario)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := addToExclusion(scenario); err != nil {
|
if err := addToExclusion(scenario); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Printf("simulation mode for '%s' enabled", scenario)
|
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 !*csConfig.Cscli.SimulationConfig.Simulation && isExcluded {
|
||||||
if err := removeFromExclusion(scenario); err != nil {
|
if err := removeFromExclusion(scenario); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Printf("simulation mode for '%s' disabled", scenario)
|
log.Printf("simulation mode for '%s' disabled", scenario)
|
||||||
continue
|
continue
|
||||||
|
@ -212,7 +212,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := addToExclusion(scenario); err != nil {
|
if err := addToExclusion(scenario); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
log.Printf("simulation mode for '%s' disabled", scenario)
|
log.Printf("simulation mode for '%s' disabled", scenario)
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ cscli simulation disable crowdsecurity/ssh-bf`,
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if err := simulationStatus(); err != nil {
|
if err := simulationStatus(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
PersistentPostRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ func indexOf(s string, slice []string) int {
|
||||||
|
|
||||||
func LoadHub() error {
|
func LoadHub() error {
|
||||||
if err := csConfig.LoadHub(); err != nil {
|
if err := csConfig.LoadHub(); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
if csConfig.Hub == nil {
|
if csConfig.Hub == nil {
|
||||||
return fmt.Errorf("unable to load hub")
|
return fmt.Errorf("unable to load hub")
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/apiserver"
|
"github.com/crowdsecurity/crowdsec/pkg/apiserver"
|
||||||
|
@ -21,17 +20,17 @@ func initAPIServer(cConfig *csconfig.Config) (*apiserver.APIServer, error) {
|
||||||
log.Info("initiating plugin broker")
|
log.Info("initiating plugin broker")
|
||||||
//On windows, the plugins are always run as medium-integrity processes, so we don't care about plugin_config
|
//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" {
|
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 == "" {
|
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 == "" {
|
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)
|
err = pluginBroker.Init(cConfig.PluginConfig, cConfig.API.Server.Profiles, cConfig.ConfigPaths)
|
||||||
if err != nil {
|
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")
|
log.Info("initiated plugin broker")
|
||||||
apiServer.AttachPluginBroker(&pluginBroker)
|
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"
|
_ "net/http/pprof"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/confluentinc/bincover"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
"github.com/crowdsecurity/crowdsec/pkg/acquisition"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||||
|
@ -196,7 +197,6 @@ func (f *Flags) Parse() {
|
||||||
|
|
||||||
// LoadConfig returns a configuration parsed from configuration file
|
// LoadConfig returns a configuration parsed from configuration file
|
||||||
func LoadConfig(cConfig *csconfig.Config) error {
|
func LoadConfig(cConfig *csconfig.Config) error {
|
||||||
|
|
||||||
if dumpFolder != "" {
|
if dumpFolder != "" {
|
||||||
parser.ParseDump = true
|
parser.ParseDump = true
|
||||||
parser.DumpFolder = dumpFolder
|
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) {
|
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 {
|
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 {
|
if flags.DebugLevel {
|
||||||
|
@ -260,8 +260,26 @@ func LoadConfig(cConfig *csconfig.Config) error {
|
||||||
return nil
|
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")
|
defer types.CatchPanic("crowdsec/main")
|
||||||
|
|
||||||
log.Debugf("os.Args: %v", os.Args)
|
log.Debugf("os.Args: %v", os.Args)
|
||||||
|
@ -269,9 +287,25 @@ func main() {
|
||||||
// Handle command line arguments
|
// Handle command line arguments
|
||||||
flags = &Flags{}
|
flags = &Flags{}
|
||||||
flags.Parse()
|
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 {
|
if flags.PrintVersion {
|
||||||
cwversion.Show()
|
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 (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/confluentinc/bincover"
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
@ -14,7 +13,7 @@ import (
|
||||||
"github.com/sirupsen/logrus/hooks/writer"
|
"github.com/sirupsen/logrus/hooks/writer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartRunSvc() {
|
func StartRunSvc() error {
|
||||||
var (
|
var (
|
||||||
cConfig *csconfig.Config
|
cConfig *csconfig.Config
|
||||||
err error
|
err error
|
||||||
|
@ -30,10 +29,10 @@ func StartRunSvc() {
|
||||||
|
|
||||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
if err := LoadConfig(cConfig); err != nil {
|
if err := LoadConfig(cConfig); err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
// Configure logging
|
// Configure logging
|
||||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
||||||
|
@ -51,18 +50,5 @@ func StartRunSvc() {
|
||||||
if cConfig.Prometheus != nil {
|
if cConfig.Prometheus != nil {
|
||||||
go registerPrometheus(cConfig.Prometheus)
|
go registerPrometheus(cConfig.Prometheus)
|
||||||
}
|
}
|
||||||
|
return Serve(cConfig)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +1,59 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/confluentinc/bincover"
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
"github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/sirupsen/logrus/hooks/writer"
|
"github.com/sirupsen/logrus/hooks/writer"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartRunSvc() {
|
func StartRunSvc() error {
|
||||||
|
|
||||||
const svcName = "CrowdSec"
|
const svcName = "CrowdSec"
|
||||||
const svcDescription = "Crowdsec IPS/IDS"
|
const svcDescription = "Crowdsec IPS/IDS"
|
||||||
|
|
||||||
isRunninginService, err := svc.IsWindowsService()
|
isRunninginService, err := svc.IsWindowsService()
|
||||||
if err != nil {
|
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 {
|
if isRunninginService {
|
||||||
runService(svcName)
|
return runService(svcName)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.WinSvc == "Install" {
|
if flags.WinSvc == "Install" {
|
||||||
err = installService(svcName, svcDescription)
|
err = installService(svcName, svcDescription)
|
||||||
if err != nil {
|
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" {
|
} else if flags.WinSvc == "Remove" {
|
||||||
err = removeService(svcName)
|
err = removeService(svcName)
|
||||||
if err != nil {
|
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" {
|
} else if flags.WinSvc == "Start" {
|
||||||
err = startService(svcName)
|
err = startService(svcName)
|
||||||
if err != nil {
|
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" {
|
} else if flags.WinSvc == "Stop" {
|
||||||
err = controlService(svcName, svc.Stop, svc.Stopped)
|
err = controlService(svcName, svc.Stop, svc.Stopped)
|
||||||
if err != nil {
|
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 == "" {
|
} else if flags.WinSvc == "" {
|
||||||
WindowsRun()
|
return WindowsRun()
|
||||||
} else {
|
} 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() error {
|
||||||
|
|
||||||
func WindowsRun() {
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
cConfig *csconfig.Config
|
cConfig *csconfig.Config
|
||||||
err error
|
err error
|
||||||
|
@ -71,15 +69,15 @@ func WindowsRun() {
|
||||||
|
|
||||||
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
if err := LoadConfig(cConfig); err != nil {
|
if err := LoadConfig(cConfig); err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
// Configure logging
|
// Configure logging
|
||||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
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 {
|
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())
|
log.Infof("Crowdsec %s", cwversion.VersionStr())
|
||||||
|
@ -92,18 +90,5 @@ func WindowsRun() {
|
||||||
if cConfig.Prometheus != nil {
|
if cConfig.Prometheus != nil {
|
||||||
go registerPrometheus(cConfig.Prometheus)
|
go registerPrometheus(cConfig.Prometheus)
|
||||||
}
|
}
|
||||||
|
return Serve(cConfig)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -18,7 +17,7 @@ import (
|
||||||
//"github.com/sevlyar/go-daemon"
|
//"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 {
|
func debugHandler(sig os.Signal, cConfig *csconfig.Config) error {
|
||||||
var tmpFile string
|
var tmpFile string
|
||||||
var err error
|
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)
|
cConfig, err = csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := LoadConfig(cConfig); err != nil {
|
if err := LoadConfig(cConfig); err != nil {
|
||||||
log.Fatalf(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
// Configure logging
|
// Configure logging
|
||||||
if err = types.SetDefaultLoggerConfig(cConfig.Common.LogMedia, cConfig.Common.LogDir, *cConfig.Common.LogLevel,
|
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 {
|
cConfig.Common.LogMaxSize, cConfig.Common.LogMaxFiles, cConfig.Common.LogMaxAge, cConfig.Common.CompressLogs); err != nil {
|
||||||
log.Fatal(err.Error())
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cConfig.DisableAPI {
|
if !cConfig.DisableAPI {
|
||||||
apiServer, err := initAPIServer(cConfig)
|
apiServer, err := initAPIServer(cConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to init api server: %s", err)
|
return errors.Wrap(err, "unable to init api server")
|
||||||
}
|
}
|
||||||
|
|
||||||
serveAPIServer(apiServer)
|
serveAPIServer(apiServer)
|
||||||
|
@ -77,7 +76,7 @@ func reloadHandler(sig os.Signal, cConfig *csconfig.Config) error {
|
||||||
if !cConfig.DisableAgent {
|
if !cConfig.DisableAgent {
|
||||||
csParsers, err := initCrowdsec(cConfig)
|
csParsers, err := initCrowdsec(cConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to init crowdsec: %s", err)
|
return errors.Wrap(err, "unable to init crowdsec")
|
||||||
}
|
}
|
||||||
//restore bucket state
|
//restore bucket state
|
||||||
if tmpFile != "" {
|
if tmpFile != "" {
|
||||||
|
@ -164,20 +163,18 @@ func shutdownCrowdsec() error {
|
||||||
func shutdown(sig os.Signal, cConfig *csconfig.Config) error {
|
func shutdown(sig os.Signal, cConfig *csconfig.Config) error {
|
||||||
if !cConfig.DisableAgent {
|
if !cConfig.DisableAgent {
|
||||||
if err := shutdownCrowdsec(); err != nil {
|
if err := shutdownCrowdsec(); err != nil {
|
||||||
log.Errorf("Failed to shut down crowdsec: %s", err)
|
return errors.Wrap(err, "Failed to shut down crowdsec")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !cConfig.DisableAPI {
|
if !cConfig.DisableAPI {
|
||||||
if err := shutdownAPI(); err != nil {
|
if err := shutdownAPI(); err != nil {
|
||||||
log.Errorf("Failed to shut down api routines: %s", err)
|
return errors.Wrap(err, "Failed to shut down api routines")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleSignals(cConfig *csconfig.Config) int {
|
func HandleSignals(cConfig *csconfig.Config) error {
|
||||||
signalChan := make(chan os.Signal, 1)
|
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
|
//We add os.Interrupt mostly to ease windows dev, it allows to simulate a clean shutdown when running in the console
|
||||||
signal.Notify(signalChan,
|
signal.Notify(signalChan,
|
||||||
|
@ -185,9 +182,10 @@ func HandleSignals(cConfig *csconfig.Config) int {
|
||||||
syscall.SIGTERM,
|
syscall.SIGTERM,
|
||||||
os.Interrupt)
|
os.Interrupt)
|
||||||
|
|
||||||
exitChan := make(chan int)
|
exitChan := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
defer types.CatchPanic("crowdsec/HandleSignals")
|
defer types.CatchPanic("crowdsec/HandleSignals")
|
||||||
|
Loop:
|
||||||
for {
|
for {
|
||||||
s := <-signalChan
|
s := <-signalChan
|
||||||
switch s {
|
switch s {
|
||||||
|
@ -195,28 +193,33 @@ func HandleSignals(cConfig *csconfig.Config) int {
|
||||||
case syscall.SIGHUP:
|
case syscall.SIGHUP:
|
||||||
log.Warningf("SIGHUP received, reloading")
|
log.Warningf("SIGHUP received, reloading")
|
||||||
if err := shutdown(s, cConfig); err != nil {
|
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 {
|
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
|
// ctrl+C, kill -SIGINT XXXX, kill -SIGTERM XXXX
|
||||||
case os.Interrupt, syscall.SIGTERM:
|
case os.Interrupt, syscall.SIGTERM:
|
||||||
log.Warningf("SIGTERM received, shutting down")
|
log.Warningf("SIGTERM received, shutting down")
|
||||||
if err := shutdown(s, cConfig); err != nil {
|
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
|
err := <-exitChan
|
||||||
|
if err == nil {
|
||||||
log.Warningf("Crowdsec service shutting down")
|
log.Warningf("Crowdsec service shutting down")
|
||||||
return code
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Serve(cConfig *csconfig.Config) (int, error) {
|
func Serve(cConfig *csconfig.Config) error {
|
||||||
acquisTomb = tomb.Tomb{}
|
acquisTomb = tomb.Tomb{}
|
||||||
parsersTomb = tomb.Tomb{}
|
parsersTomb = tomb.Tomb{}
|
||||||
bucketsTomb = tomb.Tomb{}
|
bucketsTomb = tomb.Tomb{}
|
||||||
|
@ -227,7 +230,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
||||||
if !cConfig.DisableAPI {
|
if !cConfig.DisableAPI {
|
||||||
apiServer, err := initAPIServer(cConfig)
|
apiServer, err := initAPIServer(cConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 1, errors.Wrap(err, "api server init")
|
return errors.Wrap(err, "api server init")
|
||||||
}
|
}
|
||||||
if !flags.TestMode {
|
if !flags.TestMode {
|
||||||
serveAPIServer(apiServer)
|
serveAPIServer(apiServer)
|
||||||
|
@ -237,7 +240,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
||||||
if !cConfig.DisableAgent {
|
if !cConfig.DisableAgent {
|
||||||
csParsers, err := initCrowdsec(cConfig)
|
csParsers, err := initCrowdsec(cConfig)
|
||||||
if err != nil {
|
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 it's just linting, we're done */
|
||||||
if !flags.TestMode {
|
if !flags.TestMode {
|
||||||
|
@ -256,7 +259,7 @@ func Serve(cConfig *csconfig.Config) (int, error) {
|
||||||
log.Errorf("Failed to notify(sent: %v): %v", sent, err)
|
log.Errorf("Failed to notify(sent: %v): %v", sent, err)
|
||||||
}
|
}
|
||||||
/*wait for signals*/
|
/*wait for signals*/
|
||||||
return HandleSignals(cConfig), nil
|
return HandleSignals(cConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sys/windows/svc"
|
"golang.org/x/sys/windows/svc"
|
||||||
)
|
)
|
||||||
|
@ -61,27 +62,29 @@ loop:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func runService(name string) {
|
func runService(name string) error {
|
||||||
cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
|
||||||
if err != nil {
|
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}
|
winsvc := crowdsec_winservice{config: cConfig}
|
||||||
|
|
||||||
err = svc.Run(name, &winsvc)
|
if err := svc.Run(name, &winsvc); err != nil {
|
||||||
if err != nil {
|
return errors.Wrapf(err, "%s service failed", name)
|
||||||
log.Errorf("%s service failed: %s", name, err)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("%s service stopped", name)
|
log.Infof("%s service stopped", name)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -493,6 +493,7 @@ READLOOP:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint: structcheck,unused
|
||||||
type MockSourceByDSN struct {
|
type MockSourceByDSN struct {
|
||||||
configuration.DataSourceCommonCfg `yaml:",inline"`
|
configuration.DataSourceCommonCfg `yaml:",inline"`
|
||||||
Toto string `yaml:"toto"`
|
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 {
|
if len(args) == 2 && len(args[1]) != 0 {
|
||||||
params, err := url.ParseQuery(args[1])
|
params, err := url.ParseQuery(args[1])
|
||||||
if err != nil {
|
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 {
|
for key, value := range params {
|
||||||
if key != "log_level" {
|
if key != "log_level" {
|
||||||
return fmt.Errorf("unsupported key %s in file DSN", key)
|
return fmt.Errorf("unsupported key %s in file DSN", key)
|
||||||
}
|
}
|
||||||
if len(value) != 1 {
|
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])
|
lvl, err := log.ParseLevel(value[0])
|
||||||
if err != nil {
|
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 := f.logger.WithField("tail", tail.Filename)
|
||||||
logger.Debugf("-> Starting tail of %s", tail.Filename)
|
logger.Debugf("-> Starting tail of %s", tail.Filename)
|
||||||
for {
|
for {
|
||||||
l := types.Line{}
|
|
||||||
select {
|
select {
|
||||||
case <-t.Dying():
|
case <-t.Dying():
|
||||||
logger.Infof("File datasource %s stopping", tail.Filename)
|
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
|
continue
|
||||||
}
|
}
|
||||||
linesRead.With(prometheus.Labels{"source": tail.Filename}).Inc()
|
linesRead.With(prometheus.Labels{"source": tail.Filename}).Inc()
|
||||||
l.Raw = trimLine(line.Text)
|
l := types.Line{
|
||||||
l.Labels = f.config.Labels
|
Raw: trimLine(line.Text),
|
||||||
l.Time = line.Time
|
Labels: f.config.Labels,
|
||||||
l.Src = tail.Filename
|
Time: line.Time,
|
||||||
l.Process = true
|
Src: tail.Filename,
|
||||||
l.Module = f.GetName()
|
Process: true,
|
||||||
|
Module: f.GetName(),
|
||||||
|
}
|
||||||
//we're tailing, it must be real time logs
|
//we're tailing, it must be real time logs
|
||||||
logger.Debugf("pushing %+v", l)
|
logger.Debugf("pushing %+v", l)
|
||||||
if !f.config.UseTimeMachine {
|
|
||||||
out <- types.Event{Line: l, Process: true, Type: types.LOG, ExpectMode: leaky.LIVE}
|
expectMode := leaky.LIVE
|
||||||
} else {
|
if f.config.UseTimeMachine {
|
||||||
out <- types.Event{Line: l, Process: true, Type: types.LOG, ExpectMode: leaky.TIMEMACHINE}
|
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() == "" {
|
if scanner.Text() == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logger.Debugf("line %s", scanner.Text())
|
l := types.Line{
|
||||||
l := types.Line{}
|
Raw: scanner.Text(),
|
||||||
l.Raw = scanner.Text()
|
Time: time.Now().UTC(),
|
||||||
l.Time = time.Now().UTC()
|
Src: filename,
|
||||||
l.Src = filename
|
Labels: f.config.Labels,
|
||||||
l.Labels = f.config.Labels
|
Process: true,
|
||||||
l.Process = true
|
Module: f.GetName(),
|
||||||
l.Module = f.GetName()
|
}
|
||||||
|
logger.Debugf("line %s", l.Raw)
|
||||||
linesRead.With(prometheus.Labels{"source": filename}).Inc()
|
linesRead.With(prometheus.Labels{"source": filename}).Inc()
|
||||||
|
|
||||||
//we're reading logs at once, it must be time-machine buckets
|
//we're reading logs at once, it must be time-machine buckets
|
||||||
|
|
|
@ -37,7 +37,7 @@ func TestAlertsListAsMachine(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
@ -240,7 +240,7 @@ func TestAlertsGetAsMachine(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
@ -431,7 +431,7 @@ func TestAlertsCreateAsMachine(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
@ -475,7 +475,7 @@ func TestAlertsDeleteAsMachine(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
|
@ -57,7 +57,7 @@ func TestWatcherAuth(t *testing.T) {
|
||||||
client, err := NewClient(mycfg)
|
client, err := NewClient(mycfg)
|
||||||
|
|
||||||
if err != nil {
|
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{
|
_, err = client.Auth.AuthenticateWatcher(context.Background(), models.WatcherAuthRequest{
|
||||||
|
@ -81,7 +81,7 @@ func TestWatcherAuth(t *testing.T) {
|
||||||
client, err = NewClient(mycfg)
|
client, err = NewClient(mycfg)
|
||||||
|
|
||||||
if err != nil {
|
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{
|
_, err = client.Auth.AuthenticateWatcher(context.Background(), models.WatcherAuthRequest{
|
||||||
|
@ -171,7 +171,7 @@ func TestWatcherUnregister(t *testing.T) {
|
||||||
client, err := NewClient(mycfg)
|
client, err := NewClient(mycfg)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
_, err = client.Auth.UnregisterWatcher(context.Background())
|
_, err = client.Auth.UnregisterWatcher(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -225,7 +225,7 @@ func TestWatcherEnroll(t *testing.T) {
|
||||||
client, err := NewClient(mycfg)
|
client, err := NewClient(mycfg)
|
||||||
|
|
||||||
if err != nil {
|
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)
|
_, 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())
|
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
alert := DecisionsListOpts{IPEquals: new(string)}
|
alert := DecisionsListOpts{IPEquals: new(string)}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestDecisionsList(t *testing.T) {
|
||||||
|
|
||||||
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tduration := "3h59m55.756182786s"
|
tduration := "3h59m55.756182786s"
|
||||||
|
@ -77,7 +77,7 @@ func TestDecisionsList(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(*decisions, *expected) {
|
if !reflect.DeepEqual(*decisions, *expected) {
|
||||||
t.Fatalf("returned %+v, want %+v", resp, 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())
|
newcli, err := NewDefaultClient(apiURL, "v1", "toto", auth.Client())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tduration := "3h59m55.756182786s"
|
tduration := "3h59m55.756182786s"
|
||||||
|
@ -168,7 +168,7 @@ func TestDecisionsStream(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(*decisions, *expected) {
|
if !reflect.DeepEqual(*decisions, *expected) {
|
||||||
t.Fatalf("returned %+v, want %+v", resp, expected)
|
t.Fatalf("returned %+v, want %+v", resp, expected)
|
||||||
|
@ -220,7 +220,7 @@ func TestDeleteDecisions(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("new api client: %s", err.Error())
|
log.Fatalf("new api client: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
filters := DecisionsDeleteOpts{IPEquals: new(string)}
|
filters := DecisionsDeleteOpts{IPEquals: new(string)}
|
||||||
|
|
|
@ -18,7 +18,7 @@ func TestAPIKey(t *testing.T) {
|
||||||
|
|
||||||
APIKey, err := CreateTestBouncer(config.API.Server.DbConfig)
|
APIKey, err := CreateTestBouncer(config.API.Server.DbConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%s", err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
// Login with empty token
|
// Login with empty token
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
|
@ -276,11 +276,11 @@ func (s *APIServer) Run() error {
|
||||||
go func() {
|
go func() {
|
||||||
if s.TLS != nil && s.TLS.CertFilePath != "" && s.TLS.KeyFilePath != "" {
|
if s.TLS != nil && s.TLS.CertFilePath != "" && s.TLS.KeyFilePath != "" {
|
||||||
if err := s.httpServer.ListenAndServeTLS(s.TLS.CertFilePath, s.TLS.KeyFilePath); err != nil {
|
if err := s.httpServer.ListenAndServeTLS(s.TLS.CertFilePath, s.TLS.KeyFilePath); err != nil {
|
||||||
log.Fatalf(err.Error())
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := s.httpServer.ListenAndServe(); err != http.ErrServerClosed {
|
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
|
// Create machine
|
||||||
b, err := json.Marshal(MachineTest)
|
b, err := json.Marshal(MachineTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to marshal MachineTest")
|
log.Fatal("unable to marshal MachineTest")
|
||||||
}
|
}
|
||||||
body := string(b)
|
body := string(b)
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func TestCreateMachineWithForwardedFor(t *testing.T) {
|
||||||
// Create machine
|
// Create machine
|
||||||
b, err := json.Marshal(MachineTest)
|
b, err := json.Marshal(MachineTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to marshal MachineTest")
|
log.Fatal("unable to marshal MachineTest")
|
||||||
}
|
}
|
||||||
body := string(b)
|
body := string(b)
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ func TestCreateMachineWithForwardedForNoConfig(t *testing.T) {
|
||||||
// Create machine
|
// Create machine
|
||||||
b, err := json.Marshal(MachineTest)
|
b, err := json.Marshal(MachineTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to marshal MachineTest")
|
log.Fatal("unable to marshal MachineTest")
|
||||||
}
|
}
|
||||||
body := string(b)
|
body := string(b)
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ func TestCreateMachineWithoutForwardedFor(t *testing.T) {
|
||||||
// Create machine
|
// Create machine
|
||||||
b, err := json.Marshal(MachineTest)
|
b, err := json.Marshal(MachineTest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to marshal MachineTest")
|
log.Fatal("unable to marshal MachineTest")
|
||||||
}
|
}
|
||||||
body := string(b)
|
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) {
|
func NewJWT(dbClient *database.Client) (*JWT, error) {
|
||||||
// Get secret from environment variable "SECRET"
|
// Get secret from environment variable "SECRET"
|
||||||
var (
|
var (
|
||||||
secret []byte
|
secret []byte
|
||||||
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
// Please be aware that brute force HS256 is possible.
|
// Please be aware that brute force HS256 is possible.
|
||||||
// PLEASE choose a STRONG secret
|
// PLEASE choose a STRONG secret
|
||||||
secret_string := os.Getenv("CS_LAPI_SECRET")
|
secretString := os.Getenv("CS_LAPI_SECRET")
|
||||||
if secret_string == "" {
|
secret = []byte(secretString)
|
||||||
secret = make([]byte, 64)
|
|
||||||
if n, err := rand.Read(secret); err != nil {
|
switch l := len(secret); {
|
||||||
log.Fatalf("unable to generate a new random seed for JWT generation")
|
case l == 0:
|
||||||
} else {
|
secret, err = randomSecret()
|
||||||
if n != 64 {
|
if err != nil {
|
||||||
log.Fatalf("not enough entropy at random seed generation for JWT generation")
|
return &JWT{}, err
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
secret = []byte(secret_string)
|
|
||||||
if len(secret) < 64 {
|
|
||||||
log.Fatalf("secret not strong enough")
|
|
||||||
}
|
}
|
||||||
|
case l < 64:
|
||||||
|
return &JWT{}, errors.New("CS_LAPI_SECRET not strong enough")
|
||||||
}
|
}
|
||||||
|
|
||||||
jwtMiddleware := &JWT{
|
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())
|
return fmt.Errorf("loading api client: %s", err.Error())
|
||||||
}
|
}
|
||||||
if err := c.LoadHub(); err != nil {
|
if err := c.LoadHub(); err != nil {
|
||||||
return fmt.Errorf("loading hub: %s", err)
|
return errors.Wrap(err, "while loading hub")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,22 +12,22 @@ import (
|
||||||
func TestLoadHub(t *testing.T) {
|
func TestLoadHub(t *testing.T) {
|
||||||
hubFullPath, err := filepath.Abs("./hub")
|
hubFullPath, err := filepath.Abs("./hub")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataFullPath, err := filepath.Abs("./data")
|
dataFullPath, err := filepath.Abs("./data")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
configDirFullPath, err := filepath.Abs("./tests")
|
configDirFullPath, err := filepath.Abs("./tests")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hubIndexFileFullPath, err := filepath.Abs("./hub/.index.json")
|
hubIndexFileFullPath, err := filepath.Abs("./hub/.index.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf(err.Error())
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
|
@ -133,7 +133,6 @@ func TestGetters(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIndexDownload(t *testing.T) {
|
func TestIndexDownload(t *testing.T) {
|
||||||
|
|
||||||
cfg := test_prepenv()
|
cfg := test_prepenv()
|
||||||
|
|
||||||
err := UpdateHubIdx(cfg.Hub)
|
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
|
only the keys of the expected part are checked against result
|
||||||
*/
|
*/
|
||||||
if len(testSet.Results) == 0 && len(results) == 0 {
|
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")
|
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)
|
clog.Debugf("%s = '%s'", static.TargetByName, value)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clog.Fatalf("unable to process static : unknown tartget")
|
clog.Fatal("unable to process static : unknown target")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ teardown_file() {
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
load "../lib/setup.sh"
|
load "../lib/setup.sh"
|
||||||
|
load "../lib/bats-file/load.bash"
|
||||||
./instance-data load
|
./instance-data load
|
||||||
./instance-crowdsec start
|
./instance-crowdsec start
|
||||||
}
|
}
|
||||||
|
@ -139,15 +140,45 @@ declare stderr
|
||||||
assert_output "127.0.0.1:8080"
|
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)
|
backupdir=$(TMPDIR="${BATS_TEST_TMPDIR}" mktemp -u)
|
||||||
|
|
||||||
|
# succeed the first time
|
||||||
run -0 cscli config backup "${backupdir}"
|
run -0 cscli config backup "${backupdir}"
|
||||||
assert_output --partial "Starting configuration backup"
|
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}"
|
run -0 echo "${stderr}"
|
||||||
assert_output --partial "Failed to backup configurations"
|
assert_output --partial "Failed to backup configurations"
|
||||||
assert_output --partial "file exists"
|
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:?}"
|
rm -rf -- "${backupdir:?}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,12 +275,14 @@ declare stderr
|
||||||
assert_output --partial "# bash completion for cscli"
|
assert_output --partial "# bash completion for cscli"
|
||||||
run -0 cscli completion zsh
|
run -0 cscli completion zsh
|
||||||
assert_output --partial "# zsh completion for cscli"
|
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}"
|
rm "${CONFIG_YAML}"
|
||||||
run -0 cscli completion bash
|
run -0 cscli completion bash
|
||||||
assert_output --partial "# bash completion for cscli"
|
assert_output --partial "# bash completion for cscli"
|
||||||
run -0 cscli completion zsh
|
|
||||||
assert_output --partial "# zsh completion for cscli"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "${FILE} cscli hub list" {
|
@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'"
|
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"
|
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