diff --git a/pkg/csconfig/crowdsec_service.go b/pkg/csconfig/crowdsec_service.go index c0b8b5a38..839cda617 100644 --- a/pkg/csconfig/crowdsec_service.go +++ b/pkg/csconfig/crowdsec_service.go @@ -1,6 +1,7 @@ package csconfig import ( + "encoding/json" "fmt" "os" "path/filepath" @@ -108,8 +109,9 @@ func (c *Config) LoadCrowdsec() error { c.Crowdsec.OutputRoutinesCount = 1 } - var crowdsecCleanup = []*string{ + crowdsecCleanup := []*string{ &c.Crowdsec.AcquisitionFilePath, + &c.Crowdsec.ConsoleContextPath, } for _, k := range crowdsecCleanup { @@ -131,41 +133,51 @@ func (c *Config) LoadCrowdsec() error { c.Crowdsec.AcquisitionFiles[i] = f } - if err := c.LoadAPIClient(); err != nil { + if err = c.LoadAPIClient(); err != nil { return fmt.Errorf("loading api client: %s", err) } - c.Crowdsec.ContextToSend = make(map[string][]string, 0) - fallback := false - if c.Crowdsec.ConsoleContextPath == "" { - // fallback to default config file - c.Crowdsec.ConsoleContextPath = filepath.Join(c.ConfigPaths.ConfigDir, "console", "context.yaml") - fallback = true - } - - f, err := filepath.Abs(c.Crowdsec.ConsoleContextPath) - if err != nil { - return fmt.Errorf("fail to get absolute path of %s: %s", c.Crowdsec.ConsoleContextPath, err) - } - - c.Crowdsec.ConsoleContextPath = f - yamlFile, err := os.ReadFile(c.Crowdsec.ConsoleContextPath) - if err != nil { - if fallback { - log.Debugf("Default context config file doesn't exist, will not use it") - } else { - return fmt.Errorf("failed to open context file: %s", err) + if c.Crowdsec.ConsoleContextPath != "" { + // if it's provided, it must exist + if _, err = os.Stat(c.Crowdsec.ConsoleContextPath); err != nil { + return fmt.Errorf("while checking console_context_path: %w", err) } } else { - err = yaml.Unmarshal(yamlFile, c.Crowdsec.ContextToSend) - if err != nil { - return fmt.Errorf("unmarshaling labels console config file '%s': %s", c.Crowdsec.ConsoleContextPath, err) - } + c.Crowdsec.ConsoleContextPath = filepath.Join(c.ConfigPaths.ConfigDir, "console", "context.yaml") + } + + c.Crowdsec.ContextToSend, err = buildContextToSend(c) + if err != nil { + return err } return nil } +func buildContextToSend(c *Config) (map[string][]string, error) { + ret := make(map[string][]string, 0) + + log.Tracef("loading console context from %s", c.Crowdsec.ConsoleContextPath) + content, err := os.ReadFile(c.Crowdsec.ConsoleContextPath) + if err != nil && !os.IsNotExist(err) { + return nil, fmt.Errorf("failed to open context file: %s", err) + } + + err = yaml.Unmarshal(content, ret) + if err != nil { + return nil, fmt.Errorf("while loading context from %s: %s", c.Crowdsec.ConsoleContextPath, err) + } + + feedback, err := json.Marshal(ret) + if err != nil { + return nil, fmt.Errorf("marshaling console context: %s", err) + } + + log.Debugf("console context to send: %s", feedback) + + return ret, nil +} + func (c *CrowdsecServiceCfg) DumpContextConfigFile() error { var out []byte var err error diff --git a/test/bats/09_context.bats b/test/bats/09_context.bats new file mode 100644 index 000000000..8b9ddf5a5 --- /dev/null +++ b/test/bats/09_context.bats @@ -0,0 +1,55 @@ +#!/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" + CONFIG_DIR=$(config_get '.config_paths.config_dir') + export CONFIG_DIR + CONTEXT_YAML="$CONFIG_DIR/console/context.yaml" + export CONTEXT_YAML +} + +teardown_file() { + load "../lib/teardown_file.sh" +} + +setup() { + load "../lib/setup.sh" + load "../lib/bats-file/load.bash" + ./instance-data load + config_set '.common.log_media="stdout"' + mkdir -p "$CONFIG_DIR/console" +} + +teardown() { + ./instance-crowdsec stop +} + +#---------- + +@test "attempt to load from default context file, ignore if missing" { + rune -0 rm -f "$CONTEXT_YAML" + rune -0 "$CROWDSEC" -t --trace + assert_stderr --partial "loading console context from $CONTEXT_YAML" +} + +@test "error if context file is explicitly set but does not exist" { + config_set ".crowdsec_service.console_context_path=\"$CONTEXT_YAML\"" + rune -0 rm -f "$CONTEXT_YAML" + rune -1 "$CROWDSEC" -t + assert_stderr --partial "while checking console_context_path: stat $CONTEXT_YAML: no such file or directory" +} + +@test "context file is bad" { + echo "bad yaml" > "$CONTEXT_YAML" + rune -1 "$CROWDSEC" -t + assert_stderr --partial "while loading context from $CONTEXT_YAML: yaml: unmarshal errors" +} + +@test "context file is good" { + echo '{"source_ip":["evt.Parsed.source_ip"]}' > "$CONTEXT_YAML" + rune -0 "$CROWDSEC" -t --debug + assert_stderr --partial 'console context to send: {"source_ip":["evt.Parsed.source_ip"]}' +}