Skip to content

Commit b657deb

Browse files
committed
MEN-5273: proxy: Fix websocket connection for advanced auth settings
By switching to the "enhanced" API for websocket.Dialer from mendersoftware's fork. There is a limitation in current gorilla/websocket.Dialer API in that the user cannot specify a dial method for TLS/TCP connections. The TLS handshake is always done by the library based on user's TLSClientConfig, but that is not enough for Mender as we need it to be done via OpenSSL (aka our dial wrapper for TLS) so that advance auth features like getting the keys from HSM. This commit switches to mendersoftware's fork and modifies the code accordingly (one line change!). The patch has been submitted upstream. See: * gorilla/websocket#745 * gorilla/websocket#746 Changelog: None No changelog, commit 84204a3 claims to support websockets, this commit just fixes a bug there which has not been released. Signed-off-by: Lluis Campos <lluis.campos@northern.tech>
1 parent 0a1882f commit b657deb

File tree

16 files changed

+206
-33
lines changed

16 files changed

+206
-33
lines changed

app/proxy/proxy_ws.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (pc *proxyControllerInner) DoWsUpgrade(w http.ResponseWriter, r *http.Reque
8484

8585
connBackend, resp, err := pc.wsDialer.Dial(wsUrl.String(), requestHeader)
8686
if err != nil {
87-
log.Errorf("couldn't dial to remote backend url %s", err)
87+
log.Errorf("couldn't dial to remote backend url %q, err: %s", wsUrl.String(), err.Error())
8888
if resp != nil {
8989
// WebSocket handshake failed, reply the client with backend's resp
9090
if err := copyResponse(w, resp); err != nil {

app/proxy/proxy_ws_test.go

Lines changed: 139 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
package proxy
1515

1616
import (
17+
"crypto/tls"
18+
"crypto/x509"
19+
"io/ioutil"
1720
"net/http"
1821
"reflect"
1922
"runtime"
@@ -26,21 +29,33 @@ import (
2629
"github.com/stretchr/testify/assert"
2730
"github.com/stretchr/testify/require"
2831

32+
"github.com/mendersoftware/mender/client"
2933
cltest "github.com/mendersoftware/mender/client/test"
34+
"github.com/mendersoftware/mender/conf"
3035
)
3136

32-
func prepareProxyWsTest(
33-
t *testing.T,
34-
srv *cltest.ClientTestWsServer,
35-
) (*ProxyController, *websocket.Conn) {
37+
func prepareProxyWsTest(t *testing.T, srv *cltest.ClientTestWsServer) *ProxyController {
38+
39+
wsDialer, err := client.NewWebsocketDialer(client.Config{})
40+
require.NoError(t, err)
41+
3642
proxyController, err := NewProxyController(
3743
&http.Client{},
38-
nil,
44+
wsDialer,
3945
srv.TestServer.URL,
4046
"SecretJwtToken",
4147
)
4248
require.NoError(t, err)
4349

50+
return proxyController
51+
}
52+
53+
func connectProxyWsTest(
54+
t *testing.T,
55+
srv *cltest.ClientTestWsServer,
56+
proxyController *ProxyController,
57+
) *websocket.Conn {
58+
4459
proxyServerUrl := proxyController.GetServerUrl()
4560
require.Contains(t, proxyServerUrl, "http://localhost")
4661

@@ -51,14 +66,25 @@ func prepareProxyWsTest(
5166
require.NoError(t, err)
5267
require.Equal(t, http.StatusSwitchingProtocols, resp.StatusCode)
5368

54-
return proxyController, conn
69+
return conn
5570
}
5671

57-
func TestProxyWsConnect(t *testing.T) {
58-
srv := cltest.NewClientTestWsServer()
59-
defer srv.StopWs()
60-
defer srv.Close()
72+
func prepareAndConnectProxyWsTest(
73+
t *testing.T,
74+
srv *cltest.ClientTestWsServer,
75+
) (*ProxyController, *websocket.Conn) {
6176

77+
proxyController := prepareProxyWsTest(t, srv)
78+
conn := connectProxyWsTest(t, srv, proxyController)
79+
80+
return proxyController, conn
81+
}
82+
83+
func runTestSendReceiveWs(
84+
t *testing.T,
85+
srv *cltest.ClientTestWsServer,
86+
proxyController *ProxyController,
87+
) {
6288
// Expectations for the test
6389
srv.Connect.SendMessages = append(
6490
srv.Connect.SendMessages,
@@ -82,8 +108,8 @@ func TestProxyWsConnect(t *testing.T) {
82108
{MsgType: websocket.TextMessage, Msg: []byte("hello-world")},
83109
}
84110

85-
proxyController, conn := prepareProxyWsTest(t, srv)
86-
defer proxyController.Stop()
111+
conn := connectProxyWsTest(t, srv, proxyController)
112+
87113
defer conn.Close()
88114

89115
wg := sync.WaitGroup{}
@@ -150,6 +176,17 @@ func TestProxyWsConnect(t *testing.T) {
150176
)
151177
}
152178

179+
func TestProxyWsConnect(t *testing.T) {
180+
srv := cltest.NewClientTestWsServer()
181+
defer srv.StopWs()
182+
defer srv.Close()
183+
184+
proxyController := prepareProxyWsTest(t, srv)
185+
defer proxyController.Stop()
186+
187+
runTestSendReceiveWs(t, srv, proxyController)
188+
}
189+
153190
func TestProxyWsWebSocketProtocolHeader(t *testing.T) {
154191
srv := cltest.NewClientTestWsServer()
155192
defer srv.StopWs()
@@ -195,7 +232,7 @@ func TestProxyWsTooMany(t *testing.T) {
195232
defer srv.StopWs()
196233
defer srv.Close()
197234

198-
proxyController, conn := prepareProxyWsTest(t, srv)
235+
proxyController, conn := prepareAndConnectProxyWsTest(t, srv)
199236
defer proxyController.Stop()
200237
defer conn.Close()
201238

@@ -218,7 +255,7 @@ func TestProxyWsStop(t *testing.T) {
218255
defer srv.StopWs()
219256
defer srv.Close()
220257

221-
proxyController, conn := prepareProxyWsTest(t, srv)
258+
proxyController, conn := prepareAndConnectProxyWsTest(t, srv)
222259
defer proxyController.Stop()
223260
defer conn.Close()
224261

@@ -309,3 +346,91 @@ func TestProxyWsGoroutines(t *testing.T) {
309346
1*time.Millisecond,
310347
)
311348
}
349+
350+
func TestProxyWsConnectCustomCert(t *testing.T) {
351+
serverCert, err := tls.LoadX509KeyPair(
352+
"../../client/test/server.crt",
353+
"../../client/test/server.key",
354+
)
355+
require.NoError(t, err)
356+
357+
tc := tls.Config{
358+
Certificates: []tls.Certificate{serverCert},
359+
}
360+
361+
srv := cltest.NewClientTestWsServer(&tc)
362+
defer srv.StopWs()
363+
defer srv.Close()
364+
365+
conffromfile := conf.MenderConfigFromFile{
366+
ServerCertificate: "../../client/test/server.crt",
367+
}
368+
testconf := &conf.MenderConfig{MenderConfigFromFile: conffromfile}
369+
httpConfig := testconf.GetHttpConfig()
370+
371+
api, err := client.New(httpConfig)
372+
require.NoError(t, err)
373+
374+
wsDialer, err := client.NewWebsocketDialer(httpConfig)
375+
require.NoError(t, err)
376+
377+
proxyController, err := NewProxyController(
378+
api,
379+
wsDialer,
380+
srv.TestServer.URL,
381+
"SecretJwtToken",
382+
)
383+
require.NoError(t, err)
384+
defer proxyController.Stop()
385+
386+
runTestSendReceiveWs(t, srv, proxyController)
387+
}
388+
func TestProxyWsConnectMutualTLS(t *testing.T) {
389+
serverCert, err := tls.LoadX509KeyPair(
390+
"../../client/test/server.crt",
391+
"../../client/test/server.key",
392+
)
393+
require.NoError(t, err)
394+
395+
clientClientCertPool := x509.NewCertPool()
396+
pb, err := ioutil.ReadFile("../../client/testdata/client.crt")
397+
require.NoError(t, err)
398+
clientClientCertPool.AppendCertsFromPEM(pb)
399+
400+
tc := tls.Config{
401+
Certificates: []tls.Certificate{serverCert},
402+
ClientAuth: tls.RequireAndVerifyClientCert,
403+
ClientCAs: clientClientCertPool,
404+
}
405+
406+
srv := cltest.NewClientTestWsServer(&tc)
407+
defer srv.StopWs()
408+
defer srv.Close()
409+
410+
conffromfile := conf.MenderConfigFromFile{
411+
ServerCertificate: "../../client/test/server.crt",
412+
HttpsClient: client.HttpsClient{
413+
Certificate: "../../client/testdata/client.crt",
414+
Key: "../../client/testdata/client-cert.key",
415+
},
416+
}
417+
testconf := &conf.MenderConfig{MenderConfigFromFile: conffromfile}
418+
httpConfig := testconf.GetHttpConfig()
419+
420+
api, err := client.New(httpConfig)
421+
require.NoError(t, err)
422+
423+
wsDialer, err := client.NewWebsocketDialer(httpConfig)
424+
require.NoError(t, err)
425+
426+
proxyController, err := NewProxyController(
427+
api,
428+
wsDialer,
429+
srv.TestServer.URL,
430+
"SecretJwtToken",
431+
)
432+
require.NoError(t, err)
433+
defer proxyController.Stop()
434+
435+
runTestSendReceiveWs(t, srv, proxyController)
436+
}

client/client.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,7 @@ func loadClientTrust(ctx *openssl.Ctx, conf *Config) (*openssl.Ctx, error) {
489489
return ctx, nil
490490
}
491491

492-
func dialOpenSSL(ctx *openssl.Ctx, conf *Config, network string, addr string) (net.Conn, error) {
493-
492+
func dialOpenSSL(ctx *openssl.Ctx, conf *Config, _ string, addr string) (net.Conn, error) {
494493
flags := openssl.DialFlags(0)
495494

496495
if conf.NoVerify {
@@ -694,7 +693,7 @@ func newWebsocketDialerTLS(conf Config) (*websocket.Dialer, error) {
694693
}
695694

696695
dialer := websocket.Dialer{
697-
NetDial: func(network string, addr string) (net.Conn, error) {
696+
NetDialTLS: func(network string, addr string) (net.Conn, error) {
698697
return dialOpenSSL(ctx, &conf, network, addr)
699698
},
700699
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ require (
2121
)
2222

2323
replace github.com/urfave/cli/v2 => github.com/mendersoftware/cli/v2 v2.1.1-minimal
24+
25+
replace github.com/gorilla/websocket => github.com/mendersoftware/websocket v1.4.3-0.20211210145825-8a45e5d03918

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
1010
github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4=
1111
github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
1212
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
13-
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
14-
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
1513
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
1614
github.com/klauspost/compress v1.10.5 h1:7q6vHIqubShURwQz8cQK6yIe/xC3IF0Vm7TGfqjewrc=
1715
github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
@@ -34,6 +32,8 @@ github.com/mendersoftware/openssl v1.1.0 h1:eRiG3CwzkMIna1xrTE9SiX9lrsme9irlb6i5
3432
github.com/mendersoftware/openssl v1.1.0/go.mod h1:tikEC94q+Y0TU6r19L6mHzwruoTNYPEkrQPvsHEcQyU=
3533
github.com/mendersoftware/progressbar v0.0.3 h1:AUdBGPvXO0l9i39rmXKZbEAPet2FzBeiG8b30D5/2Vc=
3634
github.com/mendersoftware/progressbar v0.0.3/go.mod h1:NYaLNLhy3UXkRweGjhR3We3Q1ngmUmOWjC3+m8EzwjE=
35+
github.com/mendersoftware/websocket v1.4.3-0.20211210145825-8a45e5d03918 h1:bxs2j1011PQiBPAP127cmBdAnw+zzq65tWOUeCFxVXU=
36+
github.com/mendersoftware/websocket v1.4.3-0.20211210145825-8a45e5d03918/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
3737
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
3838
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
3939
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

vendor/github.com/gorilla/websocket/client.go

Lines changed: 48 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/gorilla/websocket/client_clone.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/gorilla/websocket/client_clone_legacy.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/gorilla/websocket/conn_write.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/gorilla/websocket/conn_write_legacy.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)