config_test.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. package guerrilla
  2. import (
  3. "github.com/flashmob/go-guerrilla/backends"
  4. "github.com/flashmob/go-guerrilla/log"
  5. "github.com/flashmob/go-guerrilla/tests/testcert"
  6. "io/ioutil"
  7. "os"
  8. "strings"
  9. "testing"
  10. "time"
  11. )
  12. // a configuration file with a dummy backend
  13. //
  14. var configJsonA = `
  15. {
  16. "log_file" : "./tests/testlog",
  17. "log_level" : "debug",
  18. "pid_file" : "tests/go-guerrilla.pid",
  19. "allowed_hosts": ["spam4.me","grr.la"],
  20. "backend": {
  21. "processors": {
  22. "debugger": {
  23. "log_received_mails": true
  24. }
  25. },
  26. "gateways" : {
  27. "default" : {
  28. "save_workers_size": 1,
  29. "save_process": "HeadersParser|Header|Hasher|Debugger"
  30. }
  31. }
  32. },
  33. "servers" : [
  34. {
  35. "is_enabled" : true,
  36. "host_name":"mail.guerrillamail.com",
  37. "max_size": 100017,
  38. "timeout":160,
  39. "listen_interface":"127.0.0.1:2526",
  40. "max_clients": 2,
  41. "tls" : {
  42. "start_tls_on":false,
  43. "tls_always_on":false,
  44. "private_key_file":"config_test.go",
  45. "public_key_file":"config_test.go"
  46. }
  47. },
  48. {
  49. "is_enabled" : true,
  50. "host_name":"mail2.guerrillamail.com",
  51. "max_size":1000001,
  52. "timeout":180,
  53. "listen_interface":"127.0.0.1:2527",
  54. "max_clients":1,
  55. "tls" : {
  56. "private_key_file":"./tests/mail2.guerrillamail.com.key.pem",
  57. "public_key_file":"./tests/mail2.guerrillamail.com.cert.pem",
  58. "tls_always_on":false,
  59. "start_tls_on":true
  60. }
  61. },
  62. {
  63. "is_enabled" : true,
  64. "host_name":"mail.stopme.com",
  65. "max_size": 100017,
  66. "timeout":160,
  67. "listen_interface":"127.0.0.1:9999",
  68. "max_clients": 2,
  69. "tls" : {
  70. "private_key_file":"config_test.go",
  71. "public_key_file":"config_test.go",
  72. "start_tls_on":false,
  73. "tls_always_on":false
  74. }
  75. },
  76. {
  77. "is_enabled" : true,
  78. "host_name":"mail.disableme.com",
  79. "max_size": 100017,
  80. "timeout":160,
  81. "listen_interface":"127.0.0.1:3333",
  82. "max_clients": 2,
  83. "tls" : {
  84. "private_key_file":"config_test.go",
  85. "public_key_file":"config_test.go",
  86. "start_tls_on":false,
  87. "tls_always_on":false
  88. }
  89. }
  90. ]
  91. }
  92. `
  93. // B is A's configuration with different values from B
  94. // 127.0.0.1:4654 will be added
  95. // A's 127.0.0.1:3333 is disabled
  96. // B's 127.0.0.1:9999 is removed
  97. var configJsonB = `
  98. {
  99. "log_file" : "./tests/testlog",
  100. "log_level" : "debug",
  101. "pid_file" : "tests/different-go-guerrilla.pid",
  102. "allowed_hosts": ["spam4.me","grr.la","newhost.com"],
  103. "backend" : {
  104. "processors" : {
  105. "debugger": {
  106. "log_received_mails" : true
  107. }
  108. },
  109. "gateways" : {
  110. "default" : {
  111. "save_workers_size": 1,
  112. "save_process": "HeadersParser|Header|Hasher|Debugger"
  113. }
  114. }
  115. },
  116. "servers" : [
  117. {
  118. "is_enabled" : true,
  119. "host_name":"mail.guerrillamail.com",
  120. "max_size": 100017,
  121. "timeout":161,
  122. "listen_interface":"127.0.0.1:2526",
  123. "max_clients": 3,
  124. "tls" : {
  125. "private_key_file":"./tests/mail2.guerrillamail.com.key.pem",
  126. "public_key_file": "./tests/mail2.guerrillamail.com.cert.pem",
  127. "start_tls_on":false,
  128. "tls_always_on":true
  129. }
  130. },
  131. {
  132. "is_enabled" : true,
  133. "host_name":"mail2.guerrillamail.com",
  134. "max_size": 100017,
  135. "timeout":160,
  136. "listen_interface":"127.0.0.1:2527",
  137. "log_file" : "./tests/testlog",
  138. "max_clients": 2,
  139. "tls" : {
  140. "private_key_file":"./tests/mail2.guerrillamail.com.key.pem",
  141. "public_key_file": "./tests/mail2.guerrillamail.com.cert.pem",
  142. "start_tls_on":true,
  143. "tls_always_on":false
  144. }
  145. },
  146. {
  147. "is_enabled" : true,
  148. "host_name":"mail.guerrillamail.com",
  149. "max_size":1000001,
  150. "timeout":180,
  151. "listen_interface":"127.0.0.1:4654",
  152. "max_clients":1,
  153. "tls" : {
  154. "private_key_file":"config_test.go",
  155. "public_key_file":"config_test.go",
  156. "start_tls_on":false,
  157. "tls_always_on":false
  158. }
  159. },
  160. {
  161. "is_enabled" : false,
  162. "host_name":"mail.disbaleme.com",
  163. "max_size": 100017,
  164. "timeout":160,
  165. "listen_interface":"127.0.0.1:3333",
  166. "max_clients": 2,
  167. "tls" : {
  168. "private_key_file":"config_test.go",
  169. "public_key_file":"config_test.go",
  170. "start_tls_on":false,
  171. "tls_always_on":false
  172. }
  173. }
  174. ]
  175. }
  176. `
  177. func TestConfigLoad(t *testing.T) {
  178. if err := testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "./tests/"); err != nil {
  179. t.Error(err)
  180. }
  181. defer func() {
  182. if err := deleteIfExists("../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  183. t.Error(err)
  184. }
  185. if err := deleteIfExists("../tests/mail2.guerrillamail.com.key.pem"); err != nil {
  186. t.Error(err)
  187. }
  188. }()
  189. ac := &AppConfig{}
  190. if err := ac.Load([]byte(configJsonA)); err != nil {
  191. t.Error("Cannot load config |", err)
  192. t.SkipNow()
  193. }
  194. expectedLen := 4
  195. if len(ac.Servers) != expectedLen {
  196. t.Error("len(ac.Servers), expected", expectedLen, "got", len(ac.Servers))
  197. t.SkipNow()
  198. }
  199. // did we got the timestamps?
  200. if ac.Servers[0].TLS._privateKeyFileMtime <= 0 {
  201. t.Error("failed to read timestamp for _privateKeyFileMtime, got", ac.Servers[0].TLS._privateKeyFileMtime)
  202. }
  203. }
  204. // Test the sample config to make sure a valid one is given!
  205. func TestSampleConfig(t *testing.T) {
  206. fileName := "goguerrilla.conf.sample"
  207. if jsonBytes, err := ioutil.ReadFile(fileName); err == nil {
  208. ac := &AppConfig{}
  209. if err := ac.Load(jsonBytes); err != nil {
  210. // sample config can have broken tls certs
  211. if strings.Index(err.Error(), "cannot use TLS config for [127.0.0.1:25") != 0 {
  212. t.Error("Cannot load config", fileName, "|", err)
  213. t.FailNow()
  214. }
  215. }
  216. } else {
  217. t.Error("Error reading", fileName, "|", err)
  218. }
  219. }
  220. // make sure that we get all the config change events
  221. func TestConfigChangeEvents(t *testing.T) {
  222. if err := testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "./tests/"); err != nil {
  223. t.Error(err)
  224. }
  225. defer func() {
  226. if err := deleteIfExists("../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  227. t.Error(err)
  228. }
  229. if err := deleteIfExists("../tests/mail2.guerrillamail.com.key.pem"); err != nil {
  230. t.Error(err)
  231. }
  232. }()
  233. oldconf := &AppConfig{}
  234. if err := oldconf.Load([]byte(configJsonA)); err != nil {
  235. t.Error(err)
  236. }
  237. logger, _ := log.GetLogger(oldconf.LogFile, oldconf.LogLevel)
  238. oldconf.BackendConfig = backends.BackendConfig{
  239. backends.ConfigProcessors: {"debugger": {"log_received_mails": true}},
  240. backends.ConfigGateways: {
  241. "default": {
  242. "save_process": "HeadersParser|Header|Hasher|Debugger",
  243. },
  244. },
  245. }
  246. backend, err := backends.New("default", oldconf.BackendConfig, logger)
  247. if err != nil {
  248. t.Error("failed to create backend", err)
  249. return
  250. }
  251. app, err := New(oldconf, logger, backend)
  252. if err != nil {
  253. t.Error("cannot create daemon", err)
  254. }
  255. // simulate timestamp change
  256. time.Sleep(time.Second + time.Millisecond*500)
  257. if err := os.Chtimes(oldconf.Servers[1].TLS.PrivateKeyFile, time.Now(), time.Now()); err != nil {
  258. t.Error(err)
  259. }
  260. if err := os.Chtimes(oldconf.Servers[1].TLS.PublicKeyFile, time.Now(), time.Now()); err != nil {
  261. t.Error(err)
  262. }
  263. newconf := &AppConfig{}
  264. if err := newconf.Load([]byte(configJsonB)); err != nil {
  265. t.Error(err)
  266. }
  267. newconf.Servers[0].LogFile = log.OutputOff.String() // test for log file change
  268. newconf.LogLevel = log.InfoLevel.String()
  269. newconf.LogFile = "off"
  270. expectedEvents := map[Event]bool{
  271. EventConfigPidFile: false,
  272. EventConfigLogFile: false,
  273. EventConfigLogLevel: false,
  274. EventConfigAllowedHosts: false,
  275. EventConfigServerNew: false, // 127.0.0.1:4654 will be added
  276. EventConfigServerRemove: false, // 127.0.0.1:9999 server removed
  277. EventConfigServerStop: false, // 127.0.0.1:3333: server (disabled)
  278. EventConfigServerLogFile: false, // 127.0.0.1:2526
  279. EventConfigServerLogReopen: false, // 127.0.0.1:2527
  280. EventConfigServerTimeout: false, // 127.0.0.1:2526 timeout
  281. //"server_change:tls_config": false, // 127.0.0.1:2526
  282. EventConfigServerMaxClients: false, // 127.0.0.1:2526
  283. EventConfigServerTLSConfig: false, // 127.0.0.1:2527 timestamp changed on certificates
  284. }
  285. toUnsubscribe := map[Event]func(c *AppConfig){}
  286. toUnsubscribeSrv := map[Event]func(c *ServerConfig){}
  287. for event := range expectedEvents {
  288. // Put in anon func since range is overwriting event
  289. func(e Event) {
  290. if strings.Contains(e.String(), "config_change") {
  291. f := func(c *AppConfig) {
  292. expectedEvents[e] = true
  293. }
  294. _ = app.Subscribe(event, f)
  295. toUnsubscribe[event] = f
  296. } else {
  297. // must be a server config change then
  298. f := func(c *ServerConfig) {
  299. expectedEvents[e] = true
  300. }
  301. _ = app.Subscribe(event, f)
  302. toUnsubscribeSrv[event] = f
  303. }
  304. }(event)
  305. }
  306. // emit events
  307. newconf.EmitChangeEvents(oldconf, app)
  308. // unsubscribe
  309. for unevent, unfun := range toUnsubscribe {
  310. _ = app.Unsubscribe(unevent, unfun)
  311. }
  312. for unevent, unfun := range toUnsubscribeSrv {
  313. _ = app.Unsubscribe(unevent, unfun)
  314. }
  315. for event, val := range expectedEvents {
  316. if val == false {
  317. t.Error("Did not fire config change event:", event)
  318. t.FailNow()
  319. }
  320. }
  321. // don't forget to reset
  322. if err := os.Truncate(oldconf.LogFile, 0); err != nil {
  323. t.Error(err)
  324. }
  325. }