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