diff --git a/pkg/acquisition/modules/http/config.go b/pkg/acquisition/modules/http/config.go index dd3a8c0bdc8..3259540bd93 100644 --- a/pkg/acquisition/modules/http/config.go +++ b/pkg/acquisition/modules/http/config.go @@ -10,8 +10,8 @@ import ( "os" "time" + yaml "github.com/goccy/go-yaml" log "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" "github.com/crowdsecurity/crowdsec/pkg/acquisition/configuration" "github.com/crowdsecurity/crowdsec/pkg/metrics" @@ -34,6 +34,23 @@ type Configuration struct { configuration.DataSourceCommonCfg `yaml:",inline"` } +func ConfigurationFromYAML(y []byte) (Configuration, error) { + var cfg Configuration + + if err := yaml.UnmarshalWithOptions(y, &cfg, yaml.Strict()); err != nil { + return cfg, fmt.Errorf("cannot parse: %s", yaml.FormatError(err, false, false)) + } + + cfg.SetDefaults() + + err := cfg.Validate() + if err != nil { + return cfg, err + } + + return cfg, nil +} + type BasicAuthConfig struct { Username string `yaml:"username"` Password string `yaml:"password"` @@ -46,18 +63,24 @@ type TLSConfig struct { CaCert string `yaml:"ca_cert"` } -func (s *Source) UnmarshalConfig(yamlConfig []byte) error { - s.Config = Configuration{} +func (c *Configuration) SetDefaults() { + if c.Mode == "" { + c.Mode = configuration.TAIL_MODE + } - err := yaml.Unmarshal(yamlConfig, &s.Config) - if err != nil { - return fmt.Errorf("cannot parse %s datasource configuration: %w", s.GetName(), err) + if c.Path == "" { + c.Path = "/" } +} - if s.Config.Mode == "" { - s.Config.Mode = configuration.TAIL_MODE +func (s *Source) UnmarshalConfig(yamlConfig []byte) error { + cfg, err := ConfigurationFromYAML(yamlConfig) + if err != nil { + return err } + s.Config = cfg + return nil } @@ -66,10 +89,6 @@ func (c *Configuration) Validate() error { return errors.New("listen_addr or listen_socket is required") } - if c.Path == "" { - c.Path = "/" - } - if c.Path[0] != '/' { return errors.New("path must start with /") } @@ -139,10 +158,6 @@ func (s *Source) Configure(_ context.Context, yamlConfig []byte, logger *log.Ent return err } - if err := s.Config.Validate(); err != nil { - return fmt.Errorf("invalid configuration: %w", err) - } - return nil } @@ -182,4 +197,3 @@ func (c *Configuration) NewTLSConfig() (*tls.Config, error) { return &tlsConfig, nil } - diff --git a/pkg/acquisition/modules/http/http_test.go b/pkg/acquisition/modules/http/http_test.go index 7f26f4f6af7..a8e2b582f49 100644 --- a/pkg/acquisition/modules/http/http_test.go +++ b/pkg/acquisition/modules/http/http_test.go @@ -42,15 +42,15 @@ func TestConfigure(t *testing.T) { }{ { config: ` -foobar: bla`, - expectedErr: "invalid configuration: listen_addr or listen_socket is required", +timeout: 1m`, + expectedErr: "listen_addr or listen_socket is required", }, { config: ` source: http listen_addr: 127.0.0.1:8080 path: wrongpath`, - expectedErr: "invalid configuration: path must start with /", + expectedErr: "path must start with /", }, { config: ` @@ -58,7 +58,7 @@ source: http listen_addr: 127.0.0.1:8080 path: /test auth_type: basic_auth`, - expectedErr: "invalid configuration: basic_auth is selected, but basic_auth is not provided", + expectedErr: "basic_auth is selected, but basic_auth is not provided", }, { config: ` @@ -66,7 +66,7 @@ source: http listen_addr: 127.0.0.1:8080 path: /test auth_type: headers`, - expectedErr: "invalid configuration: headers is selected, but headers is not provided", + expectedErr: "headers is selected, but headers is not provided", }, { config: ` @@ -76,7 +76,7 @@ path: /test auth_type: basic_auth basic_auth: username: 132`, - expectedErr: "invalid configuration: basic_auth is selected, but password is not provided", + expectedErr: "basic_auth is selected, but password is not provided", }, { config: ` @@ -86,7 +86,7 @@ path: /test auth_type: basic_auth basic_auth: password: 132`, - expectedErr: "invalid configuration: basic_auth is selected, but username is not provided", + expectedErr: "basic_auth is selected, but username is not provided", }, { config: ` @@ -95,7 +95,7 @@ listen_addr: 127.0.0.1:8080 path: /test auth_type: headers headers:`, - expectedErr: "invalid configuration: headers is selected, but headers is not provided", + expectedErr: "headers is selected, but headers is not provided", }, { config: ` @@ -103,7 +103,7 @@ source: http listen_addr: 127.0.0.1:8080 path: /test auth_type: toto`, - expectedErr: "invalid configuration: invalid auth_type: must be one of basic_auth, headers, mtls", + expectedErr: "invalid auth_type: must be one of basic_auth, headers, mtls", }, { config: ` @@ -115,7 +115,7 @@ headers: key: value tls: server_key: key`, - expectedErr: "invalid configuration: server_cert is required", + expectedErr: "server_cert is required", }, { config: ` @@ -127,7 +127,7 @@ headers: key: value tls: server_cert: cert`, - expectedErr: "invalid configuration: server_key is required", + expectedErr: "server_key is required", }, { config: ` @@ -138,7 +138,7 @@ auth_type: mtls tls: server_cert: cert server_key: key`, - expectedErr: "invalid configuration: mtls is selected, but ca_cert is not provided", + expectedErr: "mtls is selected, but ca_cert is not provided", }, { config: ` @@ -149,7 +149,7 @@ auth_type: headers headers: key: value max_body_size: 0`, - expectedErr: "invalid configuration: max_body_size must be positive", + expectedErr: "max_body_size must be positive", }, { config: ` @@ -160,7 +160,7 @@ auth_type: headers headers: key: value timeout: toto`, - expectedErr: "cannot parse http datasource configuration: yaml: unmarshal errors:\n line 8: cannot unmarshal !!str `toto` into time.Duration", + expectedErr: `cannot parse: time: invalid duration "toto"`, }, { config: ` @@ -171,7 +171,7 @@ auth_type: headers headers: key: value custom_status_code: 999`, - expectedErr: "invalid configuration: invalid HTTP status code", + expectedErr: "invalid HTTP status code", }, } @@ -199,7 +199,7 @@ source: http listen_addr: 127.0.0.1:8080 path: 15 auth_type: headers`)) - cstest.AssertErrorMessage(t, err, "cannot parse http datasource configuration: yaml: line 4: found a tab character that violates indentation") + cstest.AssertErrorMessage(t, err, "cannot parse: [5:1] found character '\t' that cannot start any token") } func TestGetMode(t *testing.T) {