From 1af95b0307dd62515f67608c22742a02d875b854 Mon Sep 17 00:00:00 2001 From: JBP <2850825+jybp@users.noreply.github.com> Date: Sat, 17 Aug 2019 18:20:55 +0200 Subject: [PATCH] setup tls --- ebay.go | 9 ++-- test/integration/auction_test.go | 22 ++++---- test/integration/tls.go | 87 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 19 deletions(-) create mode 100644 test/integration/tls.go diff --git a/ebay.go b/ebay.go index 440cc2e..7c5e383 100644 --- a/ebay.go +++ b/ebay.go @@ -88,20 +88,17 @@ func (c *Client) NewRequest(method, url string, body interface{}, opts ...Opt) ( if err != nil { return nil, errors.WithStack(err) } - var bodyR io.Reader + var buf io.ReadWriter if body != nil { - buf := new(bytes.Buffer) + buf = new(bytes.Buffer) enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) if err := enc.Encode(body); err != nil { return nil, err } - b := buf.Bytes() - print("body:" + string(b)) // TODO - bodyR = bytes.NewReader(b) } - req, err := http.NewRequest(method, u.String(), bodyR) + req, err := http.NewRequest(method, u.String(), buf) if err != nil { return nil, errors.WithStack(err) } diff --git a/test/integration/auction_test.go b/test/integration/auction_test.go index 48a754c..c50eec5 100644 --- a/test/integration/auction_test.go +++ b/test/integration/auction_test.go @@ -35,10 +35,8 @@ func init() { } clientID = os.Getenv("SANDBOX_CLIENT_ID") clientSecret = os.Getenv("SANDBOX_CLIENT_SECRET") - // You have to manually create an auction in the sandbox. Auctions can't be created using the rest api (yet?). - auctionURL = os.Getenv("SANDOX_AUCTION_URL") - if clientID == "" || clientSecret == "" || auctionURL == "" { - panic("Please set SANDBOX_CLIENT_ID, SANDBOX_CLIENT_SECRET and SANDOX_AUCTION_URL.") + if clientID == "" || clientSecret == "" { + panic("Please set SANDBOX_CLIENT_ID and SANDBOX_CLIENT_SECRET.") } } @@ -49,6 +47,9 @@ func TestAuction(t *testing.T) { ctx := context.Background() + // You have to manually create an auction in the sandbox. Auctions can't be created using the rest api (yet?). + auctionURL = os.Getenv("SANDOX_AUCTION_URL") + conf := clientcredentials.Config{ ClientID: clientID, ClientSecret: clientSecret, @@ -66,9 +67,6 @@ func TestAuction(t *testing.T) { if err != nil { t.Fatalf("%+v", err) } - if testing.Verbose() { - t.Logf("item: %+v\n", it) - } isAuction := false for _, opt := range it.BuyingOptions { if opt == ebay.BrowseBuyingOptionAuction { @@ -89,7 +87,8 @@ func TestAuction(t *testing.T) { } state := url.QueryEscape(string(b)) authCodeC := make(chan string) - http.HandleFunc("/accept", func(rw http.ResponseWriter, r *http.Request) { + mux := setupTLS() + mux.HandleFunc("/accept", func(rw http.ResponseWriter, r *http.Request) { actualState, err := url.QueryUnescape(r.URL.Query().Get("state")) if err != nil { http.Error(rw, fmt.Sprintf("invalid state: %+v", err), http.StatusBadRequest) @@ -105,15 +104,12 @@ func TestAuction(t *testing.T) { t.Logf("The authorization code will expire in %s seconds.\n", r.URL.Query().Get("expires_in")) rw.Write([]byte("Accept. You can safely close this tab.")) }) - http.HandleFunc("/policy", func(rw http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/policy", func(rw http.ResponseWriter, r *http.Request) { rw.Write([]byte("eBay Sniper Policy")) }) - http.HandleFunc("/decline", func(rw http.ResponseWriter, r *http.Request) { + mux.HandleFunc("/decline", func(rw http.ResponseWriter, r *http.Request) { rw.Write([]byte("Decline. You can safely close this tab.")) }) - go func() { - t.Fatal(http.ListenAndServe(":52125", nil)) - }() oauthConf := oauth2.Config{ ClientID: clientID, diff --git a/test/integration/tls.go b/test/integration/tls.go new file mode 100644 index 0000000..e9c1f6a --- /dev/null +++ b/test/integration/tls.go @@ -0,0 +1,87 @@ +package integration + +// From https://gist.github.com/shivakar/cd52b5594d4912fbeb46 + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "log" + "math/big" + "net" + "net/http" + "time" +) + +// From https://golang.org/src/net/http/server.go +// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted +// connections. It's used by ListenAndServe and ListenAndServeTLS so +// dead TCP connections (e.g. closing laptop mid-download) eventually +// go away. +type tcpKeepAliveListener struct { + *net.TCPListener + keepAlivePeriod time.Duration +} + +func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { + tc, err := ln.AcceptTCP() + if err != nil { + return + } + tc.SetKeepAlive(true) + tc.SetKeepAlivePeriod(ln.keepAlivePeriod) + return tc, nil +} + +func tlsCert(name string, dur time.Duration) (tls.Certificate, error) { + now := time.Now() + template := &x509.Certificate{ + SerialNumber: big.NewInt(0), + Subject: pkix.Name{CommonName: name}, + NotBefore: now, + NotAfter: now.Add(dur), + BasicConstraintsValid: true, + IsCA: true, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, + } + + priv, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return tls.Certificate{}, err + } + + cert, err := x509.CreateCertificate(rand.Reader, template, template, priv.Public(), priv) + if err != nil { + return tls.Certificate{}, err + } + + var outCert tls.Certificate + outCert.Certificate = append(outCert.Certificate, cert) + outCert.PrivateKey = priv + return outCert, nil +} + +func setupTLS() *http.ServeMux { + cert, err := tlsCert("eSniper", time.Hour) + if err != nil { + log.Fatal(err) + } + mux := http.NewServeMux() + srv := &http.Server{Addr: ":52125", Handler: mux} + cfg := &tls.Config{} + cfg.NextProtos = []string{"http/1.1"} + cfg.Certificates = make([]tls.Certificate, 1) + cfg.Certificates[0] = cert + ln, err := net.Listen("tcp", ":52125") + if err != nil { + log.Fatal(err) + } + tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener), time.Minute}, cfg) + go func() { + srv.Serve(tlsListener) + }() + return mux +}