ssl_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package ssl_test
  18. import (
  19. "context"
  20. "crypto/tls"
  21. "encoding/json"
  22. "fmt"
  23. "io/ioutil"
  24. "net"
  25. "net/http"
  26. "time"
  27. . "github.com/onsi/ginkgo/v2"
  28. . "github.com/onsi/gomega"
  29. "github.com/apisix/manager-api/test/e2e/base"
  30. )
  31. var _ = Describe("SSL Basic", func() {
  32. var (
  33. testCert []byte
  34. testKey []byte
  35. apisixKey []byte
  36. validBody []byte
  37. validBody2 []byte
  38. invalidBody []byte
  39. createRouteBody []byte
  40. )
  41. var err error
  42. testCert, err = ioutil.ReadFile("../../certs/test2.crt")
  43. Expect(err).To(BeNil())
  44. testKey, err = ioutil.ReadFile("../../certs/test2.key")
  45. Expect(err).To(BeNil())
  46. apisixKey, err = ioutil.ReadFile("../../certs/apisix.key")
  47. Expect(err).To(BeNil())
  48. validBody, err = json.Marshal(map[string]interface{}{
  49. "id": "1",
  50. "cert": string(testCert),
  51. "key": string(testKey),
  52. "labels": map[string]string{
  53. "build": "16",
  54. "env": "production",
  55. "version": "v3",
  56. },
  57. })
  58. Expect(err).To(BeNil())
  59. validBody2, err = json.Marshal(map[string]interface{}{
  60. "id": "1",
  61. "cert": string(testCert),
  62. "key": string(testKey),
  63. "labels": map[string]string{
  64. "build": "16",
  65. "env": "production",
  66. "version": "v2",
  67. },
  68. })
  69. Expect(err).To(BeNil())
  70. invalidBody, err = json.Marshal(map[string]string{
  71. "id": "1",
  72. "cert": string(testCert),
  73. "key": string(apisixKey),
  74. })
  75. Expect(err).To(BeNil())
  76. tempBody := map[string]interface{}{
  77. "name": "route1",
  78. "uri": "/hello_",
  79. "hosts": []string{"test2.com", "*.test2.com"},
  80. "upstream": map[string]interface{}{
  81. "nodes": []map[string]interface{}{
  82. {
  83. "host": base.UpstreamIp,
  84. "port": 1980,
  85. "weight": 1,
  86. },
  87. },
  88. "type": "roundrobin",
  89. },
  90. }
  91. createRouteBody, err = json.Marshal(tempBody)
  92. Expect(err).To(BeNil())
  93. It("without certificate", func() {
  94. // Before configuring SSL, make a HTTPS request
  95. http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
  96. http.DefaultTransport.(*http.Transport).DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
  97. if addr == "www.test2.com:9443" {
  98. addr = "127.0.0.1:9443"
  99. }
  100. dialer := &net.Dialer{}
  101. return dialer.DialContext(ctx, network, addr)
  102. }
  103. _, err := http.Get("https://www.test2.com:9443")
  104. Expect(fmt.Sprintf("%s", err)).Should(Equal("Get \"https://www.test2.com:9443\": remote error: tls: internal error"))
  105. })
  106. DescribeTable("test ssl basic", func(testCase base.HttpTestCase) {
  107. base.RunTestCase(testCase)
  108. },
  109. Entry("create ssl failed", base.HttpTestCase{
  110. Object: base.ManagerApiExpect(),
  111. Method: http.MethodPost,
  112. Path: "/apisix/admin/ssl",
  113. Body: string(invalidBody),
  114. Headers: map[string]string{"Authorization": base.GetToken()},
  115. ExpectStatus: http.StatusBadRequest,
  116. ExpectBody: "SSL parse failed: key and cert don't match",
  117. Sleep: base.SleepTime,
  118. }),
  119. Entry("create ssl successfully", base.HttpTestCase{
  120. Object: base.ManagerApiExpect(),
  121. Method: http.MethodPost,
  122. Path: "/apisix/admin/ssl",
  123. Body: string(validBody),
  124. Headers: map[string]string{"Authorization": base.GetToken()},
  125. ExpectStatus: http.StatusOK,
  126. Sleep: base.SleepTime,
  127. }),
  128. Entry("validate ssl cert and key (valid)", base.HttpTestCase{
  129. Object: base.ManagerApiExpect(),
  130. Method: http.MethodPost,
  131. Path: "/apisix/admin/check_ssl_cert",
  132. Body: string(validBody),
  133. Headers: map[string]string{"Authorization": base.GetToken()},
  134. ExpectBody: "\"code\":0,\"message\":\"\"",
  135. ExpectStatus: http.StatusOK,
  136. }),
  137. Entry("validate ssl cert and key (valid)", base.HttpTestCase{
  138. Object: base.ManagerApiExpect(),
  139. Method: http.MethodPost,
  140. Path: "/apisix/admin/check_ssl_cert",
  141. Body: string(invalidBody),
  142. Headers: map[string]string{"Authorization": base.GetToken()},
  143. ExpectBody: "key and cert don't match",
  144. ExpectStatus: http.StatusOK,
  145. }),
  146. Entry("check ssl labels", base.HttpTestCase{
  147. Object: base.ManagerApiExpect(),
  148. Method: http.MethodGet,
  149. Path: "/apisix/admin/ssl/1",
  150. Headers: map[string]string{"Authorization": base.GetToken()},
  151. ExpectStatus: http.StatusOK,
  152. ExpectBody: "\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v3\"",
  153. }),
  154. Entry("update ssl", base.HttpTestCase{
  155. Object: base.ManagerApiExpect(),
  156. Method: http.MethodPut,
  157. Path: "/apisix/admin/ssl/1",
  158. Body: string(validBody2),
  159. Headers: map[string]string{"Authorization": base.GetToken()},
  160. ExpectStatus: http.StatusOK,
  161. Sleep: base.SleepTime,
  162. }),
  163. Entry("check ssl labels", base.HttpTestCase{
  164. Object: base.ManagerApiExpect(),
  165. Method: http.MethodGet,
  166. Path: "/apisix/admin/ssl/1",
  167. Headers: map[string]string{"Authorization": base.GetToken()},
  168. ExpectStatus: http.StatusOK,
  169. ExpectBody: "\"labels\":{\"build\":\"16\",\"env\":\"production\",\"version\":\"v2\"",
  170. Sleep: base.SleepTime,
  171. }),
  172. Entry("check host exist", base.HttpTestCase{
  173. Object: base.ManagerApiExpect(),
  174. Method: http.MethodPost,
  175. Path: "/apisix/admin/check_ssl_exists",
  176. Body: `{"hosts": ["www.test2.com"]}`,
  177. Headers: map[string]string{"Authorization": base.GetToken()},
  178. ExpectStatus: http.StatusOK,
  179. }),
  180. Entry("check host not exist", base.HttpTestCase{
  181. Object: base.ManagerApiExpect(),
  182. Method: http.MethodPost,
  183. Path: "/apisix/admin/check_ssl_exists",
  184. Body: `{"hosts": ["www.test3.com"]}`,
  185. Headers: map[string]string{"Authorization": base.GetToken()},
  186. ExpectStatus: http.StatusNotFound,
  187. ExpectBody: "SSL cert not exists for sni:www.test3.com",
  188. }),
  189. Entry("create route", base.HttpTestCase{
  190. Object: base.ManagerApiExpect(),
  191. Method: http.MethodPut,
  192. Path: "/apisix/admin/routes/r1",
  193. Body: string(createRouteBody),
  194. Headers: map[string]string{"Authorization": base.GetToken()},
  195. ExpectStatus: http.StatusOK,
  196. }),
  197. Entry("get the route just created to trigger removing `key`", base.HttpTestCase{
  198. Object: base.ManagerApiExpect(),
  199. Method: http.MethodGet,
  200. Path: "/apisix/admin/routes/r1",
  201. Headers: map[string]string{"Authorization": base.GetToken()},
  202. ExpectStatus: http.StatusOK,
  203. Sleep: base.SleepTime,
  204. }),
  205. Entry("hit the route just created using HTTPS", base.HttpTestCase{
  206. Object: base.APISIXHTTPSExpect(),
  207. Method: http.MethodGet,
  208. Path: "/hello_",
  209. ExpectStatus: http.StatusOK,
  210. Headers: map[string]string{"Host": "www.test2.com"},
  211. ExpectBody: "hello world\n",
  212. Sleep: base.SleepTime,
  213. }),
  214. Entry("disable SSL", base.HttpTestCase{
  215. Object: base.ManagerApiExpect(),
  216. Method: http.MethodPatch,
  217. Path: "/apisix/admin/ssl/1",
  218. Body: `{
  219. "status": 0
  220. }`,
  221. Headers: map[string]string{"Authorization": base.GetToken()},
  222. ExpectStatus: http.StatusOK,
  223. ExpectBody: "\"status\":0",
  224. }),
  225. )
  226. It("test disable SSL HTTPS request", func() {
  227. // try again after disable SSL, make a HTTPS request
  228. time.Sleep(time.Duration(500) * time.Millisecond)
  229. _, err := http.Get("https://www.test2.com:9443")
  230. Expect(fmt.Sprintf("%s", err)).Should(Equal("Get \"https://www.test2.com:9443\": remote error: tls: internal error"))
  231. })
  232. DescribeTable("test ssl basic", func(testCase base.HttpTestCase) {
  233. base.RunTestCase(testCase)
  234. },
  235. Entry("enable SSL", base.HttpTestCase{
  236. Object: base.ManagerApiExpect(),
  237. Method: http.MethodPatch,
  238. Path: "/apisix/admin/ssl/1/status",
  239. Body: `1`,
  240. Headers: map[string]string{
  241. "Authorization": base.GetToken(),
  242. "Content-Type": "text/plain",
  243. },
  244. ExpectStatus: http.StatusOK,
  245. ExpectBody: "\"status\":1",
  246. }),
  247. Entry("hit the route using HTTPS, make sure enable successful", base.HttpTestCase{
  248. Object: base.APISIXHTTPSExpect(),
  249. Method: http.MethodGet,
  250. Path: "/hello_",
  251. Headers: map[string]string{"Host": "www.test2.com"},
  252. ExpectStatus: http.StatusOK,
  253. ExpectBody: "hello world\n",
  254. Sleep: base.SleepTime,
  255. }),
  256. Entry("delete SSL", base.HttpTestCase{
  257. Object: base.ManagerApiExpect(),
  258. Method: http.MethodDelete,
  259. Path: "/apisix/admin/ssl/1",
  260. Headers: map[string]string{"Authorization": base.GetToken()},
  261. ExpectStatus: http.StatusOK,
  262. }),
  263. Entry("delete route", base.HttpTestCase{
  264. Object: base.ManagerApiExpect(),
  265. Method: http.MethodDelete,
  266. Path: "/apisix/admin/routes/r1",
  267. Headers: map[string]string{"Authorization": base.GetToken()},
  268. ExpectStatus: http.StatusOK,
  269. }),
  270. Entry("hit the route just deleted", base.HttpTestCase{
  271. Object: base.APISIXExpect(),
  272. Method: http.MethodGet,
  273. Path: "/hello_",
  274. ExpectStatus: http.StatusNotFound,
  275. ExpectBody: "{\"error_msg\":\"404 Route Not Found\"}\n",
  276. Sleep: base.SleepTime,
  277. }))
  278. })