client_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. package apiclient
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "net/http/httptest"
  7. "net/url"
  8. "runtime"
  9. "testing"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/crowdsecurity/crowdsec/pkg/cwversion"
  12. log "github.com/sirupsen/logrus"
  13. )
  14. /*this is a ripoff of google/go-github approach :
  15. - setup a test http server along with a client that is configured to talk to test server
  16. - each test will then bind handler for the method(s) they want to try
  17. */
  18. func setup() (mux *http.ServeMux, serverURL string, teardown func()) {
  19. // mux is the HTTP request multiplexer used with the test server.
  20. mux = http.NewServeMux()
  21. baseURLPath := "/v1"
  22. apiHandler := http.NewServeMux()
  23. apiHandler.Handle(baseURLPath+"/", http.StripPrefix(baseURLPath, mux))
  24. // server is a test HTTP server used to provide mock API responses.
  25. server := httptest.NewServer(apiHandler)
  26. return mux, server.URL, server.Close
  27. }
  28. func testMethod(t *testing.T, r *http.Request, want string) {
  29. t.Helper()
  30. if got := r.Method; got != want {
  31. t.Errorf("Request method: %v, want %v", got, want)
  32. }
  33. }
  34. func TestNewClientOk(t *testing.T) {
  35. mux, urlx, teardown := setup()
  36. defer teardown()
  37. apiURL, err := url.Parse(urlx + "/")
  38. if err != nil {
  39. log.Fatalf("parsing api url: %s", apiURL)
  40. }
  41. client, err := NewClient(&Config{
  42. MachineID: "test_login",
  43. Password: "test_password",
  44. UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
  45. URL: apiURL,
  46. VersionPrefix: "v1",
  47. })
  48. if err != nil {
  49. t.Fatalf("new api client: %s", err.Error())
  50. }
  51. /*mock login*/
  52. mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) {
  53. w.WriteHeader(http.StatusOK)
  54. w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`))
  55. })
  56. mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) {
  57. testMethod(t, r, "GET")
  58. w.WriteHeader(http.StatusOK)
  59. })
  60. _, resp, err := client.Alerts.List(context.Background(), AlertsListOpts{})
  61. if err != nil {
  62. t.Fatalf("test Unable to list alerts : %+v", err)
  63. }
  64. if resp.Response.StatusCode != http.StatusOK {
  65. t.Fatalf("Alerts.List returned status: %d, want %d", resp.Response.StatusCode, http.StatusCreated)
  66. }
  67. }
  68. func TestNewClientKo(t *testing.T) {
  69. mux, urlx, teardown := setup()
  70. defer teardown()
  71. apiURL, err := url.Parse(urlx + "/")
  72. if err != nil {
  73. log.Fatalf("parsing api url: %s", apiURL)
  74. }
  75. client, err := NewClient(&Config{
  76. MachineID: "test_login",
  77. Password: "test_password",
  78. UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
  79. URL: apiURL,
  80. VersionPrefix: "v1",
  81. })
  82. if err != nil {
  83. t.Fatalf("new api client: %s", err.Error())
  84. }
  85. /*mock login*/
  86. mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) {
  87. w.WriteHeader(http.StatusUnauthorized)
  88. w.Write([]byte(`{"code": 401, "message" : "bad login/password"}`))
  89. })
  90. mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) {
  91. testMethod(t, r, "GET")
  92. w.WriteHeader(http.StatusOK)
  93. })
  94. _, _, err = client.Alerts.List(context.Background(), AlertsListOpts{})
  95. assert.Contains(t, err.Error(), `API error: bad login/password`)
  96. log.Printf("err-> %s", err)
  97. }
  98. func TestNewDefaultClient(t *testing.T) {
  99. mux, urlx, teardown := setup()
  100. defer teardown()
  101. apiURL, err := url.Parse(urlx + "/")
  102. if err != nil {
  103. log.Fatalf("parsing api url: %s", apiURL)
  104. }
  105. client, err := NewDefaultClient(apiURL, "/v1", "", nil)
  106. if err != nil {
  107. t.Fatalf("new api client: %s", err.Error())
  108. }
  109. mux.HandleFunc("/alerts", func(w http.ResponseWriter, r *http.Request) {
  110. w.WriteHeader(http.StatusUnauthorized)
  111. w.Write([]byte(`{"code": 401, "message" : "brr"}`))
  112. })
  113. _, _, err = client.Alerts.List(context.Background(), AlertsListOpts{})
  114. assert.Contains(t, err.Error(), `performing request: API error: brr`)
  115. log.Printf("err-> %s", err)
  116. }
  117. func TestNewClientRegisterKO(t *testing.T) {
  118. apiURL, err := url.Parse("http://127.0.0.1:4242/")
  119. if err != nil {
  120. t.Fatalf("parsing api url: %s", apiURL)
  121. }
  122. _, err = RegisterClient(&Config{
  123. MachineID: "test_login",
  124. Password: "test_password",
  125. UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
  126. URL: apiURL,
  127. VersionPrefix: "v1",
  128. }, &http.Client{})
  129. if runtime.GOOS != "windows" {
  130. assert.Contains(t, fmt.Sprintf("%s", err), "dial tcp 127.0.0.1:4242: connect: connection refused")
  131. } else {
  132. assert.Contains(t, fmt.Sprintf("%s", err), " No connection could be made because the target machine actively refused it.")
  133. }
  134. }
  135. func TestNewClientRegisterOK(t *testing.T) {
  136. log.SetLevel(log.TraceLevel)
  137. mux, urlx, teardown := setup()
  138. defer teardown()
  139. /*mock login*/
  140. mux.HandleFunc("/watchers", func(w http.ResponseWriter, r *http.Request) {
  141. testMethod(t, r, "POST")
  142. w.WriteHeader(http.StatusOK)
  143. w.Write([]byte(`{"code": 200, "expire": "2030-01-02T15:04:05Z", "token": "oklol"}`))
  144. })
  145. apiURL, err := url.Parse(urlx + "/")
  146. if err != nil {
  147. t.Fatalf("parsing api url: %s", apiURL)
  148. }
  149. client, err := RegisterClient(&Config{
  150. MachineID: "test_login",
  151. Password: "test_password",
  152. UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
  153. URL: apiURL,
  154. VersionPrefix: "v1",
  155. }, &http.Client{})
  156. if err != nil {
  157. t.Fatalf("while registering client : %s", err)
  158. }
  159. log.Printf("->%T", client)
  160. }
  161. func TestNewClientBadAnswer(t *testing.T) {
  162. log.SetLevel(log.TraceLevel)
  163. mux, urlx, teardown := setup()
  164. defer teardown()
  165. /*mock login*/
  166. mux.HandleFunc("/watchers", func(w http.ResponseWriter, r *http.Request) {
  167. testMethod(t, r, "POST")
  168. w.WriteHeader(http.StatusUnauthorized)
  169. w.Write([]byte(`bad`))
  170. })
  171. apiURL, err := url.Parse(urlx + "/")
  172. if err != nil {
  173. t.Fatalf("parsing api url: %s", apiURL)
  174. }
  175. _, err = RegisterClient(&Config{
  176. MachineID: "test_login",
  177. Password: "test_password",
  178. UserAgent: fmt.Sprintf("crowdsec/%s", cwversion.VersionStr()),
  179. URL: apiURL,
  180. VersionPrefix: "v1",
  181. }, &http.Client{})
  182. assert.Contains(t, fmt.Sprintf("%s", err), `invalid body: invalid character 'b' looking for beginning of value`)
  183. }