config.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. package http
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "strings"
  7. "github.com/BurntSushi/toml"
  8. )
  9. const (
  10. NoConnection string = "none"
  11. UnixDomainSocketConnection string = "unix"
  12. HttpConnection string = "http"
  13. )
  14. const (
  15. TlsOff string = "off"
  16. TlsStrict string = "strict"
  17. )
  18. type Config struct {
  19. ConnectionType string `toml:"-"` // connection type is not loaded from toml
  20. Socket string // filename for unix domain socket
  21. WorkDir string // directory for unix domain socket
  22. HttpUrl string // transaction manager URL for HTTP connection
  23. Timeout uint // timeout for overall client call (seconds), zero means timeout disabled
  24. DialTimeout uint // timeout for connecting to unix socket (seconds)
  25. HttpIdleConnTimeout uint // timeout for idle http connection (seconds), zero means timeout disabled
  26. HttpWriteBufferSize int // size of http connection write buffer (bytes), if zero then uses http.Transport default
  27. HttpReadBufferSize int // size of http connection read buffer (bytes), if zero then uses http.Transport default
  28. TlsMode string // whether TLS is enabled on HTTP connection (can be "off" or "strict")
  29. TlsRootCA string // path to file containing certificate for root CA (defaults to host's certificates)
  30. TlsClientCert string // path to file containing client certificate (or chain of certs)
  31. TlsClientKey string // path to file containing client's private key
  32. TlsInsecureSkipVerify bool // if true then does not verify that server certificate is CA signed
  33. }
  34. var NoConnectionConfig = Config{
  35. ConnectionType: NoConnection,
  36. TlsMode: TlsOff,
  37. }
  38. var DefaultConfig = Config{
  39. Timeout: 5,
  40. DialTimeout: 1,
  41. HttpIdleConnTimeout: 10,
  42. TlsMode: TlsOff,
  43. }
  44. func IsSocketConfigured(cfg Config) bool {
  45. return cfg.ConnectionType == UnixDomainSocketConnection
  46. }
  47. // This will accept path as any of the following and return relevant configuration:
  48. // - path set to "ignore"
  49. // - path to an ipc file
  50. // - path to a config file
  51. func FetchConfigOrIgnore(path string) (Config, error) {
  52. if path == "" || strings.EqualFold(path, "ignore") {
  53. return NoConnectionConfig, nil
  54. }
  55. return FetchConfig(path)
  56. }
  57. // FetchConfig sets up the configuration for the connection to a txn manager.
  58. // It will accept a path to an ipc file or a path to a config file,
  59. // and returns the full configuration info for the specified type of connection.
  60. func FetchConfig(path string) (Config, error) {
  61. info, err := os.Lstat(path)
  62. if err != nil {
  63. return Config{}, fmt.Errorf("unable to check whether connection details are specified as a config file or ipc file '%s', due to: %s", path, err)
  64. }
  65. var cfg Config
  66. isSocket := info.Mode()&os.ModeSocket != 0
  67. if isSocket {
  68. cfg = DefaultConfig
  69. cfg.ConnectionType = UnixDomainSocketConnection
  70. cfg.WorkDir, cfg.Socket = filepath.Split(path)
  71. } else {
  72. cfg, err = LoadConfigFile(path)
  73. if err != nil {
  74. return Config{}, fmt.Errorf("error reading config from '%s' due to: %s", path, err)
  75. }
  76. }
  77. return cfg, nil
  78. }
  79. func LoadConfigFile(path string) (Config, error) {
  80. cfg := DefaultConfig
  81. if _, err := toml.DecodeFile(path, &cfg); err != nil {
  82. return Config{}, err
  83. }
  84. cfg.TlsMode = strings.ToLower(cfg.TlsMode)
  85. if cfg.Socket != "" {
  86. cfg.ConnectionType = UnixDomainSocketConnection
  87. } else if cfg.HttpUrl != "" {
  88. cfg.ConnectionType = HttpConnection
  89. } else {
  90. return Config{}, fmt.Errorf("either Socket or HTTP connection must be specified in config file")
  91. }
  92. return cfg, nil
  93. }
  94. func (cfg *Config) Validate() error {
  95. switch cfg.ConnectionType {
  96. case "": // no connection type defined
  97. case NoConnection:
  98. case UnixDomainSocketConnection:
  99. if len(cfg.Socket) == 0 { //sanity check - should never occur
  100. return fmt.Errorf("ipc file configuration is missing for private transaction manager connection")
  101. }
  102. if len(cfg.HttpUrl) != 0 {
  103. return fmt.Errorf("HTTP URL and unix ipc file cannot both be specified for private transaction manager connection")
  104. }
  105. if cfg.TlsMode != TlsOff {
  106. return fmt.Errorf("TLS is not supported over unix domain socket for private transaction manager connection")
  107. }
  108. case HttpConnection:
  109. if len(cfg.Socket) != 0 {
  110. return fmt.Errorf("HTTP URL and unix ipc file cannot both be specified for private transaction manager connection")
  111. }
  112. if len(cfg.HttpUrl) == 0 { //sanity check - should never occur
  113. return fmt.Errorf("URL configuration is missing for private transaction manager HTTP connection")
  114. }
  115. switch cfg.TlsMode {
  116. case TlsOff:
  117. //no action needed
  118. case TlsStrict:
  119. if !strings.Contains(strings.ToLower(cfg.HttpUrl), "https") {
  120. return fmt.Errorf("connection is configured with TLS but HTTPS url is not specified")
  121. }
  122. if (len(cfg.TlsClientCert) == 0 && len(cfg.TlsClientKey) != 0) || (len(cfg.TlsClientCert) != 0 && len(cfg.TlsClientKey) == 0) {
  123. return fmt.Errorf("invalid details for HTTP connection with TLS, configuration must specify both clientCert and clientKey, or neither one")
  124. }
  125. default:
  126. return fmt.Errorf("invalid value for TLS mode in config file, must be either OFF or STRICT")
  127. }
  128. }
  129. return nil
  130. }
  131. //
  132. // Setters for the various config fields
  133. //
  134. func (cfg *Config) SetSocket(socketPath string) {
  135. cfg.ConnectionType = UnixDomainSocketConnection
  136. workDir, socketFilename := filepath.Split(socketPath)
  137. if workDir != "" {
  138. cfg.WorkDir = workDir
  139. }
  140. cfg.Socket = socketFilename
  141. }
  142. func (cfg *Config) SetHttpUrl(httpUrl string) {
  143. cfg.ConnectionType = HttpConnection
  144. cfg.HttpUrl = httpUrl
  145. }
  146. func (cfg *Config) SetTimeout(timeout uint) {
  147. cfg.Timeout = timeout
  148. }
  149. func (cfg *Config) SetDialTimeout(dialTimeout uint) {
  150. cfg.DialTimeout = dialTimeout
  151. }
  152. func (cfg *Config) SetHttpIdleConnTimeout(httpIdleConnTimeout uint) {
  153. cfg.HttpIdleConnTimeout = httpIdleConnTimeout
  154. }
  155. func (cfg *Config) SetHttpWriteBufferSize(httpWriteBufferSize int) {
  156. cfg.HttpWriteBufferSize = httpWriteBufferSize
  157. }
  158. func (cfg *Config) SetHttpReadBufferSize(httpReadBufferSize int) {
  159. cfg.HttpReadBufferSize = httpReadBufferSize
  160. }
  161. func (cfg *Config) SetTlsMode(tlsMode string) {
  162. cfg.TlsMode = tlsMode
  163. }
  164. func (cfg *Config) SetTlsRootCA(tlsRootCA string) {
  165. cfg.TlsRootCA = tlsRootCA
  166. }
  167. func (cfg *Config) SetTlsClientCert(tlsClientCert string) {
  168. cfg.TlsClientCert = tlsClientCert
  169. }
  170. func (cfg *Config) SetTlsClientKey(tlsClientKey string) {
  171. cfg.TlsClientKey = tlsClientKey
  172. }
  173. func (cfg *Config) SetTlsInsecureSkipVerify(tlsInsecureSkipVerify bool) {
  174. cfg.TlsInsecureSkipVerify = tlsInsecureSkipVerify
  175. }