From b8de3a381abf351a3229958732b4517a928752fe Mon Sep 17 00:00:00 2001 From: furkansenharputlu Date: Tue, 12 Feb 2019 14:54:17 +0300 Subject: [PATCH 1/2] Add HTTP/2 support option and add test --- cert_go1.10_test.go | 2 +- cert_test.go | 80 ++++++++++++++++++++++------ config/config.go | 1 + install/data/tyk.self_contained.conf | 1 + install/data/tyk.with_dash.conf | 1 + main.go | 6 +++ 6 files changed, 75 insertions(+), 16 deletions(-) diff --git a/cert_go1.10_test.go b/cert_go1.10_test.go index 56b4564407fd..36a813d6aabc 100644 --- a/cert_go1.10_test.go +++ b/cert_go1.10_test.go @@ -204,7 +204,7 @@ func TestProxyTransport(t *testing.T) { spec.Proxy.Transport.ProxyURL = proxy.URL }) - client := getTLSClient(nil, nil) + client := getTLSClient(nil, nil, false) client.Transport = &http.Transport{ TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), } diff --git a/cert_test.go b/cert_test.go index 41fd7310c5c8..a5648c90e406 100644 --- a/cert_test.go +++ b/cert_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "golang.org/x/net/http2" + "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/certs" "github.com/TykTechnologies/tyk/config" @@ -25,7 +27,7 @@ import ( "github.com/TykTechnologies/tyk/user" ) -func getTLSClient(cert *tls.Certificate, caCert []byte) *http.Client { +func getTLSClient(cert *tls.Certificate, caCert []byte, isHttp2 bool) *http.Client { // Setup HTTPS client tlsConfig := &tls.Config{} @@ -42,7 +44,12 @@ func getTLSClient(cert *tls.Certificate, caCert []byte) *http.Client { tlsConfig.InsecureSkipVerify = true } - transport := &http.Transport{TLSClientConfig: tlsConfig} + var transport http.RoundTripper + if isHttp2 { + transport = &http2.Transport{TLSClientConfig: tlsConfig} + } else { + transport = &http.Transport{TLSClientConfig: tlsConfig} + } return &http.Client{Transport: transport} } @@ -91,7 +98,7 @@ func TestGatewayTLS(t *testing.T) { dir, _ := ioutil.TempDir("", "certs") defer os.RemoveAll(dir) - client := getTLSClient(nil, nil) + client := getTLSClient(nil, nil, false) t.Run("Without certificates", func(t *testing.T) { globalConf := config.Global() @@ -204,9 +211,9 @@ func TestGatewayControlAPIMutualTLS(t *testing.T) { }() clientCertPem, _, _, clientCert := genCertificate(&x509.Certificate{}) - clientWithCert := getTLSClient(&clientCert, serverCertPem) + clientWithCert := getTLSClient(&clientCert, serverCertPem, false) - clientWithoutCert := getTLSClient(nil, nil) + clientWithoutCert := getTLSClient(nil, nil, false) t.Run("Separate domain", func(t *testing.T) { certID, _ := CertificateManager.Add(combinedPEM, "") @@ -276,7 +283,7 @@ func TestAPIMutualTLS(t *testing.T) { t.Run("SNI and domain per API", func(t *testing.T) { t.Run("API without mutual TLS", func(t *testing.T) { - client := getTLSClient(&clientCert, serverCertPem) + client := getTLSClient(&clientCert, serverCertPem, false) buildAndLoadAPI(func(spec *APISpec) { spec.Domain = "localhost" @@ -287,7 +294,7 @@ func TestAPIMutualTLS(t *testing.T) { }) t.Run("MutualTLSCertificate not set", func(t *testing.T) { - client := getTLSClient(nil, nil) + client := getTLSClient(nil, nil, false) buildAndLoadAPI(func(spec *APISpec) { spec.Domain = "localhost" @@ -303,7 +310,7 @@ func TestAPIMutualTLS(t *testing.T) { }) t.Run("Client certificate match", func(t *testing.T) { - client := getTLSClient(&clientCert, serverCertPem) + client := getTLSClient(&clientCert, serverCertPem, false) clientCertID, _ := CertificateManager.Add(clientCertPem, "") buildAndLoadAPI(func(spec *APISpec) { @@ -320,14 +327,14 @@ func TestAPIMutualTLS(t *testing.T) { CertificateManager.Delete(clientCertID) CertificateManager.FlushCache() - client = getTLSClient(&clientCert, serverCertPem) + client = getTLSClient(&clientCert, serverCertPem, false) ts.Run(t, test.TestCase{ Client: client, Domain: "localhost", ErrorMatch: badcertErr, }) }) t.Run("Client certificate differ", func(t *testing.T) { - client := getTLSClient(&clientCert, serverCertPem) + client := getTLSClient(&clientCert, serverCertPem, false) clientCertPem2, _, _, _ := genCertificate(&x509.Certificate{}) clientCertID2, _ := CertificateManager.Add(clientCertPem2, "") @@ -364,7 +371,7 @@ func TestAPIMutualTLS(t *testing.T) { } t.Run("Without certificate", func(t *testing.T) { - clientWithoutCert := getTLSClient(nil, nil) + clientWithoutCert := getTLSClient(nil, nil, false) loadAPIS() @@ -385,7 +392,7 @@ func TestAPIMutualTLS(t *testing.T) { }) t.Run("Client certificate not match", func(t *testing.T) { - client := getTLSClient(&clientCert, serverCertPem) + client := getTLSClient(&clientCert, serverCertPem, false) loadAPIS() @@ -401,7 +408,7 @@ func TestAPIMutualTLS(t *testing.T) { t.Run("Client certificate match", func(t *testing.T) { loadAPIS(clientCertID) - client := getTLSClient(&clientCert, serverCertPem) + client := getTLSClient(&clientCert, serverCertPem, false) ts.Run(t, test.TestCase{ Path: "/with_mutual", @@ -431,7 +438,7 @@ func TestUpstreamMutualTLS(t *testing.T) { defer upstream.Close() t.Run("Without API", func(t *testing.T) { - client := getTLSClient(&clientCert, nil) + client := getTLSClient(&clientCert, nil, false) if _, err := client.Get(upstream.URL); err == nil { t.Error("Should reject without certificate") @@ -495,7 +502,7 @@ func TestKeyWithCertificateTLS(t *testing.T) { spec.Proxy.ListenPath = "/" }) - client := getTLSClient(&clientCert, nil) + client := getTLSClient(&clientCert, nil, false) t.Run("Cert unknown", func(t *testing.T) { ts.Run(t, test.TestCase{Code: 403, Client: client}) @@ -648,3 +655,46 @@ func TestCipherSuites(t *testing.T) { ts.Run(t, test.TestCase{Client: client, Path: "/", ErrorMatch: "tls: handshake failure"}) }) } + +func TestHTTP2(t *testing.T) { + mockHandle.PushDomains(map[string][]string{"http2.golang.org.": {"130.211.116.44"}}, nil) + + // Certificates + serverCertPem, serverPrivPem, _, _ := genServerCertificate() + _, _, _, clientCert := genCertificate(&x509.Certificate{}) + + dir, _ := ioutil.TempDir("", "certs") + defer os.RemoveAll(dir) + certFilePath := filepath.Join(dir, "server.crt") + ioutil.WriteFile(certFilePath, serverCertPem, 0666) + + certKeyPath := filepath.Join(dir, "server.key") + ioutil.WriteFile(certKeyPath, serverPrivPem, 0666) + + // Configuration + globalConf := config.Global() + globalConf.HttpServerOptions.EnableHttp2 = true + globalConf.HttpServerOptions.Certificates = []config.CertData{{ + Name: "localhost", + CertFile: certFilePath, + KeyFile: certKeyPath, + }} + globalConf.HttpServerOptions.UseSSL = true + config.SetGlobal(globalConf) + defer resetTestConfig() + + ts := newTykTestServer() + defer ts.Close() + + buildAndLoadAPI(func(spec *APISpec) { + spec.Proxy.ListenPath = "/" + spec.UseKeylessAccess = true + spec.Proxy.TargetURL = "https://http2.golang.org" // HTTP/2 Upstream + }) + + // Client + http2Client := getTLSClient(&clientCert, serverCertPem, true) + + ts.Run(t, test.TestCase{Client: http2Client, Path: "", Code: 200, BodyMatch: "

Go + HTTP/2

"}) + +} diff --git a/config/config.go b/config/config.go index 8d012c5c4241..ad0a6163c177 100644 --- a/config/config.go +++ b/config/config.go @@ -143,6 +143,7 @@ type HttpServerOptionsConfig struct { WriteTimeout int `json:"write_timeout"` UseSSL bool `json:"use_ssl"` UseLE_SSL bool `json:"use_ssl_le"` + EnableHttp2 bool `json:"enable_http2"` SSLInsecureSkipVerify bool `json:"ssl_insecure_skip_verify"` EnableWebSockets bool `json:"enable_websockets"` Certificates []CertData `json:"certificates"` diff --git a/install/data/tyk.self_contained.conf b/install/data/tyk.self_contained.conf index 061863e96bd6..aa67ec41e380 100644 --- a/install/data/tyk.self_contained.conf +++ b/install/data/tyk.self_contained.conf @@ -58,6 +58,7 @@ } }, "http_server_options": { + "enable_http2": true, "enable_websockets": true }, "hostname": "", diff --git a/install/data/tyk.with_dash.conf b/install/data/tyk.with_dash.conf index daa771149698..1201c6866c54 100644 --- a/install/data/tyk.with_dash.conf +++ b/install/data/tyk.with_dash.conf @@ -63,6 +63,7 @@ "disable_cached_session_state": false }, "http_server_options": { + "enable_http2": true, "enable_websockets": true }, "uptime_tests": { diff --git a/main.go b/main.go index f7419a13f301..c7d4f3d128a5 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,8 @@ import ( "sync" "time" + "golang.org/x/net/http2" + newrelic "github.com/newrelic/go-agent" "github.com/TykTechnologies/tyk/checkup" @@ -1145,6 +1147,10 @@ func generateListener(listenPort int) (net.Listener, error) { CipherSuites: getCipherAliases(httpServerOptions.Ciphers), } + if httpServerOptions.EnableHttp2 { + tlsConfig.NextProtos = append(tlsConfig.NextProtos, http2.NextProtoTLS) + } + tlsConfig.GetConfigForClient = getTLSConfigForClient(&tlsConfig, listenPort) return tls.Listen("tcp", targetPort, &tlsConfig) From 7fa73a3684bd377c3d664a208db6a591f97a20ad Mon Sep 17 00:00:00 2001 From: furkansenharputlu Date: Tue, 12 Feb 2019 15:56:18 +0300 Subject: [PATCH 2/2] Format code --- cert_test.go | 1 - dnscache/storage.go | 2 +- handler_success.go | 3 +-- helpers_test.go | 4 ++-- host_checker.go | 2 +- main.go | 2 +- middleware.go | 4 ++-- mw_js_plugin_test.go | 2 +- reverse_proxy.go | 2 +- test/dns.go | 7 ++++--- 10 files changed, 14 insertions(+), 15 deletions(-) diff --git a/cert_test.go b/cert_test.go index a5648c90e406..f25b76897f04 100644 --- a/cert_test.go +++ b/cert_test.go @@ -657,7 +657,6 @@ func TestCipherSuites(t *testing.T) { } func TestHTTP2(t *testing.T) { - mockHandle.PushDomains(map[string][]string{"http2.golang.org.": {"130.211.116.44"}}, nil) // Certificates serverCertPem, serverPrivPem, _, _ := genServerCertificate() diff --git a/dnscache/storage.go b/dnscache/storage.go index c67f6d4dbac2..ac8053490c87 100644 --- a/dnscache/storage.go +++ b/dnscache/storage.go @@ -7,7 +7,7 @@ import ( "fmt" "github.com/Sirupsen/logrus" - "github.com/pmylund/go-cache" + cache "github.com/pmylund/go-cache" ) // DnsCacheItem represents single record in cache diff --git a/handler_success.go b/handler_success.go index ccf5f4cffb20..4d3008bfd156 100644 --- a/handler_success.go +++ b/handler_success.go @@ -10,9 +10,8 @@ import ( "strings" "time" - "github.com/pmylund/go-cache" - "github.com/TykTechnologies/tyk/request" + cache "github.com/pmylund/go-cache" "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/user" diff --git a/helpers_test.go b/helpers_test.go index 25f08f80539e..7a98b57d1856 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -21,10 +21,10 @@ import ( "testing" "time" - "github.com/dgrijalva/jwt-go" + jwt "github.com/dgrijalva/jwt-go" "github.com/gorilla/mux" "github.com/gorilla/websocket" - "github.com/satori/go.uuid" + uuid "github.com/satori/go.uuid" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/config" diff --git a/host_checker.go b/host_checker.go index 8af72611ced7..40ae81e6008b 100644 --- a/host_checker.go +++ b/host_checker.go @@ -9,7 +9,7 @@ import ( "time" "github.com/jeffail/tunny" - "github.com/pmylund/go-cache" + cache "github.com/pmylund/go-cache" "github.com/TykTechnologies/tyk/config" ) diff --git a/main.go b/main.go index c7d4f3d128a5..babd2962a92c 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ import ( "github.com/TykTechnologies/tyk/checkup" "github.com/Sirupsen/logrus" - "github.com/Sirupsen/logrus/hooks/syslog" + logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog" logstashHook "github.com/bshuster-repo/logrus-logstash-hook" "github.com/evalphobia/logrus_sentry" "github.com/facebookgo/pidfile" diff --git a/middleware.go b/middleware.go index 9d7c19f0b921..08bb24b72536 100644 --- a/middleware.go +++ b/middleware.go @@ -9,9 +9,9 @@ import ( "github.com/Sirupsen/logrus" "github.com/gocraft/health" "github.com/justinas/alice" - "github.com/newrelic/go-agent" + newrelic "github.com/newrelic/go-agent" "github.com/paulbellamy/ratecounter" - "github.com/pmylund/go-cache" + cache "github.com/pmylund/go-cache" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/config" diff --git a/mw_js_plugin_test.go b/mw_js_plugin_test.go index 9b2cdc35a856..722261b74aad 100644 --- a/mw_js_plugin_test.go +++ b/mw_js_plugin_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/x-cray/logrus-prefixed-formatter" + prefixed "github.com/x-cray/logrus-prefixed-formatter" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/config" diff --git a/reverse_proxy.go b/reverse_proxy.go index 1c01f331096e..7a6615507ca9 100644 --- a/reverse_proxy.go +++ b/reverse_proxy.go @@ -27,7 +27,7 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/pmylund/go-cache" + cache "github.com/pmylund/go-cache" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/config" diff --git a/test/dns.go b/test/dns.go index 8e6aefced82c..13d9e7ece0dc 100644 --- a/test/dns.go +++ b/test/dns.go @@ -17,9 +17,10 @@ import ( var ( muDefaultResolver sync.RWMutex DomainsToAddresses = map[string][]string{ - "host1.local.": {"127.0.0.1"}, - "host2.local.": {"127.0.0.1"}, - "host3.local.": {"127.0.0.1"}, + "host1.local.": {"127.0.0.1"}, + "host2.local.": {"127.0.0.1"}, + "host3.local.": {"127.0.0.1"}, + "http2.golang.org.": {"130.211.116.44"}, // HTTP/2 server } )