config.go 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. // Package config manages the configuration
  2. package config
  3. import (
  4. "errors"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "strings"
  10. "github.com/spf13/viper"
  11. "github.com/drakkan/sftpgo/common"
  12. "github.com/drakkan/sftpgo/dataprovider"
  13. "github.com/drakkan/sftpgo/ftpd"
  14. "github.com/drakkan/sftpgo/httpclient"
  15. "github.com/drakkan/sftpgo/httpd"
  16. "github.com/drakkan/sftpgo/kms"
  17. "github.com/drakkan/sftpgo/logger"
  18. "github.com/drakkan/sftpgo/sftpd"
  19. "github.com/drakkan/sftpgo/telemetry"
  20. "github.com/drakkan/sftpgo/utils"
  21. "github.com/drakkan/sftpgo/version"
  22. "github.com/drakkan/sftpgo/webdavd"
  23. )
  24. const (
  25. logSender = "config"
  26. // configName defines the name for config file.
  27. // This name does not include the extension, viper will search for files
  28. // with supported extensions such as "sftpgo.json", "sftpgo.yaml" and so on
  29. configName = "sftpgo"
  30. // ConfigEnvPrefix defines a prefix that environment variables will use
  31. configEnvPrefix = "sftpgo"
  32. )
  33. var (
  34. globalConf globalConfig
  35. defaultSFTPDBanner = fmt.Sprintf("SFTPGo_%v", version.Get().Version)
  36. defaultFTPDBanner = fmt.Sprintf("SFTPGo %v ready", version.Get().Version)
  37. defaultSFTPDBinding = sftpd.Binding{
  38. Address: "",
  39. Port: 2022,
  40. ApplyProxyConfig: true,
  41. }
  42. defaultFTPDBinding = ftpd.Binding{
  43. Address: "",
  44. Port: 0,
  45. ApplyProxyConfig: true,
  46. TLSMode: 0,
  47. ForcePassiveIP: "",
  48. ClientAuthType: 0,
  49. TLSCipherSuites: nil,
  50. }
  51. defaultWebDAVDBinding = webdavd.Binding{
  52. Address: "",
  53. Port: 0,
  54. EnableHTTPS: false,
  55. ClientAuthType: 0,
  56. TLSCipherSuites: nil,
  57. Prefix: "",
  58. }
  59. defaultHTTPDBinding = httpd.Binding{
  60. Address: "127.0.0.1",
  61. Port: 8080,
  62. EnableWebAdmin: true,
  63. EnableHTTPS: false,
  64. ClientAuthType: 0,
  65. TLSCipherSuites: nil,
  66. }
  67. defaultRateLimiter = common.RateLimiterConfig{
  68. Average: 0,
  69. Period: 1000,
  70. Burst: 1,
  71. Type: 2,
  72. Protocols: []string{common.ProtocolSSH, common.ProtocolFTP, common.ProtocolWebDAV, common.ProtocolHTTP},
  73. GenerateDefenderEvents: false,
  74. EntriesSoftLimit: 100,
  75. EntriesHardLimit: 150,
  76. }
  77. )
  78. type globalConfig struct {
  79. Common common.Configuration `json:"common" mapstructure:"common"`
  80. SFTPD sftpd.Configuration `json:"sftpd" mapstructure:"sftpd"`
  81. FTPD ftpd.Configuration `json:"ftpd" mapstructure:"ftpd"`
  82. WebDAVD webdavd.Configuration `json:"webdavd" mapstructure:"webdavd"`
  83. ProviderConf dataprovider.Config `json:"data_provider" mapstructure:"data_provider"`
  84. HTTPDConfig httpd.Conf `json:"httpd" mapstructure:"httpd"`
  85. HTTPConfig httpclient.Config `json:"http" mapstructure:"http"`
  86. KMSConfig kms.Configuration `json:"kms" mapstructure:"kms"`
  87. TelemetryConfig telemetry.Conf `json:"telemetry" mapstructure:"telemetry"`
  88. }
  89. func init() {
  90. Init()
  91. }
  92. // Init initializes the global configuration.
  93. // It is not supposed to be called outside of this package.
  94. // It is exported to minimize refactoring efforts. Will eventually disappear.
  95. func Init() {
  96. // create a default configuration to use if no config file is provided
  97. globalConf = globalConfig{
  98. Common: common.Configuration{
  99. IdleTimeout: 15,
  100. UploadMode: 0,
  101. Actions: common.ProtocolActions{
  102. ExecuteOn: []string{},
  103. Hook: "",
  104. },
  105. SetstatMode: 0,
  106. ProxyProtocol: 0,
  107. ProxyAllowed: []string{},
  108. PostConnectHook: "",
  109. MaxTotalConnections: 0,
  110. DefenderConfig: common.DefenderConfig{
  111. Enabled: false,
  112. BanTime: 30,
  113. BanTimeIncrement: 50,
  114. Threshold: 15,
  115. ScoreInvalid: 2,
  116. ScoreValid: 1,
  117. ScoreRateExceeded: 3,
  118. ObservationTime: 30,
  119. EntriesSoftLimit: 100,
  120. EntriesHardLimit: 150,
  121. SafeListFile: "",
  122. BlockListFile: "",
  123. },
  124. RateLimitersConfig: []common.RateLimiterConfig{defaultRateLimiter},
  125. },
  126. SFTPD: sftpd.Configuration{
  127. Banner: defaultSFTPDBanner,
  128. Bindings: []sftpd.Binding{defaultSFTPDBinding},
  129. MaxAuthTries: 0,
  130. HostKeys: []string{},
  131. KexAlgorithms: []string{},
  132. Ciphers: []string{},
  133. MACs: []string{},
  134. TrustedUserCAKeys: []string{},
  135. LoginBannerFile: "",
  136. EnabledSSHCommands: sftpd.GetDefaultSSHCommands(),
  137. KeyboardInteractiveHook: "",
  138. PasswordAuthentication: true,
  139. },
  140. FTPD: ftpd.Configuration{
  141. Bindings: []ftpd.Binding{defaultFTPDBinding},
  142. Banner: defaultFTPDBanner,
  143. BannerFile: "",
  144. ActiveTransfersPortNon20: true,
  145. PassivePortRange: ftpd.PortRange{
  146. Start: 50000,
  147. End: 50100,
  148. },
  149. DisableActiveMode: false,
  150. EnableSite: false,
  151. HASHSupport: 0,
  152. CombineSupport: 0,
  153. CertificateFile: "",
  154. CertificateKeyFile: "",
  155. CACertificates: []string{},
  156. CARevocationLists: []string{},
  157. },
  158. WebDAVD: webdavd.Configuration{
  159. Bindings: []webdavd.Binding{defaultWebDAVDBinding},
  160. CertificateFile: "",
  161. CertificateKeyFile: "",
  162. CACertificates: []string{},
  163. CARevocationLists: []string{},
  164. Cors: webdavd.Cors{
  165. Enabled: false,
  166. AllowedOrigins: []string{},
  167. AllowedMethods: []string{},
  168. AllowedHeaders: []string{},
  169. ExposedHeaders: []string{},
  170. AllowCredentials: false,
  171. MaxAge: 0,
  172. },
  173. Cache: webdavd.Cache{
  174. Users: webdavd.UsersCacheConfig{
  175. ExpirationTime: 0,
  176. MaxSize: 50,
  177. },
  178. MimeTypes: webdavd.MimeCacheConfig{
  179. Enabled: true,
  180. MaxSize: 1000,
  181. },
  182. },
  183. },
  184. ProviderConf: dataprovider.Config{
  185. Driver: "sqlite",
  186. Name: "sftpgo.db",
  187. Host: "",
  188. Port: 0,
  189. Username: "",
  190. Password: "",
  191. ConnectionString: "",
  192. SQLTablesPrefix: "",
  193. SSLMode: 0,
  194. TrackQuota: 1,
  195. PoolSize: 0,
  196. UsersBaseDir: "",
  197. Actions: dataprovider.UserActions{
  198. ExecuteOn: []string{},
  199. Hook: "",
  200. },
  201. ExternalAuthHook: "",
  202. ExternalAuthScope: 0,
  203. CredentialsPath: "credentials",
  204. PreLoginHook: "",
  205. PostLoginHook: "",
  206. PostLoginScope: 0,
  207. CheckPasswordHook: "",
  208. CheckPasswordScope: 0,
  209. PasswordHashing: dataprovider.PasswordHashing{
  210. Argon2Options: dataprovider.Argon2Options{
  211. Memory: 65536,
  212. Iterations: 1,
  213. Parallelism: 2,
  214. },
  215. },
  216. UpdateMode: 0,
  217. PreferDatabaseCredentials: false,
  218. SkipNaturalKeysValidation: false,
  219. DelayedQuotaUpdate: 0,
  220. },
  221. HTTPDConfig: httpd.Conf{
  222. Bindings: []httpd.Binding{defaultHTTPDBinding},
  223. TemplatesPath: "templates",
  224. StaticFilesPath: "static",
  225. BackupsPath: "backups",
  226. WebAdminRoot: "",
  227. CertificateFile: "",
  228. CertificateKeyFile: "",
  229. CACertificates: nil,
  230. CARevocationLists: nil,
  231. },
  232. HTTPConfig: httpclient.Config{
  233. Timeout: 20,
  234. RetryWaitMin: 2,
  235. RetryWaitMax: 30,
  236. RetryMax: 3,
  237. CACertificates: nil,
  238. Certificates: nil,
  239. SkipTLSVerify: false,
  240. },
  241. KMSConfig: kms.Configuration{
  242. Secrets: kms.Secrets{
  243. URL: "",
  244. MasterKeyPath: "",
  245. },
  246. },
  247. TelemetryConfig: telemetry.Conf{
  248. BindPort: 10000,
  249. BindAddress: "127.0.0.1",
  250. EnableProfiler: false,
  251. AuthUserFile: "",
  252. CertificateFile: "",
  253. CertificateKeyFile: "",
  254. TLSCipherSuites: nil,
  255. },
  256. }
  257. viper.SetEnvPrefix(configEnvPrefix)
  258. replacer := strings.NewReplacer(".", "__")
  259. viper.SetEnvKeyReplacer(replacer)
  260. viper.SetConfigName(configName)
  261. setViperDefaults()
  262. viper.AutomaticEnv()
  263. viper.AllowEmptyEnv(true)
  264. }
  265. // GetCommonConfig returns the common protocols configuration
  266. func GetCommonConfig() common.Configuration {
  267. return globalConf.Common
  268. }
  269. // SetCommonConfig sets the common protocols configuration
  270. func SetCommonConfig(config common.Configuration) {
  271. globalConf.Common = config
  272. }
  273. // GetSFTPDConfig returns the configuration for the SFTP server
  274. func GetSFTPDConfig() sftpd.Configuration {
  275. return globalConf.SFTPD
  276. }
  277. // SetSFTPDConfig sets the configuration for the SFTP server
  278. func SetSFTPDConfig(config sftpd.Configuration) {
  279. globalConf.SFTPD = config
  280. }
  281. // GetFTPDConfig returns the configuration for the FTP server
  282. func GetFTPDConfig() ftpd.Configuration {
  283. return globalConf.FTPD
  284. }
  285. // SetFTPDConfig sets the configuration for the FTP server
  286. func SetFTPDConfig(config ftpd.Configuration) {
  287. globalConf.FTPD = config
  288. }
  289. // GetWebDAVDConfig returns the configuration for the WebDAV server
  290. func GetWebDAVDConfig() webdavd.Configuration {
  291. return globalConf.WebDAVD
  292. }
  293. // SetWebDAVDConfig sets the configuration for the WebDAV server
  294. func SetWebDAVDConfig(config webdavd.Configuration) {
  295. globalConf.WebDAVD = config
  296. }
  297. // GetHTTPDConfig returns the configuration for the HTTP server
  298. func GetHTTPDConfig() httpd.Conf {
  299. return globalConf.HTTPDConfig
  300. }
  301. // SetHTTPDConfig sets the configuration for the HTTP server
  302. func SetHTTPDConfig(config httpd.Conf) {
  303. globalConf.HTTPDConfig = config
  304. }
  305. // GetProviderConf returns the configuration for the data provider
  306. func GetProviderConf() dataprovider.Config {
  307. return globalConf.ProviderConf
  308. }
  309. // SetProviderConf sets the configuration for the data provider
  310. func SetProviderConf(config dataprovider.Config) {
  311. globalConf.ProviderConf = config
  312. }
  313. // GetHTTPConfig returns the configuration for HTTP clients
  314. func GetHTTPConfig() httpclient.Config {
  315. return globalConf.HTTPConfig
  316. }
  317. // GetKMSConfig returns the KMS configuration
  318. func GetKMSConfig() kms.Configuration {
  319. return globalConf.KMSConfig
  320. }
  321. // SetKMSConfig sets the kms configuration
  322. func SetKMSConfig(config kms.Configuration) {
  323. globalConf.KMSConfig = config
  324. }
  325. // GetTelemetryConfig returns the telemetry configuration
  326. func GetTelemetryConfig() telemetry.Conf {
  327. return globalConf.TelemetryConfig
  328. }
  329. // SetTelemetryConfig sets the telemetry configuration
  330. func SetTelemetryConfig(config telemetry.Conf) {
  331. globalConf.TelemetryConfig = config
  332. }
  333. // HasServicesToStart returns true if the config defines at least a service to start.
  334. // Supported services are SFTP, FTP and WebDAV
  335. func HasServicesToStart() bool {
  336. if globalConf.SFTPD.ShouldBind() {
  337. return true
  338. }
  339. if globalConf.FTPD.ShouldBind() {
  340. return true
  341. }
  342. if globalConf.WebDAVD.ShouldBind() {
  343. return true
  344. }
  345. return false
  346. }
  347. func getRedactedGlobalConf() globalConfig {
  348. conf := globalConf
  349. conf.ProviderConf.Password = "[redacted]"
  350. return conf
  351. }
  352. func setConfigFile(configDir, configFile string) {
  353. if configFile == "" {
  354. return
  355. }
  356. if !filepath.IsAbs(configFile) && utils.IsFileInputValid(configFile) {
  357. configFile = filepath.Join(configDir, configFile)
  358. }
  359. viper.SetConfigFile(configFile)
  360. }
  361. // LoadConfig loads the configuration
  362. // configDir will be added to the configuration search paths.
  363. // The search path contains by default the current directory and on linux it contains
  364. // $HOME/.config/sftpgo and /etc/sftpgo too.
  365. // configFile is an absolute or relative path (to the config dir) to the configuration file.
  366. func LoadConfig(configDir, configFile string) error {
  367. var err error
  368. viper.AddConfigPath(configDir)
  369. setViperAdditionalConfigPaths()
  370. viper.AddConfigPath(".")
  371. setConfigFile(configDir, configFile)
  372. if err = viper.ReadInConfig(); err != nil {
  373. // if the user specify a configuration file we get os.ErrNotExist.
  374. // viper.ConfigFileNotFoundError is returned if viper is unable
  375. // to find sftpgo.{json,yaml, etc..} in any of the search paths
  376. if errors.As(err, &viper.ConfigFileNotFoundError{}) {
  377. logger.Debug(logSender, "", "no configuration file found")
  378. } else {
  379. // should we return the error and not start here?
  380. logger.Warn(logSender, "", "error loading configuration file: %v", err)
  381. logger.WarnToConsole("error loading configuration file: %v", err)
  382. }
  383. }
  384. err = viper.Unmarshal(&globalConf)
  385. if err != nil {
  386. logger.Warn(logSender, "", "error parsing configuration file: %v", err)
  387. logger.WarnToConsole("error parsing configuration file: %v", err)
  388. return err
  389. }
  390. // viper only supports slice of strings from env vars, so we use our custom method
  391. loadBindingsFromEnv()
  392. if strings.TrimSpace(globalConf.SFTPD.Banner) == "" {
  393. globalConf.SFTPD.Banner = defaultSFTPDBanner
  394. }
  395. if strings.TrimSpace(globalConf.FTPD.Banner) == "" {
  396. globalConf.FTPD.Banner = defaultFTPDBanner
  397. }
  398. if globalConf.ProviderConf.UsersBaseDir != "" && !utils.IsFileInputValid(globalConf.ProviderConf.UsersBaseDir) {
  399. err = fmt.Errorf("invalid users base dir %#v will be ignored", globalConf.ProviderConf.UsersBaseDir)
  400. globalConf.ProviderConf.UsersBaseDir = ""
  401. logger.Warn(logSender, "", "Configuration error: %v", err)
  402. logger.WarnToConsole("Configuration error: %v", err)
  403. }
  404. if globalConf.Common.UploadMode < 0 || globalConf.Common.UploadMode > 2 {
  405. warn := fmt.Sprintf("invalid upload_mode 0, 1 and 2 are supported, configured: %v reset upload_mode to 0",
  406. globalConf.Common.UploadMode)
  407. globalConf.Common.UploadMode = 0
  408. logger.Warn(logSender, "", "Configuration error: %v", warn)
  409. logger.WarnToConsole("Configuration error: %v", warn)
  410. }
  411. if globalConf.Common.ProxyProtocol < 0 || globalConf.Common.ProxyProtocol > 2 {
  412. warn := fmt.Sprintf("invalid proxy_protocol 0, 1 and 2 are supported, configured: %v reset proxy_protocol to 0",
  413. globalConf.Common.ProxyProtocol)
  414. globalConf.Common.ProxyProtocol = 0
  415. logger.Warn(logSender, "", "Configuration error: %v", warn)
  416. logger.WarnToConsole("Configuration error: %v", warn)
  417. }
  418. if globalConf.ProviderConf.ExternalAuthScope < 0 || globalConf.ProviderConf.ExternalAuthScope > 15 {
  419. warn := fmt.Sprintf("invalid external_auth_scope: %v reset to 0", globalConf.ProviderConf.ExternalAuthScope)
  420. globalConf.ProviderConf.ExternalAuthScope = 0
  421. logger.Warn(logSender, "", "Configuration error: %v", warn)
  422. logger.WarnToConsole("Configuration error: %v", warn)
  423. }
  424. if globalConf.ProviderConf.CredentialsPath == "" {
  425. warn := "invalid credentials path, reset to \"credentials\""
  426. globalConf.ProviderConf.CredentialsPath = "credentials"
  427. logger.Warn(logSender, "", "Configuration error: %v", warn)
  428. logger.WarnToConsole("Configuration error: %v", warn)
  429. }
  430. logger.Debug(logSender, "", "config file used: '%#v', config loaded: %+v", viper.ConfigFileUsed(), getRedactedGlobalConf())
  431. return nil
  432. }
  433. func checkSFTPDBindingsCompatibility() {
  434. if globalConf.SFTPD.BindPort == 0 { //nolint:staticcheck
  435. return
  436. }
  437. // we copy deprecated fields to new ones to keep backward compatibility so lint is disabled
  438. binding := sftpd.Binding{
  439. ApplyProxyConfig: true,
  440. }
  441. if globalConf.SFTPD.BindPort > 0 { //nolint:staticcheck
  442. binding.Port = globalConf.SFTPD.BindPort //nolint:staticcheck
  443. }
  444. if globalConf.SFTPD.BindAddress != "" { //nolint:staticcheck
  445. binding.Address = globalConf.SFTPD.BindAddress //nolint:staticcheck
  446. }
  447. globalConf.SFTPD.Bindings = []sftpd.Binding{binding}
  448. }
  449. func checkFTPDBindingCompatibility() {
  450. if globalConf.FTPD.BindPort == 0 { //nolint:staticcheck
  451. return
  452. }
  453. binding := ftpd.Binding{
  454. ApplyProxyConfig: true,
  455. }
  456. if globalConf.FTPD.BindPort > 0 { //nolint:staticcheck
  457. binding.Port = globalConf.FTPD.BindPort //nolint:staticcheck
  458. }
  459. if globalConf.FTPD.BindAddress != "" { //nolint:staticcheck
  460. binding.Address = globalConf.FTPD.BindAddress //nolint:staticcheck
  461. }
  462. if globalConf.FTPD.TLSMode > 0 { //nolint:staticcheck
  463. binding.TLSMode = globalConf.FTPD.TLSMode //nolint:staticcheck
  464. }
  465. if globalConf.FTPD.ForcePassiveIP != "" { //nolint:staticcheck
  466. binding.ForcePassiveIP = globalConf.FTPD.ForcePassiveIP //nolint:staticcheck
  467. }
  468. globalConf.FTPD.Bindings = []ftpd.Binding{binding}
  469. }
  470. func checkWebDAVDBindingCompatibility() {
  471. if globalConf.WebDAVD.BindPort == 0 { //nolint:staticcheck
  472. return
  473. }
  474. binding := webdavd.Binding{
  475. EnableHTTPS: globalConf.WebDAVD.CertificateFile != "" && globalConf.WebDAVD.CertificateKeyFile != "",
  476. }
  477. if globalConf.WebDAVD.BindPort > 0 { //nolint:staticcheck
  478. binding.Port = globalConf.WebDAVD.BindPort //nolint:staticcheck
  479. }
  480. if globalConf.WebDAVD.BindAddress != "" { //nolint:staticcheck
  481. binding.Address = globalConf.WebDAVD.BindAddress //nolint:staticcheck
  482. }
  483. globalConf.WebDAVD.Bindings = []webdavd.Binding{binding}
  484. }
  485. func checkHTTPDBindingCompatibility() {
  486. if globalConf.HTTPDConfig.BindPort == 0 { //nolint:staticcheck
  487. return
  488. }
  489. binding := httpd.Binding{
  490. EnableWebAdmin: globalConf.HTTPDConfig.StaticFilesPath != "" && globalConf.HTTPDConfig.TemplatesPath != "",
  491. EnableHTTPS: globalConf.HTTPDConfig.CertificateFile != "" && globalConf.HTTPDConfig.CertificateKeyFile != "",
  492. }
  493. if globalConf.HTTPDConfig.BindPort > 0 { //nolint:staticcheck
  494. binding.Port = globalConf.HTTPDConfig.BindPort //nolint:staticcheck
  495. }
  496. if globalConf.HTTPDConfig.BindAddress != "" { //nolint:staticcheck
  497. binding.Address = globalConf.HTTPDConfig.BindAddress //nolint:staticcheck
  498. }
  499. globalConf.HTTPDConfig.Bindings = []httpd.Binding{binding}
  500. }
  501. func loadBindingsFromEnv() {
  502. checkSFTPDBindingsCompatibility()
  503. checkFTPDBindingCompatibility()
  504. checkWebDAVDBindingCompatibility()
  505. checkHTTPDBindingCompatibility()
  506. for idx := 0; idx < 10; idx++ {
  507. getRateLimitersFromEnv(idx)
  508. getSFTPDBindindFromEnv(idx)
  509. getFTPDBindingFromEnv(idx)
  510. getWebDAVDBindingFromEnv(idx)
  511. getHTTPDBindingFromEnv(idx)
  512. getHTTPClientCertificatesFromEnv(idx)
  513. }
  514. }
  515. func getRateLimitersFromEnv(idx int) {
  516. rtlConfig := defaultRateLimiter
  517. if len(globalConf.Common.RateLimitersConfig) > idx {
  518. rtlConfig = globalConf.Common.RateLimitersConfig[idx]
  519. }
  520. isSet := false
  521. average, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__AVERAGE", idx))
  522. if ok {
  523. rtlConfig.Average = average
  524. isSet = true
  525. }
  526. period, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__PERIOD", idx))
  527. if ok {
  528. rtlConfig.Period = period
  529. isSet = true
  530. }
  531. burst, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__BURST", idx))
  532. if ok {
  533. rtlConfig.Burst = int(burst)
  534. isSet = true
  535. }
  536. rtlType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__TYPE", idx))
  537. if ok {
  538. rtlConfig.Type = int(rtlType)
  539. isSet = true
  540. }
  541. protocols, ok := lookupStringListFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__PROTOCOLS", idx))
  542. if ok {
  543. rtlConfig.Protocols = protocols
  544. isSet = true
  545. }
  546. generateEvents, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__GENERATE_DEFENDER_EVENTS", idx))
  547. if ok {
  548. rtlConfig.GenerateDefenderEvents = generateEvents
  549. isSet = true
  550. }
  551. softLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_SOFT_LIMIT", idx))
  552. if ok {
  553. rtlConfig.EntriesSoftLimit = int(softLimit)
  554. isSet = true
  555. }
  556. hardLimit, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_COMMON__RATE_LIMITERS__%v__ENTRIES_HARD_LIMIT", idx))
  557. if ok {
  558. rtlConfig.EntriesHardLimit = int(hardLimit)
  559. isSet = true
  560. }
  561. if isSet {
  562. if len(globalConf.Common.RateLimitersConfig) > idx {
  563. globalConf.Common.RateLimitersConfig[idx] = rtlConfig
  564. } else {
  565. globalConf.Common.RateLimitersConfig = append(globalConf.Common.RateLimitersConfig, rtlConfig)
  566. }
  567. }
  568. }
  569. func getSFTPDBindindFromEnv(idx int) {
  570. binding := sftpd.Binding{
  571. ApplyProxyConfig: true,
  572. }
  573. if len(globalConf.SFTPD.Bindings) > idx {
  574. binding = globalConf.SFTPD.Bindings[idx]
  575. }
  576. isSet := false
  577. port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_SFTPD__BINDINGS__%v__PORT", idx))
  578. if ok {
  579. binding.Port = int(port)
  580. isSet = true
  581. }
  582. address, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_SFTPD__BINDINGS__%v__ADDRESS", idx))
  583. if ok {
  584. binding.Address = address
  585. isSet = true
  586. }
  587. applyProxyConfig, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_SFTPD__BINDINGS__%v__APPLY_PROXY_CONFIG", idx))
  588. if ok {
  589. binding.ApplyProxyConfig = applyProxyConfig
  590. isSet = true
  591. }
  592. if isSet {
  593. if len(globalConf.SFTPD.Bindings) > idx {
  594. globalConf.SFTPD.Bindings[idx] = binding
  595. } else {
  596. globalConf.SFTPD.Bindings = append(globalConf.SFTPD.Bindings, binding)
  597. }
  598. }
  599. }
  600. func getFTPDBindingFromEnv(idx int) {
  601. binding := ftpd.Binding{
  602. ApplyProxyConfig: true,
  603. }
  604. if len(globalConf.FTPD.Bindings) > idx {
  605. binding = globalConf.FTPD.Bindings[idx]
  606. }
  607. isSet := false
  608. port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__PORT", idx))
  609. if ok {
  610. binding.Port = int(port)
  611. isSet = true
  612. }
  613. address, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__ADDRESS", idx))
  614. if ok {
  615. binding.Address = address
  616. isSet = true
  617. }
  618. applyProxyConfig, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__APPLY_PROXY_CONFIG", idx))
  619. if ok {
  620. binding.ApplyProxyConfig = applyProxyConfig
  621. isSet = true
  622. }
  623. tlsMode, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__TLS_MODE", idx))
  624. if ok {
  625. binding.TLSMode = int(tlsMode)
  626. isSet = true
  627. }
  628. passiveIP, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__FORCE_PASSIVE_IP", idx))
  629. if ok {
  630. binding.ForcePassiveIP = passiveIP
  631. isSet = true
  632. }
  633. clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx))
  634. if ok {
  635. binding.ClientAuthType = int(clientAuthType)
  636. isSet = true
  637. }
  638. tlsCiphers, ok := lookupStringListFromEnv(fmt.Sprintf("SFTPGO_FTPD__BINDINGS__%v__TLS_CIPHER_SUITES", idx))
  639. if ok {
  640. binding.TLSCipherSuites = tlsCiphers
  641. isSet = true
  642. }
  643. if isSet {
  644. if len(globalConf.FTPD.Bindings) > idx {
  645. globalConf.FTPD.Bindings[idx] = binding
  646. } else {
  647. globalConf.FTPD.Bindings = append(globalConf.FTPD.Bindings, binding)
  648. }
  649. }
  650. }
  651. func getWebDAVDBindingFromEnv(idx int) {
  652. binding := webdavd.Binding{}
  653. if len(globalConf.WebDAVD.Bindings) > idx {
  654. binding = globalConf.WebDAVD.Bindings[idx]
  655. }
  656. isSet := false
  657. port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__PORT", idx))
  658. if ok {
  659. binding.Port = int(port)
  660. isSet = true
  661. }
  662. address, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__ADDRESS", idx))
  663. if ok {
  664. binding.Address = address
  665. isSet = true
  666. }
  667. enableHTTPS, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__ENABLE_HTTPS", idx))
  668. if ok {
  669. binding.EnableHTTPS = enableHTTPS
  670. isSet = true
  671. }
  672. clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx))
  673. if ok {
  674. binding.ClientAuthType = int(clientAuthType)
  675. isSet = true
  676. }
  677. tlsCiphers, ok := lookupStringListFromEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__TLS_CIPHER_SUITES", idx))
  678. if ok {
  679. binding.TLSCipherSuites = tlsCiphers
  680. isSet = true
  681. }
  682. prefix, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__PREFIX", idx))
  683. if ok {
  684. binding.Prefix = prefix
  685. isSet = true
  686. }
  687. if isSet {
  688. if len(globalConf.WebDAVD.Bindings) > idx {
  689. globalConf.WebDAVD.Bindings[idx] = binding
  690. } else {
  691. globalConf.WebDAVD.Bindings = append(globalConf.WebDAVD.Bindings, binding)
  692. }
  693. }
  694. }
  695. func getHTTPDBindingFromEnv(idx int) {
  696. binding := httpd.Binding{}
  697. if len(globalConf.HTTPDConfig.Bindings) > idx {
  698. binding = globalConf.HTTPDConfig.Bindings[idx]
  699. }
  700. isSet := false
  701. port, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__PORT", idx))
  702. if ok {
  703. binding.Port = int(port)
  704. isSet = true
  705. }
  706. address, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__ADDRESS", idx))
  707. if ok {
  708. binding.Address = address
  709. isSet = true
  710. }
  711. enableWebAdmin, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__ENABLE_WEB_ADMIN", idx))
  712. if ok {
  713. binding.EnableWebAdmin = enableWebAdmin
  714. isSet = true
  715. }
  716. enableHTTPS, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__ENABLE_HTTPS", idx))
  717. if ok {
  718. binding.EnableHTTPS = enableHTTPS
  719. isSet = true
  720. }
  721. clientAuthType, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__CLIENT_AUTH_TYPE", idx))
  722. if ok {
  723. binding.ClientAuthType = int(clientAuthType)
  724. isSet = true
  725. }
  726. tlsCiphers, ok := lookupStringListFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__TLS_CIPHER_SUITES", idx))
  727. if ok {
  728. binding.TLSCipherSuites = tlsCiphers
  729. isSet = true
  730. }
  731. if isSet {
  732. if len(globalConf.HTTPDConfig.Bindings) > idx {
  733. globalConf.HTTPDConfig.Bindings[idx] = binding
  734. } else {
  735. globalConf.HTTPDConfig.Bindings = append(globalConf.HTTPDConfig.Bindings, binding)
  736. }
  737. }
  738. }
  739. func getHTTPClientCertificatesFromEnv(idx int) {
  740. tlsCert := httpclient.TLSKeyPair{}
  741. cert, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTP__CERTIFICATES__%v__CERT", idx))
  742. if ok {
  743. tlsCert.Cert = cert
  744. }
  745. key, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTP__CERTIFICATES__%v__KEY", idx))
  746. if ok {
  747. tlsCert.Key = key
  748. }
  749. if tlsCert.Cert != "" && tlsCert.Key != "" {
  750. if len(globalConf.HTTPConfig.Certificates) > idx {
  751. globalConf.HTTPConfig.Certificates[idx] = tlsCert
  752. } else {
  753. globalConf.HTTPConfig.Certificates = append(globalConf.HTTPConfig.Certificates, tlsCert)
  754. }
  755. }
  756. }
  757. func setViperDefaults() {
  758. viper.SetDefault("common.idle_timeout", globalConf.Common.IdleTimeout)
  759. viper.SetDefault("common.upload_mode", globalConf.Common.UploadMode)
  760. viper.SetDefault("common.actions.execute_on", globalConf.Common.Actions.ExecuteOn)
  761. viper.SetDefault("common.actions.hook", globalConf.Common.Actions.Hook)
  762. viper.SetDefault("common.setstat_mode", globalConf.Common.SetstatMode)
  763. viper.SetDefault("common.proxy_protocol", globalConf.Common.ProxyProtocol)
  764. viper.SetDefault("common.proxy_allowed", globalConf.Common.ProxyAllowed)
  765. viper.SetDefault("common.post_connect_hook", globalConf.Common.PostConnectHook)
  766. viper.SetDefault("common.max_total_connections", globalConf.Common.MaxTotalConnections)
  767. viper.SetDefault("common.defender.enabled", globalConf.Common.DefenderConfig.Enabled)
  768. viper.SetDefault("common.defender.ban_time", globalConf.Common.DefenderConfig.BanTime)
  769. viper.SetDefault("common.defender.ban_time_increment", globalConf.Common.DefenderConfig.BanTimeIncrement)
  770. viper.SetDefault("common.defender.threshold", globalConf.Common.DefenderConfig.Threshold)
  771. viper.SetDefault("common.defender.score_invalid", globalConf.Common.DefenderConfig.ScoreInvalid)
  772. viper.SetDefault("common.defender.score_valid", globalConf.Common.DefenderConfig.ScoreValid)
  773. viper.SetDefault("common.defender.score_rate_exceeded", globalConf.Common.DefenderConfig.ScoreRateExceeded)
  774. viper.SetDefault("common.defender.observation_time", globalConf.Common.DefenderConfig.ObservationTime)
  775. viper.SetDefault("common.defender.entries_soft_limit", globalConf.Common.DefenderConfig.EntriesSoftLimit)
  776. viper.SetDefault("common.defender.entries_hard_limit", globalConf.Common.DefenderConfig.EntriesHardLimit)
  777. viper.SetDefault("common.defender.safelist_file", globalConf.Common.DefenderConfig.SafeListFile)
  778. viper.SetDefault("common.defender.blocklist_file", globalConf.Common.DefenderConfig.BlockListFile)
  779. viper.SetDefault("sftpd.max_auth_tries", globalConf.SFTPD.MaxAuthTries)
  780. viper.SetDefault("sftpd.banner", globalConf.SFTPD.Banner)
  781. viper.SetDefault("sftpd.host_keys", globalConf.SFTPD.HostKeys)
  782. viper.SetDefault("sftpd.kex_algorithms", globalConf.SFTPD.KexAlgorithms)
  783. viper.SetDefault("sftpd.ciphers", globalConf.SFTPD.Ciphers)
  784. viper.SetDefault("sftpd.macs", globalConf.SFTPD.MACs)
  785. viper.SetDefault("sftpd.trusted_user_ca_keys", globalConf.SFTPD.TrustedUserCAKeys)
  786. viper.SetDefault("sftpd.login_banner_file", globalConf.SFTPD.LoginBannerFile)
  787. viper.SetDefault("sftpd.enabled_ssh_commands", globalConf.SFTPD.EnabledSSHCommands)
  788. viper.SetDefault("sftpd.keyboard_interactive_auth_hook", globalConf.SFTPD.KeyboardInteractiveHook)
  789. viper.SetDefault("sftpd.password_authentication", globalConf.SFTPD.PasswordAuthentication)
  790. viper.SetDefault("ftpd.banner", globalConf.FTPD.Banner)
  791. viper.SetDefault("ftpd.banner_file", globalConf.FTPD.BannerFile)
  792. viper.SetDefault("ftpd.active_transfers_port_non_20", globalConf.FTPD.ActiveTransfersPortNon20)
  793. viper.SetDefault("ftpd.passive_port_range.start", globalConf.FTPD.PassivePortRange.Start)
  794. viper.SetDefault("ftpd.passive_port_range.end", globalConf.FTPD.PassivePortRange.End)
  795. viper.SetDefault("ftpd.disable_active_mode", globalConf.FTPD.DisableActiveMode)
  796. viper.SetDefault("ftpd.enable_site", globalConf.FTPD.EnableSite)
  797. viper.SetDefault("ftpd.hash_support", globalConf.FTPD.HASHSupport)
  798. viper.SetDefault("ftpd.combine_support", globalConf.FTPD.CombineSupport)
  799. viper.SetDefault("ftpd.certificate_file", globalConf.FTPD.CertificateFile)
  800. viper.SetDefault("ftpd.certificate_key_file", globalConf.FTPD.CertificateKeyFile)
  801. viper.SetDefault("ftpd.ca_certificates", globalConf.FTPD.CACertificates)
  802. viper.SetDefault("ftpd.ca_revocation_lists", globalConf.FTPD.CARevocationLists)
  803. viper.SetDefault("webdavd.certificate_file", globalConf.WebDAVD.CertificateFile)
  804. viper.SetDefault("webdavd.certificate_key_file", globalConf.WebDAVD.CertificateKeyFile)
  805. viper.SetDefault("webdavd.ca_certificates", globalConf.WebDAVD.CACertificates)
  806. viper.SetDefault("webdavd.ca_revocation_lists", globalConf.WebDAVD.CARevocationLists)
  807. viper.SetDefault("webdavd.cors.enabled", globalConf.WebDAVD.Cors.Enabled)
  808. viper.SetDefault("webdavd.cors.allowed_origins", globalConf.WebDAVD.Cors.AllowedOrigins)
  809. viper.SetDefault("webdavd.cors.allowed_methods", globalConf.WebDAVD.Cors.AllowedMethods)
  810. viper.SetDefault("webdavd.cors.allowed_headers", globalConf.WebDAVD.Cors.AllowedHeaders)
  811. viper.SetDefault("webdavd.cors.exposed_headers", globalConf.WebDAVD.Cors.ExposedHeaders)
  812. viper.SetDefault("webdavd.cors.allow_credentials", globalConf.WebDAVD.Cors.AllowCredentials)
  813. viper.SetDefault("webdavd.cors.max_age", globalConf.WebDAVD.Cors.MaxAge)
  814. viper.SetDefault("webdavd.cache.users.expiration_time", globalConf.WebDAVD.Cache.Users.ExpirationTime)
  815. viper.SetDefault("webdavd.cache.users.max_size", globalConf.WebDAVD.Cache.Users.MaxSize)
  816. viper.SetDefault("webdavd.cache.mime_types.enabled", globalConf.WebDAVD.Cache.MimeTypes.Enabled)
  817. viper.SetDefault("webdavd.cache.mime_types.max_size", globalConf.WebDAVD.Cache.MimeTypes.MaxSize)
  818. viper.SetDefault("data_provider.driver", globalConf.ProviderConf.Driver)
  819. viper.SetDefault("data_provider.name", globalConf.ProviderConf.Name)
  820. viper.SetDefault("data_provider.host", globalConf.ProviderConf.Host)
  821. viper.SetDefault("data_provider.port", globalConf.ProviderConf.Port)
  822. viper.SetDefault("data_provider.username", globalConf.ProviderConf.Username)
  823. viper.SetDefault("data_provider.password", globalConf.ProviderConf.Password)
  824. viper.SetDefault("data_provider.sslmode", globalConf.ProviderConf.SSLMode)
  825. viper.SetDefault("data_provider.connection_string", globalConf.ProviderConf.ConnectionString)
  826. viper.SetDefault("data_provider.sql_tables_prefix", globalConf.ProviderConf.SQLTablesPrefix)
  827. viper.SetDefault("data_provider.track_quota", globalConf.ProviderConf.TrackQuota)
  828. viper.SetDefault("data_provider.pool_size", globalConf.ProviderConf.PoolSize)
  829. viper.SetDefault("data_provider.users_base_dir", globalConf.ProviderConf.UsersBaseDir)
  830. viper.SetDefault("data_provider.actions.execute_on", globalConf.ProviderConf.Actions.ExecuteOn)
  831. viper.SetDefault("data_provider.actions.hook", globalConf.ProviderConf.Actions.Hook)
  832. viper.SetDefault("data_provider.external_auth_hook", globalConf.ProviderConf.ExternalAuthHook)
  833. viper.SetDefault("data_provider.external_auth_scope", globalConf.ProviderConf.ExternalAuthScope)
  834. viper.SetDefault("data_provider.credentials_path", globalConf.ProviderConf.CredentialsPath)
  835. viper.SetDefault("data_provider.prefer_database_credentials", globalConf.ProviderConf.PreferDatabaseCredentials)
  836. viper.SetDefault("data_provider.pre_login_hook", globalConf.ProviderConf.PreLoginHook)
  837. viper.SetDefault("data_provider.post_login_hook", globalConf.ProviderConf.PostLoginHook)
  838. viper.SetDefault("data_provider.post_login_scope", globalConf.ProviderConf.PostLoginScope)
  839. viper.SetDefault("data_provider.check_password_hook", globalConf.ProviderConf.CheckPasswordHook)
  840. viper.SetDefault("data_provider.check_password_scope", globalConf.ProviderConf.CheckPasswordScope)
  841. viper.SetDefault("data_provider.password_hashing.argon2_options.memory", globalConf.ProviderConf.PasswordHashing.Argon2Options.Memory)
  842. viper.SetDefault("data_provider.password_hashing.argon2_options.iterations", globalConf.ProviderConf.PasswordHashing.Argon2Options.Iterations)
  843. viper.SetDefault("data_provider.password_hashing.argon2_options.parallelism", globalConf.ProviderConf.PasswordHashing.Argon2Options.Parallelism)
  844. viper.SetDefault("data_provider.update_mode", globalConf.ProviderConf.UpdateMode)
  845. viper.SetDefault("data_provider.skip_natural_keys_validation", globalConf.ProviderConf.SkipNaturalKeysValidation)
  846. viper.SetDefault("data_provider.delayed_quota_update", globalConf.ProviderConf.DelayedQuotaUpdate)
  847. viper.SetDefault("httpd.templates_path", globalConf.HTTPDConfig.TemplatesPath)
  848. viper.SetDefault("httpd.static_files_path", globalConf.HTTPDConfig.StaticFilesPath)
  849. viper.SetDefault("httpd.backups_path", globalConf.HTTPDConfig.BackupsPath)
  850. viper.SetDefault("httpd.web_admin_root", globalConf.HTTPDConfig.WebAdminRoot)
  851. viper.SetDefault("httpd.certificate_file", globalConf.HTTPDConfig.CertificateFile)
  852. viper.SetDefault("httpd.certificate_key_file", globalConf.HTTPDConfig.CertificateKeyFile)
  853. viper.SetDefault("httpd.ca_certificates", globalConf.HTTPDConfig.CACertificates)
  854. viper.SetDefault("httpd.ca_revocation_lists", globalConf.HTTPDConfig.CARevocationLists)
  855. viper.SetDefault("http.timeout", globalConf.HTTPConfig.Timeout)
  856. viper.SetDefault("http.retry_wait_min", globalConf.HTTPConfig.RetryWaitMin)
  857. viper.SetDefault("http.retry_wait_max", globalConf.HTTPConfig.RetryWaitMax)
  858. viper.SetDefault("http.retry_max", globalConf.HTTPConfig.RetryMax)
  859. viper.SetDefault("http.ca_certificates", globalConf.HTTPConfig.CACertificates)
  860. viper.SetDefault("http.skip_tls_verify", globalConf.HTTPConfig.SkipTLSVerify)
  861. viper.SetDefault("kms.secrets.url", globalConf.KMSConfig.Secrets.URL)
  862. viper.SetDefault("kms.secrets.master_key_path", globalConf.KMSConfig.Secrets.MasterKeyPath)
  863. viper.SetDefault("telemetry.bind_port", globalConf.TelemetryConfig.BindPort)
  864. viper.SetDefault("telemetry.bind_address", globalConf.TelemetryConfig.BindAddress)
  865. viper.SetDefault("telemetry.enable_profiler", globalConf.TelemetryConfig.EnableProfiler)
  866. viper.SetDefault("telemetry.auth_user_file", globalConf.TelemetryConfig.AuthUserFile)
  867. viper.SetDefault("telemetry.certificate_file", globalConf.TelemetryConfig.CertificateFile)
  868. viper.SetDefault("telemetry.certificate_key_file", globalConf.TelemetryConfig.CertificateKeyFile)
  869. viper.SetDefault("telemetry.tls_cipher_suites", globalConf.TelemetryConfig.TLSCipherSuites)
  870. }
  871. func lookupBoolFromEnv(envName string) (bool, bool) {
  872. value, ok := os.LookupEnv(envName)
  873. if ok {
  874. converted, err := strconv.ParseBool(value)
  875. if err == nil {
  876. return converted, ok
  877. }
  878. }
  879. return false, false
  880. }
  881. func lookupIntFromEnv(envName string) (int64, bool) {
  882. value, ok := os.LookupEnv(envName)
  883. if ok {
  884. converted, err := strconv.ParseInt(value, 10, 64)
  885. if err == nil {
  886. return converted, ok
  887. }
  888. }
  889. return 0, false
  890. }
  891. func lookupStringListFromEnv(envName string) ([]string, bool) {
  892. value, ok := os.LookupEnv(envName)
  893. if ok {
  894. var result []string
  895. for _, v := range strings.Split(value, ",") {
  896. result = append(result, strings.TrimSpace(v))
  897. }
  898. return result, true
  899. }
  900. return nil, false
  901. }