config.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Package csconfig contains the configuration structures for crowdsec and cscli.
  2. package csconfig
  3. import (
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. log "github.com/sirupsen/logrus"
  8. "gopkg.in/yaml.v2"
  9. "github.com/crowdsecurity/go-cs-lib/csstring"
  10. "github.com/crowdsecurity/go-cs-lib/ptr"
  11. "github.com/crowdsecurity/go-cs-lib/yamlpatch"
  12. )
  13. // defaultConfigDir is the base path to all configuration files, to be overridden in the Makefile */
  14. var defaultConfigDir = "/etc/crowdsec"
  15. // defaultDataDir is the base path to all data files, to be overridden in the Makefile */
  16. var defaultDataDir = "/var/lib/crowdsec/data/"
  17. // Config contains top-level defaults -> overridden by configuration file -> overridden by CLI flags
  18. type Config struct {
  19. //just a path to ourself :p
  20. FilePath *string `yaml:"-"`
  21. Self []byte `yaml:"-"`
  22. Common *CommonCfg `yaml:"common,omitempty"`
  23. Prometheus *PrometheusCfg `yaml:"prometheus,omitempty"`
  24. Crowdsec *CrowdsecServiceCfg `yaml:"crowdsec_service,omitempty"`
  25. Cscli *CscliCfg `yaml:"cscli,omitempty"`
  26. DbConfig *DatabaseCfg `yaml:"db_config,omitempty"`
  27. API *APICfg `yaml:"api,omitempty"`
  28. ConfigPaths *ConfigurationPaths `yaml:"config_paths,omitempty"`
  29. PluginConfig *PluginCfg `yaml:"plugin_config,omitempty"`
  30. DisableAPI bool `yaml:"-"`
  31. DisableAgent bool `yaml:"-"`
  32. Hub *HubCfg `yaml:"-"`
  33. }
  34. func NewConfig(configFile string, disableAgent bool, disableAPI bool, quiet bool) (*Config, string, error) {
  35. patcher := yamlpatch.NewPatcher(configFile, ".local")
  36. patcher.SetQuiet(quiet)
  37. fcontent, err := patcher.MergedPatchContent()
  38. if err != nil {
  39. return nil, "", err
  40. }
  41. configData := csstring.StrictExpand(string(fcontent), os.LookupEnv)
  42. cfg := Config{
  43. FilePath: &configFile,
  44. DisableAgent: disableAgent,
  45. DisableAPI: disableAPI,
  46. }
  47. err = yaml.UnmarshalStrict([]byte(configData), &cfg)
  48. if err != nil {
  49. // this is actually the "merged" yaml
  50. return nil, "", fmt.Errorf("%s: %w", configFile, err)
  51. }
  52. if cfg.Prometheus == nil {
  53. cfg.Prometheus = &PrometheusCfg{}
  54. }
  55. if cfg.Prometheus.ListenAddr == "" {
  56. cfg.Prometheus.ListenAddr = "127.0.0.1"
  57. log.Debugf("prometheus.listen_addr is empty, defaulting to %s", cfg.Prometheus.ListenAddr)
  58. }
  59. if cfg.Prometheus.ListenPort == 0 {
  60. cfg.Prometheus.ListenPort = 6060
  61. log.Debugf("prometheus.listen_port is empty or zero, defaulting to %d", cfg.Prometheus.ListenPort)
  62. }
  63. if err = cfg.loadCommon(); err != nil {
  64. return nil, "", err
  65. }
  66. if err = cfg.loadConfigurationPaths(); err != nil {
  67. return nil, "", err
  68. }
  69. if err = cfg.loadHub(); err != nil {
  70. return nil, "", err
  71. }
  72. if err = cfg.loadCSCLI(); err != nil {
  73. return nil, "", err
  74. }
  75. return &cfg, configData, nil
  76. }
  77. // XXX: We must not not have a different behavior with an empty vs a missing configuration file.
  78. // XXX: For this reason, all defaults have to come from NewConfig(). The following function should
  79. // XXX: be replaced
  80. func NewDefaultConfig() *Config {
  81. logLevel := log.InfoLevel
  82. commonCfg := CommonCfg{
  83. Daemonize: false,
  84. LogMedia: "stdout",
  85. LogLevel: &logLevel,
  86. }
  87. prometheus := PrometheusCfg{
  88. Enabled: true,
  89. Level: "full",
  90. }
  91. configPaths := ConfigurationPaths{
  92. ConfigDir: DefaultConfigPath("."),
  93. DataDir: DefaultDataPath("."),
  94. SimulationFilePath: DefaultConfigPath("simulation.yaml"),
  95. HubDir: DefaultConfigPath("hub"),
  96. HubIndexFile: DefaultConfigPath("hub", ".index.json"),
  97. }
  98. crowdsecCfg := CrowdsecServiceCfg{
  99. AcquisitionFilePath: DefaultConfigPath("acquis.yaml"),
  100. ParserRoutinesCount: 1,
  101. }
  102. cscliCfg := CscliCfg{
  103. Output: "human",
  104. Color: "auto",
  105. }
  106. apiCfg := APICfg{
  107. Client: &LocalApiClientCfg{
  108. CredentialsFilePath: DefaultConfigPath("lapi-secrets.yaml"),
  109. },
  110. Server: &LocalApiServerCfg{
  111. ListenURI: "127.0.0.1:8080",
  112. UseForwardedForHeaders: false,
  113. OnlineClient: &OnlineApiClientCfg{
  114. CredentialsFilePath: DefaultConfigPath("online_api_credentials.yaml"),
  115. },
  116. },
  117. CTI: &CTICfg{
  118. Enabled: ptr.Of(false),
  119. },
  120. }
  121. dbConfig := DatabaseCfg{
  122. Type: "sqlite",
  123. DbPath: DefaultDataPath("crowdsec.db"),
  124. MaxOpenConns: ptr.Of(DEFAULT_MAX_OPEN_CONNS),
  125. }
  126. globalCfg := Config{
  127. Common: &commonCfg,
  128. Prometheus: &prometheus,
  129. Crowdsec: &crowdsecCfg,
  130. Cscli: &cscliCfg,
  131. API: &apiCfg,
  132. ConfigPaths: &configPaths,
  133. DbConfig: &dbConfig,
  134. }
  135. return &globalCfg
  136. }
  137. // DefaultConfigPath returns the default path for a configuration resource
  138. // "elem" parameters are path components relative to the default cfg directory.
  139. func DefaultConfigPath(elem ...string) string {
  140. elem = append([]string{defaultConfigDir}, elem...)
  141. return filepath.Join(elem...)
  142. }
  143. // DefaultDataPath returns the default path for a data resource.
  144. // "elem" parameters are path components relative to the default data directory.
  145. func DefaultDataPath(elem ...string) string {
  146. elem = append([]string{defaultDataDir}, elem...)
  147. return filepath.Join(elem...)
  148. }