Skip to content

Commit 84204a3

Browse files
committed
MEN-5216: Local HTTP proxy for Mender server API calls
Changelog: Mender starts a local HTTP server that will proxy incoming requests to `/api/devices` to the currently authenticated Mender server. The existing D-Bus API endpoints GetJwtToken and JwtTokenStateChange will now return the local address together with the JWT token. Supports also websocket upgrade when calling `/api/devices/v1/deviceconnect/connect` endpoint Signed-off-by: Lluis Campos <[email protected]>
1 parent 3bb7b09 commit 84204a3

38 files changed

+5145
-43
lines changed

LIC_FILES_CHKSUM.sha256

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30 vendor/github.
88
# BSD 2 Clause license.
99
8d427fd87bc9579ea368fde3d49f9ca22eac857f91a9dec7e3004bdfab7dee86 vendor/github.com/pkg/errors/LICENSE
1010
e4646a82a976369d7ae8f6ed5c11d35dc0af18433a8ccc24c85b459ad8b95128 vendor/github.com/godbus/dbus/LICENSE
11+
2be1b548b0387ca8948e1bb9434e709126904d15f622cc2d0d8e7f186e4d122d vendor/github.com/gorilla/websocket/LICENSE
1112
#
1213
# BSD 3 Clause license.
1314
16f848582e4b276a7392cd34496b7a33d6f65c0e190c163ff3a056a7c61219ce vendor/github.com/klauspost/compress/LICENSE

app/auth.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/pkg/errors"
2727
log "github.com/sirupsen/logrus"
2828

29+
"github.com/mendersoftware/mender/app/proxy"
2930
"github.com/mendersoftware/mender/client"
3031
"github.com/mendersoftware/mender/conf"
3132
"github.com/mendersoftware/mender/datastore"
@@ -144,6 +145,8 @@ type menderAuthManagerService struct {
144145
idSrc device.IdentityDataGetter
145146
serverURL string
146147
tenantToken client.AuthToken
148+
149+
localProxy *proxy.ProxyController
147150
}
148151

149152
// AuthManagerConfig holds the configuration of the auth manager
@@ -162,13 +165,15 @@ func NewAuthManager(conf AuthManagerConfig) *MenderAuthManager {
162165
return nil
163166
}
164167

165-
var api *client.ApiClient
168+
httpConfig := client.Config{}
166169
if conf.Config != nil {
167-
var err error
168-
api, err = client.New(conf.Config.GetHttpConfig())
169-
if err != nil {
170-
return nil
171-
}
170+
httpConfig = conf.Config.GetHttpConfig()
171+
172+
}
173+
174+
api, err := client.New(httpConfig)
175+
if err != nil {
176+
return nil
172177
}
173178

174179
// get the first server URL available in the config file
@@ -192,6 +197,16 @@ func NewAuthManager(conf AuthManagerConfig) *MenderAuthManager {
192197
log.Errorf("Error handling the caching of the tenant token: %s", err.Error())
193198
}
194199

