roundtripper_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /*
  15. Copyright 2015 The Kubernetes Authors.
  16. Licensed under the Apache License, Version 2.0 (the "License");
  17. you may not use this file except in compliance with the License.
  18. You may obtain a copy of the License at
  19. http://www.apache.org/licenses/LICENSE-2.0
  20. Unless required by applicable law or agreed to in writing, software
  21. distributed under the License is distributed on an "AS IS" BASIS,
  22. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  23. See the License for the specific language governing permissions and
  24. limitations under the License.
  25. */
  26. package spdy
  27. import (
  28. "fmt"
  29. "io"
  30. "net/http"
  31. "net/http/httptest"
  32. "strings"
  33. "sync/atomic"
  34. "testing"
  35. "yunion.io/x/onecloud/pkg/util/httpstream"
  36. )
  37. // be sure to unset environment variable https_proxy (if exported) before testing, otherwise the testing will fail unexpectedly.
  38. /*func TestRoundTripAndNewConnection(t *testing.T) {
  39. for _, redirect := range []bool{false, true} {
  40. t.Run(fmt.Sprintf("redirect = %t", redirect), func(t *testing.T) {
  41. localhostPool := x509.NewCertPool()
  42. if !localhostPool.AppendCertsFromPEM(localhostCert) {
  43. t.Errorf("error setting up localhostCert pool")
  44. }
  45. httpsServerInvalidHostname := func(h http.Handler) *httptest.Server {
  46. cert, err := tls.X509KeyPair(exampleCert, exampleKey)
  47. if err != nil {
  48. t.Errorf("https (invalid hostname): proxy_test: %v", err)
  49. }
  50. ts := httptest.NewUnstartedServer(h)
  51. ts.TLS = &tls.Config{
  52. Certificates: []tls.Certificate{cert},
  53. }
  54. ts.StartTLS()
  55. return ts
  56. }
  57. httpsServerValidHostname := func(h http.Handler) *httptest.Server {
  58. cert, err := tls.X509KeyPair(localhostCert, localhostKey)
  59. if err != nil {
  60. t.Errorf("https (valid hostname): proxy_test: %v", err)
  61. }
  62. ts := httptest.NewUnstartedServer(h)
  63. ts.TLS = &tls.Config{
  64. Certificates: []tls.Certificate{cert},
  65. }
  66. ts.StartTLS()
  67. return ts
  68. }
  69. testCases := map[string]struct {
  70. serverFunc func(http.Handler) *httptest.Server
  71. proxyServerFunc func(http.Handler) *httptest.Server
  72. proxyAuth *url.Userinfo
  73. clientTLS *tls.Config
  74. serverConnectionHeader string
  75. serverUpgradeHeader string
  76. serverStatusCode int
  77. shouldError bool
  78. }{
  79. "no headers": {
  80. serverFunc: httptest.NewServer,
  81. serverConnectionHeader: "",
  82. serverUpgradeHeader: "",
  83. serverStatusCode: http.StatusSwitchingProtocols,
  84. shouldError: true,
  85. },
  86. "no upgrade header": {
  87. serverFunc: httptest.NewServer,
  88. serverConnectionHeader: "Upgrade",
  89. serverUpgradeHeader: "",
  90. serverStatusCode: http.StatusSwitchingProtocols,
  91. shouldError: true,
  92. },
  93. "no connection header": {
  94. serverFunc: httptest.NewServer,
  95. serverConnectionHeader: "",
  96. serverUpgradeHeader: "SPDY/3.1",
  97. serverStatusCode: http.StatusSwitchingProtocols,
  98. shouldError: true,
  99. },
  100. "no switching protocol status code": {
  101. serverFunc: httptest.NewServer,
  102. serverConnectionHeader: "Upgrade",
  103. serverUpgradeHeader: "SPDY/3.1",
  104. serverStatusCode: http.StatusForbidden,
  105. shouldError: true,
  106. },
  107. "http": {
  108. serverFunc: httptest.NewServer,
  109. serverConnectionHeader: "Upgrade",
  110. serverUpgradeHeader: "SPDY/3.1",
  111. serverStatusCode: http.StatusSwitchingProtocols,
  112. shouldError: false,
  113. },
  114. "https (invalid hostname + InsecureSkipVerify)": {
  115. serverFunc: httpsServerInvalidHostname,
  116. clientTLS: &tls.Config{InsecureSkipVerify: true},
  117. serverConnectionHeader: "Upgrade",
  118. serverUpgradeHeader: "SPDY/3.1",
  119. serverStatusCode: http.StatusSwitchingProtocols,
  120. shouldError: false,
  121. },
  122. "https (invalid hostname + hostname verification)": {
  123. serverFunc: httpsServerInvalidHostname,
  124. clientTLS: &tls.Config{InsecureSkipVerify: false},
  125. serverConnectionHeader: "Upgrade",
  126. serverUpgradeHeader: "SPDY/3.1",
  127. serverStatusCode: http.StatusSwitchingProtocols,
  128. shouldError: true,
  129. },
  130. "https (valid hostname + RootCAs)": {
  131. serverFunc: httpsServerValidHostname,
  132. clientTLS: &tls.Config{RootCAs: localhostPool},
  133. serverConnectionHeader: "Upgrade",
  134. serverUpgradeHeader: "SPDY/3.1",
  135. serverStatusCode: http.StatusSwitchingProtocols,
  136. shouldError: false,
  137. },
  138. "proxied http->http": {
  139. serverFunc: httptest.NewServer,
  140. proxyServerFunc: httptest.NewServer,
  141. serverConnectionHeader: "Upgrade",
  142. serverUpgradeHeader: "SPDY/3.1",
  143. serverStatusCode: http.StatusSwitchingProtocols,
  144. shouldError: false,
  145. },
  146. "proxied https (invalid hostname + InsecureSkipVerify) -> http": {
  147. serverFunc: httptest.NewServer,
  148. proxyServerFunc: httpsServerInvalidHostname,
  149. clientTLS: &tls.Config{InsecureSkipVerify: true},
  150. serverConnectionHeader: "Upgrade",
  151. serverUpgradeHeader: "SPDY/3.1",
  152. serverStatusCode: http.StatusSwitchingProtocols,
  153. shouldError: false,
  154. },
  155. "proxied https with auth (invalid hostname + InsecureSkipVerify) -> http": {
  156. serverFunc: httptest.NewServer,
  157. proxyServerFunc: httpsServerInvalidHostname,
  158. proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
  159. clientTLS: &tls.Config{InsecureSkipVerify: true},
  160. serverConnectionHeader: "Upgrade",
  161. serverUpgradeHeader: "SPDY/3.1",
  162. serverStatusCode: http.StatusSwitchingProtocols,
  163. shouldError: false,
  164. },
  165. "proxied https (invalid hostname + hostname verification) -> http": {
  166. serverFunc: httptest.NewServer,
  167. proxyServerFunc: httpsServerInvalidHostname,
  168. clientTLS: &tls.Config{InsecureSkipVerify: false},
  169. serverConnectionHeader: "Upgrade",
  170. serverUpgradeHeader: "SPDY/3.1",
  171. serverStatusCode: http.StatusSwitchingProtocols,
  172. shouldError: true, // fails because the client doesn't trust the proxy
  173. },
  174. "proxied https (valid hostname + RootCAs) -> http": {
  175. serverFunc: httptest.NewServer,
  176. proxyServerFunc: httpsServerValidHostname,
  177. clientTLS: &tls.Config{RootCAs: localhostPool},
  178. serverConnectionHeader: "Upgrade",
  179. serverUpgradeHeader: "SPDY/3.1",
  180. serverStatusCode: http.StatusSwitchingProtocols,
  181. shouldError: false,
  182. },
  183. "proxied https with auth (valid hostname + RootCAs) -> http": {
  184. serverFunc: httptest.NewServer,
  185. proxyServerFunc: httpsServerValidHostname,
  186. proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
  187. clientTLS: &tls.Config{RootCAs: localhostPool},
  188. serverConnectionHeader: "Upgrade",
  189. serverUpgradeHeader: "SPDY/3.1",
  190. serverStatusCode: http.StatusSwitchingProtocols,
  191. shouldError: false,
  192. },
  193. "proxied https (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": {
  194. serverFunc: httpsServerInvalidHostname,
  195. proxyServerFunc: httpsServerInvalidHostname,
  196. clientTLS: &tls.Config{InsecureSkipVerify: true},
  197. serverConnectionHeader: "Upgrade",
  198. serverUpgradeHeader: "SPDY/3.1",
  199. serverStatusCode: http.StatusSwitchingProtocols,
  200. shouldError: false, // works because the test proxy ignores TLS errors
  201. },
  202. "proxied https with auth (invalid hostname + InsecureSkipVerify) -> https (invalid hostname)": {
  203. serverFunc: httpsServerInvalidHostname,
  204. proxyServerFunc: httpsServerInvalidHostname,
  205. proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
  206. clientTLS: &tls.Config{InsecureSkipVerify: true},
  207. serverConnectionHeader: "Upgrade",
  208. serverUpgradeHeader: "SPDY/3.1",
  209. serverStatusCode: http.StatusSwitchingProtocols,
  210. shouldError: false, // works because the test proxy ignores TLS errors
  211. },
  212. "proxied https (invalid hostname + hostname verification) -> https (invalid hostname)": {
  213. serverFunc: httpsServerInvalidHostname,
  214. proxyServerFunc: httpsServerInvalidHostname,
  215. clientTLS: &tls.Config{InsecureSkipVerify: false},
  216. serverConnectionHeader: "Upgrade",
  217. serverUpgradeHeader: "SPDY/3.1",
  218. serverStatusCode: http.StatusSwitchingProtocols,
  219. shouldError: true, // fails because the client doesn't trust the proxy
  220. },
  221. "proxied https (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": {
  222. serverFunc: httpsServerValidHostname,
  223. proxyServerFunc: httpsServerValidHostname,
  224. clientTLS: &tls.Config{RootCAs: localhostPool},
  225. serverConnectionHeader: "Upgrade",
  226. serverUpgradeHeader: "SPDY/3.1",
  227. serverStatusCode: http.StatusSwitchingProtocols,
  228. shouldError: false,
  229. },
  230. "proxied https with auth (valid hostname + RootCAs) -> https (valid hostname + RootCAs)": {
  231. serverFunc: httpsServerValidHostname,
  232. proxyServerFunc: httpsServerValidHostname,
  233. proxyAuth: url.UserPassword("proxyuser", "proxypasswd"),
  234. clientTLS: &tls.Config{RootCAs: localhostPool},
  235. serverConnectionHeader: "Upgrade",
  236. serverUpgradeHeader: "SPDY/3.1",
  237. serverStatusCode: http.StatusSwitchingProtocols,
  238. shouldError: false,
  239. },
  240. }
  241. for k, testCase := range testCases {
  242. server := testCase.serverFunc(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  243. if testCase.shouldError {
  244. if e, a := httpstream.HeaderUpgrade, req.Header.Get(httpstream.HeaderConnection); e != a {
  245. t.Fatalf("%s: Expected connection=upgrade header, got '%s", k, a)
  246. }
  247. w.Header().Set(httpstream.HeaderConnection, testCase.serverConnectionHeader)
  248. w.Header().Set(httpstream.HeaderUpgrade, testCase.serverUpgradeHeader)
  249. w.WriteHeader(testCase.serverStatusCode)
  250. return
  251. }
  252. streamCh := make(chan httpstream.Stream)
  253. responseUpgrader := NewResponseUpgrader()
  254. spdyConn := responseUpgrader.UpgradeResponse(w, req, func(s httpstream.Stream, replySent <-chan struct{}) error {
  255. streamCh <- s
  256. return nil
  257. })
  258. if spdyConn == nil {
  259. t.Fatalf("%s: unexpected nil spdyConn", k)
  260. }
  261. defer spdyConn.Close()
  262. stream := <-streamCh
  263. io.Copy(stream, stream)
  264. }))
  265. defer server.Close()
  266. serverURL, err := url.Parse(server.URL)
  267. if err != nil {
  268. t.Fatalf("%s: Error creating request: %s", k, err)
  269. }
  270. req, err := http.NewRequest("GET", server.URL, nil)
  271. if err != nil {
  272. t.Fatalf("%s: Error creating request: %s", k, err)
  273. }
  274. spdyTransport := NewSpdyRoundTripper(testCase.clientTLS, redirect, redirect)
  275. var proxierCalled bool
  276. var proxyCalledWithHost string
  277. var proxyCalledWithAuth bool
  278. var proxyCalledWithAuthHeader string
  279. if testCase.proxyServerFunc != nil {
  280. proxyHandler := goproxy.NewProxyHttpServer()
  281. proxyHandler.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
  282. proxyCalledWithHost = host
  283. proxyAuthHeaderName := "Proxy-Authorization"
  284. _, proxyCalledWithAuth = ctx.Req.Header[proxyAuthHeaderName]
  285. proxyCalledWithAuthHeader = ctx.Req.Header.Get(proxyAuthHeaderName)
  286. return goproxy.OkConnect, host
  287. })
  288. proxy := testCase.proxyServerFunc(proxyHandler)
  289. spdyTransport.proxier = func(proxierReq *http.Request) (*url.URL, error) {
  290. proxierCalled = true
  291. proxyURL, err := url.Parse(proxy.URL)
  292. if err != nil {
  293. return nil, err
  294. }
  295. proxyURL.User = testCase.proxyAuth
  296. return proxyURL, nil
  297. }
  298. defer proxy.Close()
  299. }
  300. client := &http.Client{Transport: spdyTransport}
  301. resp, err := client.Do(req)
  302. var conn httpstream.Connection
  303. if err == nil {
  304. conn, err = spdyTransport.NewConnection(resp)
  305. }
  306. haveErr := err != nil
  307. if e, a := testCase.shouldError, haveErr; e != a {
  308. t.Fatalf("%s: shouldError=%t, got %t: %v", k, e, a, err)
  309. }
  310. if testCase.shouldError {
  311. continue
  312. }
  313. defer conn.Close()
  314. if resp.StatusCode != http.StatusSwitchingProtocols {
  315. t.Fatalf("%s: expected http 101 switching protocols, got %d", k, resp.StatusCode)
  316. }
  317. stream, err := conn.CreateStream(http.Header{})
  318. if err != nil {
  319. t.Fatalf("%s: error creating client stream: %s", k, err)
  320. }
  321. n, err := stream.Write([]byte("hello"))
  322. if err != nil {
  323. t.Fatalf("%s: error writing to stream: %s", k, err)
  324. }
  325. if n != 5 {
  326. t.Fatalf("%s: Expected to write 5 bytes, but actually wrote %d", k, n)
  327. }
  328. b := make([]byte, 5)
  329. n, err = stream.Read(b)
  330. if err != nil {
  331. t.Fatalf("%s: error reading from stream: %s", k, err)
  332. }
  333. if n != 5 {
  334. t.Fatalf("%s: Expected to read 5 bytes, but actually read %d", k, n)
  335. }
  336. if e, a := "hello", string(b[0:n]); e != a {
  337. t.Fatalf("%s: expected '%s', got '%s'", k, e, a)
  338. }
  339. if testCase.proxyServerFunc != nil {
  340. if !proxierCalled {
  341. t.Fatalf("%s: Expected to use a proxy but proxier in SpdyRoundTripper wasn't called", k)
  342. }
  343. if proxyCalledWithHost != serverURL.Host {
  344. t.Fatalf("%s: Expected to see a call to the proxy for backend %q, got %q", k, serverURL.Host, proxyCalledWithHost)
  345. }
  346. }
  347. var expectedProxyAuth string
  348. if testCase.proxyAuth != nil {
  349. encodedCredentials := base64.StdEncoding.EncodeToString([]byte(testCase.proxyAuth.String()))
  350. expectedProxyAuth = "Basic " + encodedCredentials
  351. }
  352. if len(expectedProxyAuth) == 0 && proxyCalledWithAuth {
  353. t.Fatalf("%s: Proxy authorization unexpected, got %q", k, proxyCalledWithAuthHeader)
  354. }
  355. if proxyCalledWithAuthHeader != expectedProxyAuth {
  356. t.Fatalf("%s: Expected to see a call to the proxy with credentials %q, got %q", k, testCase.proxyAuth, proxyCalledWithAuthHeader)
  357. }
  358. }
  359. })
  360. }
  361. }*/
  362. func TestRoundTripRedirects(t *testing.T) {
  363. tests := []struct {
  364. redirects int32
  365. expectSuccess bool
  366. }{
  367. {0, true},
  368. {1, true},
  369. {9, true},
  370. {10, false},
  371. }
  372. for _, test := range tests {
  373. t.Run(fmt.Sprintf("with %d redirects", test.redirects), func(t *testing.T) {
  374. var redirects int32 = 0
  375. server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
  376. if redirects < test.redirects {
  377. atomic.AddInt32(&redirects, 1)
  378. http.Redirect(w, req, "redirect", http.StatusFound)
  379. return
  380. }
  381. streamCh := make(chan httpstream.Stream)
  382. responseUpgrader := NewResponseUpgrader()
  383. spdyConn := responseUpgrader.UpgradeResponse(w, req, func(s httpstream.Stream, replySent <-chan struct{}) error {
  384. streamCh <- s
  385. return nil
  386. })
  387. if spdyConn == nil {
  388. t.Fatalf("unexpected nil spdyConn")
  389. }
  390. defer spdyConn.Close()
  391. stream := <-streamCh
  392. io.Copy(stream, stream)
  393. }))
  394. defer server.Close()
  395. req, err := http.NewRequest("GET", server.URL, nil)
  396. if err != nil {
  397. t.Fatalf("Error creating request: %s", err)
  398. }
  399. spdyTransport := NewSpdyRoundTripper(nil, true, true)
  400. client := &http.Client{Transport: spdyTransport}
  401. resp, err := client.Do(req)
  402. if test.expectSuccess {
  403. if err != nil {
  404. t.Fatalf("error calling Do: %v", err)
  405. }
  406. } else {
  407. if err == nil {
  408. t.Fatalf("expecting an error")
  409. } else if !strings.Contains(err.Error(), "too many redirects") && !strings.Contains(err.Error(), "stopped after") {
  410. t.Fatalf("expecting too many redirects, got %v", err)
  411. }
  412. return
  413. }
  414. conn, err := spdyTransport.NewConnection(resp)
  415. if err != nil {
  416. t.Fatalf("error calling NewConnection: %v", err)
  417. }
  418. defer conn.Close()
  419. if resp.StatusCode != http.StatusSwitchingProtocols {
  420. t.Fatalf("expected http 101 switching protocols, got %d", resp.StatusCode)
  421. }
  422. stream, err := conn.CreateStream(http.Header{})
  423. if err != nil {
  424. t.Fatalf("error creating client stream: %s", err)
  425. }
  426. n, err := stream.Write([]byte("hello"))
  427. if err != nil {
  428. t.Fatalf("error writing to stream: %s", err)
  429. }
  430. if n != 5 {
  431. t.Fatalf("Expected to write 5 bytes, but actually wrote %d", n)
  432. }
  433. b := make([]byte, 5)
  434. n, err = stream.Read(b)
  435. if err != nil {
  436. t.Fatalf("error reading from stream: %s", err)
  437. }
  438. if n != 5 {
  439. t.Fatalf("Expected to read 5 bytes, but actually read %d", n)
  440. }
  441. if e, a := "hello", string(b[0:n]); e != a {
  442. t.Fatalf("expected '%s', got '%s'", e, a)
  443. }
  444. })
  445. }
  446. }
  447. // exampleCert was generated from crypto/tls/generate_cert.go with the following command:
  448. //
  449. // go run generate_cert.go --rsa-bits 512 --host example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
  450. var exampleCert = []byte(`-----BEGIN CERTIFICATE-----
  451. MIIBdzCCASGgAwIBAgIRAOVTAdPnfbS5V85mfS90TfIwDQYJKoZIhvcNAQELBQAw
  452. EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
  453. MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
  454. QQCoVSqeu8TBvF+70T7Jm4340YQNhds6IxjRoifenYodAO1dnKGrcbF266DJGunh
  455. nIjQH7B12tduhl0fLK4Ezf7/AgMBAAGjUDBOMA4GA1UdDwEB/wQEAwICpDATBgNV
  456. HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBYGA1UdEQQPMA2CC2V4
  457. YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA0EAk1kVa5uZ/AzwYDVcS9bpM/czwjjV
  458. xq3VeSCfmNa2uNjbFvodmCRwZOHUvipAMGCUCV6j5vMrJ8eMj8tCQ36W9A==
  459. -----END CERTIFICATE-----`)
  460. var exampleKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
  461. MIIBOgIBAAJBAKhVKp67xMG8X7vRPsmbjfjRhA2F2zojGNGiJ96dih0A7V2coatx
  462. sXbroMka6eGciNAfsHXa126GXR8srgTN/v8CAwEAAQJASdzdD7vKsUwMIejGCUb1
  463. fAnLTPfAY3lFCa+CmR89nE22dAoRDv+5RbnBsZ58BazPNJHrsVPRlfXB3OQmSQr0
  464. SQIhANoJhs+xOJE/i8nJv0uAbzKyiD1YkvRkta0GpUOULyAVAiEAxaQus3E/SuqD
  465. P7y5NeJnE7X6XkyC35zrsJRkz7orE8MCIHdDjsI8pjyNDeGqwUCDWE/a6DrmIDwe
  466. emHSqMN2YvChAiEAnxLCM9NWaenOsaIoP+J1rDuvw+4499nJKVqGuVrSCRkCIEqK
  467. 4KSchPMc3x8M/uhw9oWTtKFmjA/PPh0FsWCdKrEy
  468. -----END RSA PRIVATE KEY-----`)
  469. // localhostCert was generated from crypto/tls/generate_cert.go with the following command:
  470. //
  471. // go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
  472. var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
  473. MIIBjzCCATmgAwIBAgIRAKpi2WmTcFrVjxrl5n5YDUEwDQYJKoZIhvcNAQELBQAw
  474. EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
  475. MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
  476. QQC9fEbRszP3t14Gr4oahV7zFObBI4TfA5i7YnlMXeLinb7MnvT4bkfOJzE6zktn
  477. 59zP7UiHs3l4YOuqrjiwM413AgMBAAGjaDBmMA4GA1UdDwEB/wQEAwICpDATBgNV
  478. HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MC4GA1UdEQQnMCWCC2V4
  479. YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUA
  480. A0EAUsVE6KMnza/ZbodLlyeMzdo7EM/5nb5ywyOxgIOCf0OOLHsPS9ueGLQX9HEG
  481. //yjTXuhNcUugExIjM/AIwAZPQ==
  482. -----END CERTIFICATE-----`)
  483. // localhostKey is the private key for localhostCert.
  484. var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
  485. MIIBOwIBAAJBAL18RtGzM/e3XgavihqFXvMU5sEjhN8DmLtieUxd4uKdvsye9Phu
  486. R84nMTrOS2fn3M/tSIezeXhg66quOLAzjXcCAwEAAQJBAKcRxH9wuglYLBdI/0OT
  487. BLzfWPZCEw1vZmMR2FF1Fm8nkNOVDPleeVGTWoOEcYYlQbpTmkGSxJ6ya+hqRi6x
  488. goECIQDx3+X49fwpL6B5qpJIJMyZBSCuMhH4B7JevhGGFENi3wIhAMiNJN5Q3UkL
  489. IuSvv03kaPR5XVQ99/UeEetUgGvBcABpAiBJSBzVITIVCGkGc7d+RCf49KTCIklv
  490. bGWObufAR8Ni4QIgWpILjW8dkGg8GOUZ0zaNA6Nvt6TIv2UWGJ4v5PoV98kCIQDx
  491. rIiZs5QbKdycsv9gQJzwQAogC8o04X3Zz3dsoX+h4A==
  492. -----END RSA PRIVATE KEY-----`)