github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/testutil.go (about)

     1  package gateway
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"compress/gzip"
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"encoding/binary"
    10  	"encoding/json"
    11  	"fmt"
    12  	"io"
    13  	"io/ioutil"
    14  	"math/rand"
    15  	"net"
    16  	"net/http"
    17  	"net/http/httptest"
    18  	"os"
    19  	"path/filepath"
    20  	"runtime"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"testing"
    25  	"time"
    26  
    27  	jwt "github.com/dgrijalva/jwt-go"
    28  	"github.com/go-redis/redis"
    29  	"github.com/gorilla/mux"
    30  	"github.com/gorilla/websocket"
    31  	uuid "github.com/satori/go.uuid"
    32  	"golang.org/x/net/context"
    33  
    34  	"github.com/TykTechnologies/tyk/apidef"
    35  	"github.com/TykTechnologies/tyk/cli"
    36  	"github.com/TykTechnologies/tyk/config"
    37  	"github.com/TykTechnologies/tyk/storage"
    38  	"github.com/TykTechnologies/tyk/test"
    39  	"github.com/TykTechnologies/tyk/user"
    40  )
    41  
    42  var (
    43  	// to register to, but never used
    44  	discardMuxer = mux.NewRouter()
    45  
    46  	// to simulate time ticks for tests that do reloads
    47  	reloadTick = make(chan time.Time)
    48  
    49  	// Used to store the test bundles:
    50  	testMiddlewarePath, _ = ioutil.TempDir("", "tyk-middleware-path")
    51  
    52  	mockHandle *test.DnsMockHandle
    53  
    54  	testServerRouter  *mux.Router
    55  	defaultTestConfig config.Config
    56  
    57  	EnableTestDNSMock = true
    58  )
    59  
    60  // ReloadMachinery is a helper struct to use when writing tests that do manual
    61  // gateway reloads
    62  type ReloadMachinery struct {
    63  	run    bool
    64  	count  int
    65  	cycles int
    66  	mu     sync.RWMutex
    67  }
    68  
    69  // OnQueued is called when a reload has been queued. This increments the queue
    70  // count
    71  func (r *ReloadMachinery) OnQueued() {
    72  	r.mu.Lock()
    73  	defer r.mu.Unlock()
    74  	if r.run {
    75  		r.count++
    76  	}
    77  }
    78  
    79  // OnReload is called when a reload has been completed. This increments the
    80  // reload cycles count.
    81  func (r *ReloadMachinery) OnReload() {
    82  	r.mu.Lock()
    83  	defer r.mu.Unlock()
    84  	if r.run {
    85  		r.cycles++
    86  	}
    87  }
    88  
    89  // Reloaded returns true if a read has occured since r was enabled
    90  func (r *ReloadMachinery) Reloaded() bool {
    91  	r.mu.RLock()
    92  	defer r.mu.RUnlock()
    93  	return r.cycles > 0
    94  }
    95  
    96  // Enable  when callled it will allow r to keep track of reload cycles and queues
    97  func (r *ReloadMachinery) Enable() {
    98  	r.mu.Lock()
    99  	defer r.mu.Unlock()
   100  	r.run = true
   101  }
   102  
   103  // Disable turns off tracking of reload cycles and queues
   104  func (r *ReloadMachinery) Disable() {
   105  	r.mu.Lock()
   106  	defer r.mu.Unlock()
   107  	r.run = true
   108  	r.count = 0
   109  	r.cycles = 0
   110  }
   111  
   112  // Reset sets reloads counts and queues to 0
   113  func (r *ReloadMachinery) Reset() {
   114  	r.mu.Lock()
   115  	defer r.mu.Unlock()
   116  	r.count = 0
   117  	r.cycles = 0
   118  }
   119  
   120  // Queued returns true if any queue happened
   121  func (r *ReloadMachinery) Queued() bool {
   122  	r.mu.RLock()
   123  	defer r.mu.RUnlock()
   124  	return r.count > 0
   125  }
   126  
   127  // EnsureQueued this will block until any queue happens. It will timeout after
   128  // 100ms
   129  func (r *ReloadMachinery) EnsureQueued(t *testing.T) {
   130  	deadline := time.NewTimer(100 * time.Millisecond)
   131  	defer deadline.Stop()
   132  	tick := time.NewTicker(time.Millisecond)
   133  	defer tick.Stop()
   134  	for {
   135  		select {
   136  		case <-deadline.C:
   137  			t.Fatal("Timedout waiting for reload to be queue")
   138  		case <-tick.C:
   139  			if r.Queued() {
   140  				return
   141  			}
   142  		}
   143  	}
   144  }
   145  
   146  // EnsureReloaded this will block until any reload happens. It will timeout after
   147  // 100ms
   148  func (r *ReloadMachinery) EnsureReloaded(t *testing.T) {
   149  	deadline := time.NewTimer(100 * time.Millisecond)
   150  	defer deadline.Stop()
   151  	tick := time.NewTicker(time.Millisecond)
   152  	defer tick.Stop()
   153  	for {
   154  		select {
   155  		case <-deadline.C:
   156  			t.Fatal("Timedout waiting for reload to be queue")
   157  		case <-tick.C:
   158  			if r.Reloaded() {
   159  				return
   160  			}
   161  		}
   162  	}
   163  }
   164  
   165  // Tick triggers reload
   166  func (r *ReloadMachinery) Tick() {
   167  	reloadTick <- time.Time{}
   168  }
   169  
   170  // TickOk triggers a reload and ensures a queue happend and a reload cycle
   171  // happens. This will block until all the cases are met.
   172  func (r *ReloadMachinery) TickOk(t *testing.T) {
   173  	r.EnsureQueued(t)
   174  	reloadTick <- time.Time{}
   175  	r.EnsureReloaded(t)
   176  }
   177  
   178  // ReloadTestCase use this when in any test for gateway reloads
   179  var ReloadTestCase = &ReloadMachinery{}
   180  
   181  func InitTestMain(ctx context.Context, m *testing.M, genConf ...func(globalConf *config.Config)) int {
   182  	setTestMode(true)
   183  	testServerRouter = testHttpHandler()
   184  	testServer := &http.Server{
   185  		Addr:           testHttpListen,
   186  		Handler:        testServerRouter,
   187  		ReadTimeout:    1 * time.Second,
   188  		WriteTimeout:   1 * time.Second,
   189  		MaxHeaderBytes: 1 << 20,
   190  	}
   191  
   192  	globalConf := config.Global()
   193  	if err := config.WriteDefault("", &globalConf); err != nil {
   194  		panic(err)
   195  	}
   196  	globalConf.Storage.Database = rand.Intn(15)
   197  	var err error
   198  	globalConf.AppPath, err = ioutil.TempDir("", "tyk-test-")
   199  	if err != nil {
   200  		panic(err)
   201  	}
   202  	globalConf.EnableAnalytics = true
   203  	globalConf.AnalyticsConfig.EnableGeoIP = true
   204  	_, b, _, _ := runtime.Caller(0)
   205  	gatewayPath := filepath.Dir(b)
   206  	rootPath := filepath.Dir(gatewayPath)
   207  	globalConf.AnalyticsConfig.GeoIPDBLocation = filepath.Join(rootPath, "testdata", "MaxMind-DB-test-ipv4-24.mmdb")
   208  	globalConf.EnableJSVM = true
   209  	globalConf.HashKeyFunction = storage.HashMurmur64
   210  	globalConf.Monitor.EnableTriggerMonitors = true
   211  	globalConf.AnalyticsConfig.NormaliseUrls.Enabled = true
   212  	globalConf.AllowInsecureConfigs = true
   213  	// Enable coprocess and bundle downloader:
   214  	globalConf.CoProcessOptions.EnableCoProcess = true
   215  	globalConf.EnableBundleDownloader = true
   216  	globalConf.BundleBaseURL = testHttpBundles
   217  	globalConf.MiddlewarePath = testMiddlewarePath
   218  	purgeTicker = make(chan time.Time)
   219  	rpcPurgeTicker = make(chan time.Time)
   220  	// force ipv4 for now, to work around the docker bug affecting
   221  	// Go 1.8 and ealier
   222  	globalConf.ListenAddress = "127.0.0.1"
   223  	if len(genConf) > 0 {
   224  		genConf[0](&globalConf)
   225  	}
   226  
   227  	if EnableTestDNSMock {
   228  		mockHandle, err = test.InitDNSMock(test.DomainsToAddresses, nil)
   229  		if err != nil {
   230  			panic(err)
   231  		}
   232  
   233  		defer mockHandle.ShutdownDnsMock()
   234  	}
   235  
   236  	go func() {
   237  		err := testServer.ListenAndServe()
   238  		if err != nil {
   239  			log.Warn("testServer.ListenAndServe() err: ", err.Error())
   240  		}
   241  	}()
   242  
   243  	defer testServer.Shutdown(context.Background())
   244  
   245  	CoProcessInit()
   246  	afterConfSetup(&globalConf)
   247  	defaultTestConfig = globalConf
   248  	config.SetGlobal(globalConf)
   249  	if err := emptyRedis(); err != nil {
   250  		panic(err)
   251  	}
   252  	cli.Init(VERSION, confPaths)
   253  	initialiseSystem(ctx)
   254  	// Small part of start()
   255  	loadAPIEndpoints(mainRouter())
   256  	if analytics.GeoIPDB == nil {
   257  		panic("GeoIPDB was not initialized")
   258  	}
   259  
   260  	go startPubSubLoop()
   261  	go reloadLoop(ctx, reloadTick, ReloadTestCase.OnReload)
   262  	go reloadQueueLoop(ctx, ReloadTestCase.OnQueued)
   263  	go reloadSimulation()
   264  	exitCode := m.Run()
   265  	os.RemoveAll(config.Global().AppPath)
   266  	return exitCode
   267  }
   268  
   269  func ResetTestConfig() {
   270  	config.SetGlobal(defaultTestConfig)
   271  }
   272  
   273  func emptyRedis() error {
   274  	addr := config.Global().Storage.Host + ":" + strconv.Itoa(config.Global().Storage.Port)
   275  	c := redis.NewClient(&redis.Options{Addr: addr})
   276  	defer c.Close()
   277  	dbName := strconv.Itoa(config.Global().Storage.Database)
   278  	if err := c.Do("SELECT", dbName).Err(); err != nil {
   279  		return err
   280  	}
   281  	err := c.FlushDB().Err()
   282  	return err
   283  }
   284  
   285  // simulate reloads in the background, i.e. writes to
   286  // global variables that should not be accessed in a
   287  // racy way like the policies and api specs maps.
   288  func reloadSimulation() {
   289  	for {
   290  		policiesMu.Lock()
   291  		policiesByID["_"] = user.Policy{}
   292  		delete(policiesByID, "_")
   293  		policiesMu.Unlock()
   294  		apisMu.Lock()
   295  		old := apiSpecs
   296  		apiSpecs = append(apiSpecs, nil)
   297  		apiSpecs = old
   298  		apisByID["_"] = nil
   299  		delete(apisByID, "_")
   300  		apisMu.Unlock()
   301  		time.Sleep(5 * time.Millisecond)
   302  	}
   303  }
   304  
   305  // map[bundleName]map[fileName]fileContent
   306  var testBundles = map[string]map[string]string{}
   307  var testBundleMu sync.Mutex
   308  
   309  func RegisterJSFileMiddleware(apiid string, files map[string]string) {
   310  	os.MkdirAll(config.Global().MiddlewarePath+"/"+apiid+"/post", 0755)
   311  	os.MkdirAll(config.Global().MiddlewarePath+"/"+apiid+"/pre", 0755)
   312  
   313  	for file, content := range files {
   314  		ioutil.WriteFile(config.Global().MiddlewarePath+"/"+apiid+"/"+file, []byte(content), 0755)
   315  	}
   316  }
   317  
   318  func RegisterBundle(name string, files map[string]string) string {
   319  	testBundleMu.Lock()
   320  	defer testBundleMu.Unlock()
   321  
   322  	bundleID := name + "-" + uuid.NewV4().String() + ".zip"
   323  	testBundles[bundleID] = files
   324  
   325  	return bundleID
   326  }
   327  
   328  func bundleHandleFunc(w http.ResponseWriter, r *http.Request) {
   329  	testBundleMu.Lock()
   330  	defer testBundleMu.Unlock()
   331  
   332  	bundleName := strings.Replace(r.URL.Path, "/bundles/", "", -1)
   333  	bundle, exists := testBundles[bundleName]
   334  	if !exists {
   335  		log.Warning(testBundles)
   336  		http.Error(w, "Bundle not found", http.StatusNotFound)
   337  		return
   338  	}
   339  
   340  	w.Header().Set("Content-Type", "application/zip")
   341  
   342  	z := zip.NewWriter(w)
   343  	for name, content := range bundle {
   344  		f, _ := z.Create(name)
   345  		f.Write([]byte(content))
   346  	}
   347  	z.Close()
   348  }
   349  func mainRouter() *mux.Router {
   350  	return getMainRouter(defaultProxyMux)
   351  }
   352  
   353  func mainProxy() *proxy {
   354  	return defaultProxyMux.getProxy(config.Global().ListenPort)
   355  }
   356  
   357  func controlProxy() *proxy {
   358  	p := defaultProxyMux.getProxy(config.Global().ControlAPIPort)
   359  	if p != nil {
   360  		return p
   361  	}
   362  	return mainProxy()
   363  }
   364  
   365  func EnablePort(port int, protocol string) {
   366  	c := config.Global()
   367  	if c.PortWhiteList == nil {
   368  		c.PortWhiteList = map[string]config.PortWhiteList{
   369  			protocol: {
   370  				Ports: []int{port},
   371  			},
   372  		}
   373  	} else {
   374  		m, ok := c.PortWhiteList[protocol]
   375  		if !ok {
   376  			m = config.PortWhiteList{
   377  				Ports: []int{port},
   378  			}
   379  		} else {
   380  			m.Ports = append(m.Ports, port)
   381  		}
   382  		c.PortWhiteList[protocol] = m
   383  	}
   384  	config.SetGlobal(c)
   385  }
   386  
   387  func getMainRouter(m *proxyMux) *mux.Router {
   388  	var protocol string
   389  	if config.Global().HttpServerOptions.UseSSL {
   390  		protocol = "https"
   391  	} else {
   392  		protocol = "http"
   393  	}
   394  	return m.router(config.Global().ListenPort, protocol)
   395  }
   396  
   397  type TestHttpResponse struct {
   398  	Method  string
   399  	URI     string
   400  	Url     string
   401  	Body    string
   402  	Headers map[string]string
   403  	Form    map[string]string
   404  }
   405  
   406  // ProxyHandler Proxies requests through to their final destination, if they make it through the middleware chain.
   407  func ProxyHandler(p *ReverseProxy, apiSpec *APISpec) http.Handler {
   408  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   409  		baseMid := BaseMiddleware{Spec: apiSpec, Proxy: p}
   410  		handler := SuccessHandler{baseMid}
   411  		// Skip all other execution
   412  		handler.ServeHTTP(w, r)
   413  	})
   414  }
   415  
   416  const (
   417  	// We need a static port so that the urls can be used in static
   418  	// test data, and to prevent the requests from being randomized
   419  	// for checksums. Port 16500 should be obscure and unused.
   420  	testHttpListen = "127.0.0.1:16500"
   421  	// Accepts any http requests on /, only allows GET on /get, etc.
   422  	// All return a JSON with request info.
   423  	TestHttpAny           = "http://" + testHttpListen
   424  	TestHttpGet           = TestHttpAny + "/get"
   425  	testHttpPost          = TestHttpAny + "/post"
   426  	testGraphQLDataSource = TestHttpAny + "/graphql-data-source"
   427  	testRESTDataSource    = TestHttpAny + "/rest-data-source"
   428  	testHttpJWK           = TestHttpAny + "/jwk.json"
   429  	testHttpJWKDER        = TestHttpAny + "/jwk-der.json"
   430  	testHttpBundles       = TestHttpAny + "/bundles/"
   431  	testReloadGroup       = TestHttpAny + "/groupReload"
   432  
   433  	// Nothing should be listening on port 16501 - useful for
   434  	// testing TCP and HTTP failures.
   435  	testHttpFailure    = "127.0.0.1:16501"
   436  	testHttpFailureAny = "http://" + testHttpFailure
   437  	MockOrgID          = "507f1f77bcf86cd799439011"
   438  )
   439  
   440  func testHttpHandler() *mux.Router {
   441  	var upgrader = websocket.Upgrader{
   442  		ReadBufferSize:  1024,
   443  		WriteBufferSize: 1024,
   444  	}
   445  
   446  	wsHandler := func(w http.ResponseWriter, req *http.Request) {
   447  		conn, err := upgrader.Upgrade(w, req, nil)
   448  		if err != nil {
   449  			http.Error(w, fmt.Sprintf("cannot upgrade: %v", err), http.StatusInternalServerError)
   450  		}
   451  
   452  		// start simple reader/writer per connection
   453  		go func() {
   454  			for {
   455  				mt, p, err := conn.ReadMessage()
   456  				if err != nil {
   457  					return
   458  				}
   459  				conn.WriteMessage(mt, []byte("reply to message: "+string(p)))
   460  			}
   461  		}()
   462  	}
   463  
   464  	httpError := func(w http.ResponseWriter, status int) {
   465  		http.Error(w, http.StatusText(status), status)
   466  	}
   467  	writeDetails := func(w http.ResponseWriter, r *http.Request) {
   468  		if err := r.ParseForm(); err != nil {
   469  			httpError(w, http.StatusInternalServerError)
   470  			return
   471  		}
   472  		r.URL.Opaque = r.URL.RawPath
   473  		w.Header().Set("X-Tyk-Test", "1")
   474  		body, _ := ioutil.ReadAll(r.Body)
   475  
   476  		err := json.NewEncoder(w).Encode(TestHttpResponse{
   477  			Method:  r.Method,
   478  			URI:     r.RequestURI,
   479  			Url:     r.URL.String(),
   480  			Headers: firstVals(r.Header),
   481  			Form:    firstVals(r.Form),
   482  			Body:    string(body),
   483  		})
   484  		if err != nil {
   485  			httpError(w, http.StatusInternalServerError)
   486  		}
   487  	}
   488  	handleMethod := func(method string) http.HandlerFunc {
   489  		return func(w http.ResponseWriter, r *http.Request) {
   490  			if method != "" && r.Method != method {
   491  				httpError(w, http.StatusMethodNotAllowed)
   492  			} else {
   493  				writeDetails(w, r)
   494  			}
   495  		}
   496  	}
   497  
   498  	// use gorilla's mux as it allows to cancel URI cleaning
   499  	// (it is not configurable in standard http mux)
   500  	r := mux.NewRouter()
   501  
   502  	r.HandleFunc("/get", handleMethod("GET"))
   503  	r.HandleFunc("/post", handleMethod("POST"))
   504  	r.HandleFunc("/ws", wsHandler)
   505  	r.HandleFunc("/jwk.json", func(w http.ResponseWriter, r *http.Request) {
   506  		io.WriteString(w, jwkTestJson)
   507  	})
   508  	r.HandleFunc("/jwk-der.json", func(w http.ResponseWriter, r *http.Request) {
   509  		io.WriteString(w, jwkTestDERJson)
   510  	})
   511  	r.HandleFunc("/compressed", func(w http.ResponseWriter, r *http.Request) {
   512  		response := "This is a compressed response"
   513  		w.Header().Set("Content-Encoding", "gzip")
   514  		gz := gzip.NewWriter(w)
   515  		json.NewEncoder(gz).Encode(response)
   516  		gz.Close()
   517  	})
   518  	r.HandleFunc("/groupReload", groupResetHandler)
   519  	r.HandleFunc("/bundles/{rest:.*}", bundleHandleFunc)
   520  	r.HandleFunc("/errors/{status}", func(w http.ResponseWriter, r *http.Request) {
   521  		statusCode, _ := strconv.Atoi(mux.Vars(r)["status"])
   522  		httpError(w, statusCode)
   523  	})
   524  	r.HandleFunc("/{rest:.*}", handleMethod(""))
   525  
   526  	return r
   527  }
   528  
   529  const jwkTestJson = `{
   530      "keys": [{
   531          "alg": "RS256",
   532          "kty": "RSA",
   533          "use": "sig",
   534          "x5c": ["Ci0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tCk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBeXFaNHJ3S0Y4cUNFeFM3a3BZNGMKbkphLzM3Rk1rSk5rYWxaM091c2xMQjBvUkw4VDRjOTRrZEY0YWVOelNGa1NlMm45OUlCSTZTc2w3OXZiZk1aYgordDA2TDBROTRrKy9QMzd4NysvUkpaaWZmNHkxVkdqcm5ybk1JMml1OWw0aUJCUll6Tm1HNmVibHJvRU1NV2xnCms1dHlzSGd4QjU5Q1NOSWNEOWdxazFoeDRuL0ZnT212S3NmUWdXSE5sUFNEVFJjV0dXR2hCMi9YZ05WWUcycE8KbFF4QVBxTGhCSGVxR1RYQmJQZkdGOWNIeml4cHNQcjZHdGJ6UHdoc1EvOGJQeG9KN2hkZm4rcnp6dGtzM2Q2KwpIV1VSY3lOVExSZTBtalhqamVlOVo2K2daK0grZlM0cG5QOXRxVDdJZ1U2ZVBVV1Rwam9pUHRMZXhnc0FhL2N0CmpRSURBUUFCCi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQo="],
   535          "n": "xofiG8gsnv9-I_g-5OWTLhaZtgAGq1QEsBCPK9lmLqhuonHe8lT-nK1DM49f6J9QgaOjZ3DB50QkhBysnIFNcXFyzaYIPMoccvuHLPgdBawX4WYKm5gficD0WB0XnTt4sqTI5usFpuop9vvW44BwVGhRqMT7c11gA8TSWMBxDI4A5ARc4MuQtfm64oN-JQodSztArwb9wcmH8WrBvSUkR4pyi9MT8W27gqJ2e2Xn8jgGnswNQWOyCTN84PawOYaN-2ORHeIea1g-URln1bofcHN73vZCIrVbE6iA2D7Ybh22AVrCfunekEDEe2GZfLZLejiZiBWG7enJhcrQIzAQGw",
   536          "e": "AQAB",
   537          "kid": "12345",
   538          "x5t": "12345"
   539      }]
   540  }`
   541  
   542  // This has public key encoded as PKIX, ASN.1 DER form.
   543  const jwkTestDERJson = `{
   544      "keys": [{
   545          "alg": "RS256",
   546          "kty": "RSA",
   547          "use": "sig",
   548          "x5c": ["MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqZ4rwKF8qCExS7kpY4cnJa/37FMkJNkalZ3OuslLB0oRL8T4c94kdF4aeNzSFkSe2n99IBI6Ssl79vbfMZb+t06L0Q94k+/P37x7+/RJZiff4y1VGjrnrnMI2iu9l4iBBRYzNmG6eblroEMMWlgk5tysHgxB59CSNIcD9gqk1hx4n/FgOmvKsfQgWHNlPSDTRcWGWGhB2/XgNVYG2pOlQxAPqLhBHeqGTXBbPfGF9cHzixpsPr6GtbzPwhsQ/8bPxoJ7hdfn+rzztks3d6+HWURcyNTLRe0mjXjjee9Z6+gZ+H+fS4pnP9tqT7IgU6ePUWTpjoiPtLexgsAa/ctjQIDAQAB"],
   549          "n": "xofiG8gsnv9-I_g-5OWTLhaZtgAGq1QEsBCPK9lmLqhuonHe8lT-nK1DM49f6J9QgaOjZ3DB50QkhBysnIFNcXFyzaYIPMoccvuHLPgdBawX4WYKm5gficD0WB0XnTt4sqTI5usFpuop9vvW44BwVGhRqMT7c11gA8TSWMBxDI4A5ARc4MuQtfm64oN-JQodSztArwb9wcmH8WrBvSUkR4pyi9MT8W27gqJ2e2Xn8jgGnswNQWOyCTN84PawOYaN-2ORHeIea1g-URln1bofcHN73vZCIrVbE6iA2D7Ybh22AVrCfunekEDEe2GZfLZLejiZiBWG7enJhcrQIzAQGw",
   550          "e": "AQAB",
   551          "kid": "12345",
   552          "x5t": "12345"
   553      }]
   554  }`
   555  
   556  func withAuth(r *http.Request) *http.Request {
   557  	// This is the default config secret
   558  	r.Header.Set("x-tyk-authorization", config.Global().Secret)
   559  	return r
   560  }
   561  
   562  // Deprecated: Use Test.CreateSession instead.
   563  func CreateSession(sGen ...func(s *user.SessionState)) string {
   564  	key := generateToken("default", "")
   565  	session := CreateStandardSession()
   566  	if len(sGen) > 0 {
   567  		sGen[0](session)
   568  	}
   569  	if session.Certificate != "" {
   570  		key = generateToken("default", session.Certificate)
   571  	}
   572  
   573  	FallbackKeySesionManager.UpdateSession(storage.HashKey(key), session, 60, config.Global().HashKeys)
   574  	return key
   575  }
   576  
   577  func CreateStandardSession() *user.SessionState {
   578  	session := new(user.SessionState)
   579  	session.Rate = 10000
   580  	session.Allowance = session.Rate
   581  	session.LastCheck = time.Now().Unix()
   582  	session.Per = 60
   583  	session.Expires = -1
   584  	session.QuotaRenewalRate = 300 // 5 minutes
   585  	session.QuotaRenews = time.Now().Unix() + 20
   586  	session.QuotaRemaining = 10
   587  	session.QuotaMax = -1
   588  	session.Tags = []string{}
   589  	session.MetaData = make(map[string]interface{})
   590  	session.OrgID = "default"
   591  	session.Mutex = &sync.RWMutex{}
   592  	return session
   593  }
   594  
   595  func CreateStandardPolicy() *user.Policy {
   596  	return &user.Policy{
   597  		OrgID:            "default",
   598  		Rate:             1000.0,
   599  		Per:              1.0,
   600  		QuotaMax:         -1,
   601  		QuotaRenewalRate: -1,
   602  		AccessRights:     map[string]user.AccessDefinition{},
   603  		Active:           true,
   604  		KeyExpiresIn:     60,
   605  	}
   606  }
   607  
   608  func CreatePolicy(pGen ...func(p *user.Policy)) string {
   609  	pID := keyGen.GenerateAuthKey("")
   610  	pol := CreateStandardPolicy()
   611  	pol.ID = pID
   612  
   613  	if len(pGen) > 0 {
   614  		pGen[0](pol)
   615  	}
   616  
   617  	policiesMu.Lock()
   618  	policiesByID[pol.ID] = *pol
   619  	policiesMu.Unlock()
   620  
   621  	return pol.ID
   622  }
   623  
   624  func CreateJWKToken(jGen ...func(*jwt.Token)) string {
   625  	// Create the token
   626  	token := jwt.New(jwt.GetSigningMethod("RS512"))
   627  	// Set the token ID
   628  
   629  	if len(jGen) > 0 {
   630  		jGen[0](token)
   631  	}
   632  
   633  	// Sign and get the complete encoded token as a string
   634  	signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(jwtRSAPrivKey))
   635  	if err != nil {
   636  		panic("Couldn't extract private key: " + err.Error())
   637  	}
   638  	tokenString, err := token.SignedString(signKey)
   639  	if err != nil {
   640  		panic("Couldn't create JWT token: " + err.Error())
   641  	}
   642  
   643  	return tokenString
   644  }
   645  
   646  func CreateJWKTokenECDSA(jGen ...func(*jwt.Token)) string {
   647  	// Create the token
   648  	token := jwt.New(jwt.GetSigningMethod("ES256"))
   649  	// Set the token ID
   650  
   651  	if len(jGen) > 0 {
   652  		jGen[0](token)
   653  	}
   654  
   655  	// Sign and get the complete encoded token as a string
   656  	signKey, err := jwt.ParseECPrivateKeyFromPEM([]byte(jwtECDSAPrivateKey))
   657  	if err != nil {
   658  		panic("Couldn't extract private key: " + err.Error())
   659  	}
   660  	tokenString, err := token.SignedString(signKey)
   661  	if err != nil {
   662  		panic("Couldn't create JWT token: " + err.Error())
   663  	}
   664  
   665  	return tokenString
   666  }
   667  
   668  func createJWKTokenHMAC(jGen ...func(*jwt.Token)) string {
   669  	// Create the token
   670  	token := jwt.New(jwt.SigningMethodHS256)
   671  	// Set the token ID
   672  
   673  	if len(jGen) > 0 {
   674  		jGen[0](token)
   675  	}
   676  
   677  	tokenString, err := token.SignedString([]byte(jwtSecret))
   678  	if err != nil {
   679  		panic("Couldn't create JWT token: " + err.Error())
   680  	}
   681  
   682  	return tokenString
   683  }
   684  
   685  func TestReqBody(t testing.TB, body interface{}) io.Reader {
   686  	switch x := body.(type) {
   687  	case []byte:
   688  		return bytes.NewReader(x)
   689  	case string:
   690  		return strings.NewReader(x)
   691  	case io.Reader:
   692  		return x
   693  	case nil:
   694  		return nil
   695  	default: // JSON objects (structs)
   696  		bs, err := json.Marshal(x)
   697  		if err != nil {
   698  			t.Fatal(err)
   699  		}
   700  		return bytes.NewReader(bs)
   701  	}
   702  }
   703  
   704  func TestReq(t testing.TB, method, urlStr string, body interface{}) *http.Request {
   705  	return httptest.NewRequest(method, urlStr, TestReqBody(t, body))
   706  }
   707  
   708  func CreateDefinitionFromString(defStr string) *APISpec {
   709  	loader := APIDefinitionLoader{}
   710  	def := loader.ParseDefinition(strings.NewReader(defStr))
   711  	spec := loader.MakeSpec(def, nil)
   712  	return spec
   713  }
   714  
   715  func LoadSampleAPI(def string) (spec *APISpec) {
   716  	spec = CreateDefinitionFromString(def)
   717  	loadApps([]*APISpec{spec})
   718  	return
   719  }
   720  
   721  func firstVals(vals map[string][]string) map[string]string {
   722  	m := make(map[string]string, len(vals))
   723  	for k, vs := range vals {
   724  		m[k] = vs[0]
   725  	}
   726  	return m
   727  }
   728  
   729  type TestConfig struct {
   730  	sepatateControlAPI bool
   731  	Delay              time.Duration
   732  	HotReload          bool
   733  	overrideDefaults   bool
   734  	CoprocessConfig    config.CoProcessConfig
   735  }
   736  
   737  type Test struct {
   738  	URL string
   739  
   740  	testRunner   *test.HTTPTestRunner
   741  	GlobalConfig config.Config
   742  	config       TestConfig
   743  	cacnel       func()
   744  }
   745  
   746  func (s *Test) Start() {
   747  	l, _ := net.Listen("tcp", "127.0.0.1:0")
   748  	_, port, _ := net.SplitHostPort(l.Addr().String())
   749  	l.Close()
   750  	globalConf := config.Global()
   751  	globalConf.ListenPort, _ = strconv.Atoi(port)
   752  
   753  	if s.config.sepatateControlAPI {
   754  		l, _ := net.Listen("tcp", "127.0.0.1:0")
   755  
   756  		_, port, _ = net.SplitHostPort(l.Addr().String())
   757  		l.Close()
   758  		globalConf.ControlAPIPort, _ = strconv.Atoi(port)
   759  	}
   760  	globalConf.CoProcessOptions = s.config.CoprocessConfig
   761  	config.SetGlobal(globalConf)
   762  
   763  	setupPortsWhitelist()
   764  
   765  	startServer()
   766  	ctx, cancel := context.WithCancel(context.Background())
   767  	s.cacnel = cancel
   768  	setupGlobals(ctx)
   769  	// Set up a default org manager so we can traverse non-live paths
   770  	if !config.Global().SupressDefaultOrgStore {
   771  		DefaultOrgStore.Init(getGlobalStorageHandler("orgkey.", false))
   772  		DefaultQuotaStore.Init(getGlobalStorageHandler("orgkey.", false))
   773  	}
   774  
   775  	s.GlobalConfig = globalConf
   776  
   777  	scheme := "http://"
   778  	if s.GlobalConfig.HttpServerOptions.UseSSL {
   779  		scheme = "https://"
   780  	}
   781  	s.URL = scheme + mainProxy().listener.Addr().String()
   782  
   783  	s.testRunner = &test.HTTPTestRunner{
   784  		RequestBuilder: func(tc *test.TestCase) (*http.Request, error) {
   785  			tc.BaseURL = s.URL
   786  			if tc.ControlRequest {
   787  				if s.config.sepatateControlAPI {
   788  					tc.BaseURL = scheme + controlProxy().listener.Addr().String()
   789  				} else if s.GlobalConfig.ControlAPIHostname != "" {
   790  					tc.Domain = s.GlobalConfig.ControlAPIHostname
   791  				}
   792  			}
   793  			r, err := test.NewRequest(tc)
   794  
   795  			if tc.AdminAuth {
   796  				r = withAuth(r)
   797  			}
   798  
   799  			if s.config.Delay > 0 {
   800  				tc.Delay = s.config.Delay
   801  			}
   802  
   803  			return r, err
   804  		},
   805  		Do: test.HttpServerRunner(),
   806  	}
   807  }
   808  
   809  func (s *Test) Do(tc test.TestCase) (*http.Response, error) {
   810  	req, _ := s.testRunner.RequestBuilder(&tc)
   811  	return s.testRunner.Do(req, &tc)
   812  }
   813  
   814  func (s *Test) Close() {
   815  	if s.cacnel != nil {
   816  		s.cacnel()
   817  	}
   818  	defaultProxyMux.swap(&proxyMux{})
   819  	if s.config.sepatateControlAPI {
   820  		globalConf := config.Global()
   821  		globalConf.ControlAPIPort = 0
   822  		config.SetGlobal(globalConf)
   823  	}
   824  }
   825  
   826  func (s *Test) Run(t testing.TB, testCases ...test.TestCase) (*http.Response, error) {
   827  	return s.testRunner.Run(t, testCases...)
   828  }
   829  
   830  //TODO:(gernest) when hot reload is suppored enable this.
   831  func (s *Test) RunExt(t testing.TB, testCases ...test.TestCase) {
   832  	s.Run(t, testCases...)
   833  	var testMatrix = []struct {
   834  		goagain          bool
   835  		overrideDefaults bool
   836  	}{
   837  		{false, false},
   838  		{false, true},
   839  		{true, true},
   840  		{true, false},
   841  	}
   842  
   843  	for i, m := range testMatrix {
   844  		s.config.HotReload = m.goagain
   845  		s.config.overrideDefaults = m.overrideDefaults
   846  
   847  		if i > 0 {
   848  			s.Close()
   849  			s.Start()
   850  		}
   851  
   852  		title := fmt.Sprintf("hotReload: %v, overrideDefaults: %v", m.goagain, m.overrideDefaults)
   853  		t.(*testing.T).Run(title, func(t *testing.T) {
   854  			s.Run(t, testCases...)
   855  		})
   856  	}
   857  }
   858  
   859  func GetTLSClient(cert *tls.Certificate, caCert []byte) *http.Client {
   860  	// Setup HTTPS client
   861  	tlsConfig := &tls.Config{}
   862  
   863  	if cert != nil {
   864  		tlsConfig.Certificates = []tls.Certificate{*cert}
   865  	}
   866  
   867  	if len(caCert) > 0 {
   868  		caCertPool := x509.NewCertPool()
   869  		caCertPool.AppendCertsFromPEM(caCert)
   870  		tlsConfig.RootCAs = caCertPool
   871  		tlsConfig.BuildNameToCertificate()
   872  	} else {
   873  		tlsConfig.InsecureSkipVerify = true
   874  	}
   875  
   876  	transport := &http.Transport{TLSClientConfig: tlsConfig}
   877  
   878  	return &http.Client{Transport: transport}
   879  }
   880  
   881  func (s *Test) CreateSession(sGen ...func(s *user.SessionState)) (*user.SessionState, string) {
   882  	session := CreateStandardSession()
   883  	if len(sGen) > 0 {
   884  		sGen[0](session)
   885  	}
   886  
   887  	client := GetTLSClient(nil, nil)
   888  
   889  	resp, err := s.Do(test.TestCase{
   890  		Method:    http.MethodPost,
   891  		Path:      "/tyk/keys/create",
   892  		Data:      session,
   893  		Client:    client,
   894  		AdminAuth: true,
   895  	})
   896  
   897  	if err != nil {
   898  		log.Fatal("Error while creating session:", err)
   899  		return nil, ""
   900  	}
   901  
   902  	keySuccess := apiModifyKeySuccess{}
   903  	err = json.NewDecoder(resp.Body).Decode(&keySuccess)
   904  	if err != nil {
   905  		log.Fatal("Error while decoding session response:", err)
   906  		return nil, ""
   907  	}
   908  
   909  	return session, keySuccess.Key
   910  }
   911  
   912  func StartTest(config ...TestConfig) *Test {
   913  	t := &Test{}
   914  	if len(config) > 0 {
   915  		t.config = config[0]
   916  	}
   917  	t.Start()
   918  
   919  	return t
   920  }
   921  
   922  const sampleAPI = `{
   923      "api_id": "test",
   924  	"org_id": "default",
   925      "use_keyless": true,
   926      "definition": {
   927          "location": "header",
   928          "key": "version"
   929      },
   930      "auth": {
   931          "auth_header_name": "authorization"
   932  	},
   933      "version_data": {
   934  		"default_version": "Default",
   935          "not_versioned": true,
   936          "versions": {
   937              "v1": {
   938              	"name": "v1",
   939              	"use_extended_paths": true
   940             	}
   941          }
   942      },
   943      "proxy": {
   944          "listen_path": "/sample",
   945          "target_url": "` + TestHttpAny + `"
   946      }
   947  }`
   948  
   949  func UpdateAPIVersion(spec *APISpec, name string, verGen func(version *apidef.VersionInfo)) {
   950  	version := spec.VersionData.Versions[name]
   951  	verGen(&version)
   952  	spec.VersionData.Versions[name] = version
   953  }
   954  
   955  func jsonMarshalString(i interface{}) (out string) {
   956  	b, _ := json.Marshal(i)
   957  	return string(b)
   958  }
   959  
   960  func BuildAPI(apiGens ...func(spec *APISpec)) (specs []*APISpec) {
   961  	if len(apiGens) == 0 {
   962  		apiGens = append(apiGens, func(spec *APISpec) {})
   963  	}
   964  
   965  	for _, gen := range apiGens {
   966  		spec := &APISpec{APIDefinition: &apidef.APIDefinition{}}
   967  		if err := json.Unmarshal([]byte(sampleAPI), spec.APIDefinition); err != nil {
   968  			panic(err)
   969  		}
   970  
   971  		gen(spec)
   972  		specs = append(specs, spec)
   973  	}
   974  
   975  	return specs
   976  }
   977  
   978  func LoadAPI(specs ...*APISpec) (out []*APISpec) {
   979  	globalConf := config.Global()
   980  	oldPath := globalConf.AppPath
   981  	globalConf.AppPath, _ = ioutil.TempDir("", "apps")
   982  	config.SetGlobal(globalConf)
   983  	defer func() {
   984  		globalConf := config.Global()
   985  		os.RemoveAll(globalConf.AppPath)
   986  		globalConf.AppPath = oldPath
   987  		config.SetGlobal(globalConf)
   988  	}()
   989  
   990  	for i, spec := range specs {
   991  		specBytes, err := json.Marshal(spec)
   992  		if err != nil {
   993  			panic(err)
   994  		}
   995  		specFilePath := filepath.Join(config.Global().AppPath, spec.APIID+strconv.Itoa(i)+".json")
   996  		if err := ioutil.WriteFile(specFilePath, specBytes, 0644); err != nil {
   997  			panic(err)
   998  		}
   999  	}
  1000  
  1001  	DoReload()
  1002  
  1003  	for _, spec := range specs {
  1004  		out = append(out, getApiSpec(spec.APIID))
  1005  	}
  1006  
  1007  	return out
  1008  }
  1009  
  1010  func BuildAndLoadAPI(apiGens ...func(spec *APISpec)) (specs []*APISpec) {
  1011  	return LoadAPI(BuildAPI(apiGens...)...)
  1012  }
  1013  
  1014  func CloneAPI(a *APISpec) *APISpec {
  1015  	new := &APISpec{}
  1016  	new.APIDefinition = &apidef.APIDefinition{}
  1017  	*new.APIDefinition = *a.APIDefinition
  1018  
  1019  	return new
  1020  }
  1021  
  1022  // Taken from https://medium.com/@mlowicki/http-s-proxy-in-golang-in-less-than-100-lines-of-code-6a51c2f2c38c
  1023  type httpProxyHandler struct {
  1024  	proto    string
  1025  	URL      string
  1026  	server   *http.Server
  1027  	listener net.Listener
  1028  }
  1029  
  1030  func (p *httpProxyHandler) handleTunneling(w http.ResponseWriter, r *http.Request) {
  1031  	dest_conn, err := net.DialTimeout("tcp", r.Host, 10*time.Second)
  1032  	if err != nil {
  1033  		http.Error(w, err.Error(), http.StatusServiceUnavailable)
  1034  		return
  1035  	}
  1036  	w.WriteHeader(http.StatusOK)
  1037  	hijacker, ok := w.(http.Hijacker)
  1038  	if !ok {
  1039  		http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
  1040  		return
  1041  	}
  1042  	client_conn, _, err := hijacker.Hijack()
  1043  	if err != nil {
  1044  		http.Error(w, err.Error(), http.StatusServiceUnavailable)
  1045  	}
  1046  	go p.transfer(dest_conn, client_conn)
  1047  	go p.transfer(client_conn, dest_conn)
  1048  }
  1049  
  1050  func (p *httpProxyHandler) transfer(destination io.WriteCloser, source io.ReadCloser) {
  1051  	defer destination.Close()
  1052  	defer source.Close()
  1053  	io.Copy(destination, source)
  1054  }
  1055  func (p *httpProxyHandler) handleHTTP(w http.ResponseWriter, req *http.Request) {
  1056  	resp, err := http.DefaultTransport.RoundTrip(req)
  1057  	if err != nil {
  1058  		http.Error(w, err.Error(), http.StatusServiceUnavailable)
  1059  		return
  1060  	}
  1061  	defer resp.Body.Close()
  1062  	p.copyHeader(w.Header(), resp.Header)
  1063  	w.WriteHeader(resp.StatusCode)
  1064  	io.Copy(w, resp.Body)
  1065  }
  1066  
  1067  func (p *httpProxyHandler) Stop() error {
  1068  	ResetTestConfig()
  1069  	return p.server.Close()
  1070  }
  1071  
  1072  func (p *httpProxyHandler) copyHeader(dst, src http.Header) {
  1073  	for k, vv := range src {
  1074  		for _, v := range vv {
  1075  			dst.Add(k, v)
  1076  		}
  1077  	}
  1078  }
  1079  
  1080  func initProxy(proto string, tlsConfig *tls.Config) *httpProxyHandler {
  1081  	proxy := &httpProxyHandler{proto: proto}
  1082  
  1083  	proxy.server = &http.Server{
  1084  		Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1085  			if r.Method == http.MethodConnect {
  1086  				proxy.handleTunneling(w, r)
  1087  			} else {
  1088  				proxy.handleHTTP(w, r)
  1089  			}
  1090  		}),
  1091  		// Disable HTTP/2.
  1092  		TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)),
  1093  	}
  1094  
  1095  	var err error
  1096  
  1097  	switch proto {
  1098  	case "http":
  1099  		proxy.listener, err = net.Listen("tcp", ":0")
  1100  	case "https":
  1101  		proxy.listener, err = tls.Listen("tcp", ":0", tlsConfig)
  1102  	default:
  1103  		log.Fatal("Unsupported proto scheme", proto)
  1104  	}
  1105  
  1106  	if err != nil {
  1107  		log.Fatal(err)
  1108  	}
  1109  
  1110  	proxy.URL = proto + "://" + proxy.listener.Addr().String()
  1111  
  1112  	go proxy.server.Serve(proxy.listener)
  1113  
  1114  	return proxy
  1115  }
  1116  
  1117  func GenerateTestBinaryData() (buf *bytes.Buffer) {
  1118  	buf = new(bytes.Buffer)
  1119  	type testData struct {
  1120  		a float32
  1121  		b float64
  1122  		c uint32
  1123  	}
  1124  	for i := 0; i < 10; i++ {
  1125  		s := &testData{rand.Float32(), rand.Float64(), rand.Uint32()}
  1126  		binary.Write(buf, binary.BigEndian, s)
  1127  	}
  1128  	return buf
  1129  }
  1130  
  1131  // openssl genrsa -out app.rsa
  1132  const jwtRSAPrivKey = `
  1133  -----BEGIN RSA PRIVATE KEY-----
  1134  MIIEpQIBAAKCAQEAyqZ4rwKF8qCExS7kpY4cnJa/37FMkJNkalZ3OuslLB0oRL8T
  1135  4c94kdF4aeNzSFkSe2n99IBI6Ssl79vbfMZb+t06L0Q94k+/P37x7+/RJZiff4y1
  1136  VGjrnrnMI2iu9l4iBBRYzNmG6eblroEMMWlgk5tysHgxB59CSNIcD9gqk1hx4n/F
  1137  gOmvKsfQgWHNlPSDTRcWGWGhB2/XgNVYG2pOlQxAPqLhBHeqGTXBbPfGF9cHzixp
  1138  sPr6GtbzPwhsQ/8bPxoJ7hdfn+rzztks3d6+HWURcyNTLRe0mjXjjee9Z6+gZ+H+
  1139  fS4pnP9tqT7IgU6ePUWTpjoiPtLexgsAa/ctjQIDAQABAoIBAECWvnBJRZgHQUn3
  1140  oDiECup9wbnyMI0D7UVXObk1qSteP69pl1SpY6xWLyLQs7WjbhiXt7FuEc7/SaAh
  1141  Wttx/W7/g8P85Bx1fmcmdsYakXaCJpPorQKyTibQ4ReIDfvIFN9n/MWNr0ptpVbx
  1142  GonFJFrneK52IGplgCLllLwYEbnULYcJc6E25Ro8U2gQjF2r43PDa07YiDrmB/GV
  1143  QQW4HTo+CA9rdK0bP8GpXgc0wpmBhx/t/YdnDg6qhzyUMk9As7JrAzYPjHO0cRun
  1144  vhA/aG/mdMmRumY75nj7wB5U5DgstsN2ER75Pjr1xe1knftIyNm15AShCPfLaLGo
  1145  dA2IpwECgYEA5E8h6ssa7QroCGwp/N0wSJW41hFYGygbOEg6yPWTJkqmMZVduD8X
  1146  /KFqJK4LcIbFQuR28+hWJpHm/RF1AMRhbbWkAj6h02gv5izFwDiFKev5paky4Evg
  1147  G8WfUOmSZ1D+fVxwaoG0OaRZpCovUTxYig3xrI659DMeKqpQ7e8l9ekCgYEA4zql
  1148  l4P4Dn0ydr+TI/s4NHIQHkaLQAVk3OWwyKowijXd8LCtuZRA1NKSpqQ4ZXi0B17o
  1149  9zzF5jEUjws3qWv4PKWdxJu3y+h/etsg7wxUeNizbY2ooUGeMbk0tWxJihbgaI7E
  1150  XxLIT50F3Ky4EJ2cUL9GmJ+gLCw0KIaVbkiyYAUCgYEA0WyVHB76r/2VIkS1rzHm
  1151  HG7ageKfAyoi7dmzsqsxM6q+EDWHJn8Zra8TAlp0O+AkClwvkUTJ4c9sJy9gODfr
  1152  dwtrSnPRVW74oRbovo4Z+H5xHbi65mwzQsZggYP/u63cA3pL1Cbt/wH3CFN52/aS
  1153  8PAhg7vYb1yEi3Z3jgoUtCECgYEAhSPX4u9waQzyhKG7lVmdlR1AVH0BGoIOl1/+
  1154  NZWC23i0klLzd8lmM00uoHWYldwjoC38UuFJE5eudCIeeybITMC9sHWNO+z+xP2g
  1155  TnDrDePrPkXCiLnp9ziNqb/JVyAQXTNJ3Gsk84EN7j9Fmna/IJDyzHq7XyaHaTdy
  1156  VyxBWAECgYEA4jYS07bPx5UMhKiMJDqUmDfLNFD97XwPoJIkOdn6ezqeOSmlmo7t
  1157  jxHLbCmsDOAsCU/0BlLXg9wMU7n5QKSlfTVGok/PU0rq2FUXQwyKGnellrqODwFQ
  1158  YGivtXBGXk1hlVYlje1RB+W6RQuDAegI5h8vl8pYJS9JQH0wjatsDaE=
  1159  -----END RSA PRIVATE KEY-----
  1160  `
  1161  
  1162  const jwtECDSAPrivateKey = `-----BEGIN PRIVATE KEY-----
  1163  MHcCAQEEIFjaz7TJpBOHmQttPypGRh3rqaXvRpsWE/EWUiLzc6veoAoGCCqGSM49
  1164  AwEHoUQDQgAEDmKdIVHH9D5xkUiMJvo4T9H8yU+QYOIBlX5DYpJFtEvzTs4SsXYC
  1165  tFsPk7c31tOpMuS8aQiLsXR82VMLqQBf1w==
  1166  -----END PRIVATE KEY-----`
  1167  
  1168  const jwtECDSAPublicKey = `-----BEGIN PUBLIC KEY-----
  1169  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDmKdIVHH9D5xkUiMJvo4T9H8yU+Q
  1170  YOIBlX5DYpJFtEvzTs4SsXYCtFsPk7c31tOpMuS8aQiLsXR82VMLqQBf1w==
  1171  -----END PUBLIC KEY-----`
  1172  
  1173  const jwtSecret = "9879879878787878"
  1174  const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1175  
  1176  func randStringBytes(n int) string {
  1177  	b := make([]byte, n)
  1178  
  1179  	for i := range b {
  1180  		b[i] = letters[rand.Intn(len(letters))]
  1181  	}
  1182  
  1183  	return string(b)
  1184  }