200+
wsDialer, err := client.NewWebsocketDialer(httpConfig)
201+
if err != nil {
202+
return nil
203+
}
204+
205+
proxy, err := proxy.NewProxyController(api, wsDialer, "", "")
206+
if err != nil {
207+
log.Errorf("Error creating local proxy: %s", err.Error())
208+
}
209+
195210
mgr := &MenderAuthManager{
196211
&menderAuthManagerService{
197212
inChan: make(chan AuthManagerRequest, authManagerInMessageChanSize),
@@ -207,6 +222,7 @@ func NewAuthManager(conf AuthManagerConfig) *MenderAuthManager {
207222
idSrc: conf.IdentitySource,
208223
tenantToken: tenantToken,
209224
serverURL: serverURL,
225+
localProxy: proxy,
210226
},
211227
}
212228

@@ -310,7 +326,7 @@ func (m *menderAuthManagerService) registerDBusCallbacks() (unregisterFunc func(
310326
case message := <-respChan:
311327
tokenAndServerURL := dbus.TokenAndServerURL{
312328
Token: string(message.AuthToken),
313-
ServerURL: m.serverURL,
329+
ServerURL: m.localProxy.GetServerUrl(),
314330
}
315331
return tokenAndServerURL, message.Error
316332
case <-time.After(5 * time.Second):
@@ -370,7 +386,7 @@ func (m *menderAuthManagerService) run() {
370386
// When we are being stopped, make sure they know that this happened.
371387
defer func() {
372388
// Checking for panic here is just to avoid deadlocking if we
373-
// get an unexpected panic: Let it propogate instead of blocking
389+
// get an unexpected panic: Let it propagate instead of blocking
374390
// on the channel. If the program is correct, this should never
375391
// be non-nil.
376392
if recover() == nil {
@@ -487,6 +503,8 @@ func (m *MenderAuthManager) Stop() {
487503
<-m.menderAuthManagerService.quitResp
488504
m.menderAuthManagerService.hasStarted = false
489505

506+
m.localProxy.Stop()
507+
490508
runtime.SetFinalizer(m, nil)
491509
}
492510

@@ -516,7 +534,7 @@ func (m *menderAuthManagerService) broadcast(message AuthManagerResponse) {
516534
if m.dbus != nil {
517535
tokenAndServerURL := dbus.TokenAndServerURL{
518536
Token: string(message.AuthToken),
519-
ServerURL: m.serverURL,
537+
ServerURL: m.localProxy.GetServerUrl(),
520538
}
521539
_ = m.dbus.EmitSignal(m.dbusConn, "", AuthManagerDBusPath,
522540
AuthManagerDBusInterfaceName, AuthManagerDBusSignalJwtTokenStateChange,
@@ -527,7 +545,26 @@ func (m *menderAuthManagerService) broadcast(message AuthManagerResponse) {
527545
// broadcastAuthTokenStateChange broadcasts the notification to all the subscribers
528546
func (m *menderAuthManagerService) broadcastAuthTokenStateChange() {
529547
authToken, err := m.authToken()
548+
549+
// stop proxy regardless
550+
m.localProxy.Stop()
530551
if err == nil {
552+
// reconfigure proxy
553+
err = m.localProxy.Reconfigure(m.serverURL, string(authToken))
554+
if err != nil {
555+
log.Errorf(
556+
"Could not reconfigure proxy with URL %q and token '%s...'"+
557+
" Other applications running on the device won't be able"+
558+
" to reach the Mender server. Error: %s",
559+
m.serverURL,
560+
string(authToken)[:7],
561+
err.Error(),
562+
)
563+
} else {
564+
m.localProxy.Start()
565+
566+
}
567+
531568
m.broadcast(AuthManagerResponse{
532569
Event: EventAuthTokenStateChange,
533570
AuthToken: authToken,

app/mender_test.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ func TestReauthorization(t *testing.T) {
952952
assert.Error(t, err)
953953
}
954954

955-
// TestFailbackServers tests the optional failover feature for which
955+
// TestFailoverServers tests the optional failover feature for which
956956
// a client can swap server if current server stops serving.
957957
//
958958
// Add multiple servers into conf.MenderConfig, and let the first one "fail".
@@ -979,6 +979,11 @@ func TestFailoverServers(t *testing.T) {
979979
srv2 := cltest.NewClientTestServer()
980980
defer srv1.Close()
981981
defer srv2.Close()
982+
// Give srv1 the wrong artifact- and device name to trigger 400 Bad Request
983+
srv1.Update.Current = &client.CurrentUpdate{
984+
Artifact: "mender-image-foo",
985+
DeviceType: "dev-bar",
986+
}
982987
// Give srv2 knowledge about client artifact- and device name
983988
srv2.Update.Current = &client.CurrentUpdate{
984989
Artifact: "mender-image",
@@ -1132,10 +1137,7 @@ func TestMutualTLSClientConnection(t *testing.T) {
11321137

11331138
for name, test := range tests {
11341139
t.Run(name, func(t *testing.T) {
1135-
srv := cltest.NewClientTestServer(
1136-
cltest.Options{
1137-
TLSConfig: &tc,
1138-
})
1140+
srv := cltest.NewClientTestServer(&tc)
11391141
defer srv.Close()
11401142

11411143
test.conf.ServerURL = srv.URL

0 commit comments

Comments
 (0)