config.go 35 KB

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