Commit cc14366f authored by Jacob Vosmaer's avatar Jacob Vosmaer

Merge branch 'mk/add-workhorse-support-for-https-backend' into 'master'

Add Workhorse support for HTTPS backend

See merge request gitlab-org/gitlab!67700
parents af8b3a7c 6764676e
...@@ -2,6 +2,7 @@ package roundtripper ...@@ -2,6 +2,7 @@ package roundtripper
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"net" "net"
"net/http" "net/http"
...@@ -15,10 +16,6 @@ import ( ...@@ -15,10 +16,6 @@ import (
) )
func mustParseAddress(address, scheme string) string { func mustParseAddress(address, scheme string) string {
if scheme == "https" {
panic("TLS is not supported for backend connections")
}
for _, suffix := range []string{"", ":" + scheme} { for _, suffix := range []string{"", ":" + scheme} {
address += suffix address += suffix
if host, port, err := net.SplitHostPort(address); err == nil && host != "" && port != "" { if host, port, err := net.SplitHostPort(address); err == nil && host != "" && port != "" {
...@@ -31,9 +28,14 @@ func mustParseAddress(address, scheme string) string { ...@@ -31,9 +28,14 @@ func mustParseAddress(address, scheme string) string {
// NewBackendRoundTripper returns a new RoundTripper instance using the provided values // NewBackendRoundTripper returns a new RoundTripper instance using the provided values
func NewBackendRoundTripper(backend *url.URL, socket string, proxyHeadersTimeout time.Duration, developmentMode bool) http.RoundTripper { func NewBackendRoundTripper(backend *url.URL, socket string, proxyHeadersTimeout time.Duration, developmentMode bool) http.RoundTripper {
return newBackendRoundTripper(backend, socket, proxyHeadersTimeout, developmentMode, nil)
}
func newBackendRoundTripper(backend *url.URL, socket string, proxyHeadersTimeout time.Duration, developmentMode bool, tlsConf *tls.Config) http.RoundTripper {
// Copied from the definition of http.DefaultTransport. We can't literally copy http.DefaultTransport because of its hidden internal state. // Copied from the definition of http.DefaultTransport. We can't literally copy http.DefaultTransport because of its hidden internal state.
transport, dialer := newBackendTransport() transport, dialer := newBackendTransport()
transport.ResponseHeaderTimeout = proxyHeadersTimeout transport.ResponseHeaderTimeout = proxyHeadersTimeout
transport.TLSClientConfig = tlsConf
if backend != nil && socket == "" { if backend != nil && socket == "" {
address := mustParseAddress(backend.Host, backend.Scheme) address := mustParseAddress(backend.Host, backend.Scheme)
......
package roundtripper package roundtripper
import ( import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strconv" "strconv"
"testing" "testing"
...@@ -12,6 +19,7 @@ func TestMustParseAddress(t *testing.T) { ...@@ -12,6 +19,7 @@ func TestMustParseAddress(t *testing.T) {
{"1.2.3.4:56", "http", "1.2.3.4:56"}, {"1.2.3.4:56", "http", "1.2.3.4:56"},
{"[::1]:23", "http", "::1:23"}, {"[::1]:23", "http", "::1:23"},
{"4.5.6.7", "http", "4.5.6.7:http"}, {"4.5.6.7", "http", "4.5.6.7:http"},
{"4.5.6.7", "https", "4.5.6.7:https"},
} }
for i, example := range successExamples { for i, example := range successExamples {
t.Run(strconv.Itoa(i), func(t *testing.T) { t.Run(strconv.Itoa(i), func(t *testing.T) {
...@@ -23,7 +31,6 @@ func TestMustParseAddress(t *testing.T) { ...@@ -23,7 +31,6 @@ func TestMustParseAddress(t *testing.T) {
func TestMustParseAddressPanic(t *testing.T) { func TestMustParseAddressPanic(t *testing.T) {
panicExamples := []struct{ address, scheme string }{ panicExamples := []struct{ address, scheme string }{
{"1.2.3.4", ""}, {"1.2.3.4", ""},
{"1.2.3.4", "https"},
} }
for i, panicExample := range panicExamples { for i, panicExample := range panicExamples {
...@@ -37,3 +44,50 @@ func TestMustParseAddressPanic(t *testing.T) { ...@@ -37,3 +44,50 @@ func TestMustParseAddressPanic(t *testing.T) {
}) })
} }
} }
func TestSupportsHTTPBackend(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
fmt.Fprint(w, "successful response")
}))
defer ts.Close()
testNewBackendRoundTripper(t, ts, nil, "successful response")
}
func TestSupportsHTTPSBackend(t *testing.T) {
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
fmt.Fprint(w, "successful response")
}))
defer ts.Close()
certpool := x509.NewCertPool()
certpool.AddCert(ts.Certificate())
tlsClientConfig := &tls.Config{
RootCAs: certpool,
}
testNewBackendRoundTripper(t, ts, tlsClientConfig, "successful response")
}
func testNewBackendRoundTripper(t *testing.T, ts *httptest.Server, tlsClientConfig *tls.Config, expectedResponseBody string) {
t.Helper()
backend, err := url.Parse(ts.URL)
require.NoError(t, err, "parse url")
rt := newBackendRoundTripper(backend, "", 0, true, tlsClientConfig)
req, err := http.NewRequest("GET", ts.URL+"/", nil)
require.NoError(t, err, "build request")
response, err := rt.RoundTrip(req)
require.NoError(t, err, "perform roundtrip")
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
require.NoError(t, err)
require.Equal(t, expectedResponseBody, string(body))
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment