From e34e0ccd120849df13e7df49430e0b4b3f21aeeb Mon Sep 17 00:00:00 2001 From: Misha Bragin Date: Sat, 30 Jul 2022 19:17:18 +0200 Subject: [PATCH] Check and update Agent's Management URL if is legacy (#406) All the existing agents by default connect to port 33073 of the Management service. This value is also stored in the local config. All the agents won't switch to the new port 443 unless explicitly specified in the config. We want the transition to be smooth for our users, therefore this PR adds logic to check whether the old port 33073 can be changed to 443 and updates the config automatically. --- client/cmd/login.go | 2 ++ client/cmd/up.go | 2 ++ client/internal/config.go | 13 ++++---- client/internal/connect.go | 65 ++++++++++++++++++++++++++++++++++++++ client/internal/login.go | 3 +- client/server/server.go | 7 ++++ 6 files changed, 84 insertions(+), 8 deletions(-) diff --git a/client/cmd/login.go b/client/cmd/login.go index d17a9265b..2331e0b63 100644 --- a/client/cmd/login.go +++ b/client/cmd/login.go @@ -43,6 +43,8 @@ var loginCmd = &cobra.Command{ return fmt.Errorf("get config file: %v", err) } + config, _ = internal.UpdateOldManagementPort(ctx, config, configPath) + err = foregroundLogin(ctx, cmd, config, setupKey) if err != nil { return fmt.Errorf("foreground login failed: %v", err) diff --git a/client/cmd/up.go b/client/cmd/up.go index 98ee9e559..2501dcb7a 100644 --- a/client/cmd/up.go +++ b/client/cmd/up.go @@ -40,6 +40,8 @@ var upCmd = &cobra.Command{ return fmt.Errorf("get config file: %v", err) } + config, _ = internal.UpdateOldManagementPort(ctx, config, configPath) + err = foregroundLogin(ctx, cmd, config, setupKey) if err != nil { return fmt.Errorf("foreground login failed: %v", err) diff --git a/client/internal/config.go b/client/internal/config.go index e1dc62b3f..18eef58fc 100644 --- a/client/internal/config.go +++ b/client/internal/config.go @@ -22,7 +22,7 @@ func ManagementURLDefault() *url.URL { } func init() { - managementURL, err := parseURL("Management URL", "https://api.wiretrustee.com:443") + managementURL, err := ParseURL("Management URL", "https://api.wiretrustee.com:443") if err != nil { panic(err) } @@ -51,7 +51,7 @@ func createNewConfig(managementURL, adminURL, configPath, preSharedKey string) ( } config := &Config{SSHKey: string(pem), PrivateKey: wgKey, WgIface: iface.WgInterfaceDefault, IFaceBlackList: []string{}} if managementURL != "" { - URL, err := parseURL("Management URL", managementURL) + URL, err := ParseURL("Management URL", managementURL) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func createNewConfig(managementURL, adminURL, configPath, preSharedKey string) ( } if adminURL != "" { - newURL, err := parseURL("Admin Panel URL", adminURL) + newURL, err := ParseURL("Admin Panel URL", adminURL) if err != nil { return nil, err } @@ -83,7 +83,8 @@ func createNewConfig(managementURL, adminURL, configPath, preSharedKey string) ( return config, nil } -func parseURL(serviceName, managementURL string) (*url.URL, error) { +// ParseURL parses and validates management URL +func ParseURL(serviceName, managementURL string) (*url.URL, error) { parsedMgmtURL, err := url.ParseRequestURI(managementURL) if err != nil { log.Errorf("failed parsing management URL %s: [%s]", managementURL, err.Error()) @@ -115,7 +116,7 @@ func ReadConfig(managementURL, adminURL, configPath string, preSharedKey *string if managementURL != "" && config.ManagementURL.String() != managementURL { log.Infof("new Management URL provided, updated to %s (old value %s)", managementURL, config.ManagementURL) - newURL, err := parseURL("Management URL", managementURL) + newURL, err := ParseURL("Management URL", managementURL) if err != nil { return nil, err } @@ -126,7 +127,7 @@ func ReadConfig(managementURL, adminURL, configPath string, preSharedKey *string if adminURL != "" && (config.AdminURL == nil || config.AdminURL.String() != adminURL) { log.Infof("new Admin Panel URL provided, updated to %s (old value %s)", adminURL, config.AdminURL) - newURL, err := parseURL("Admin Panel URL", adminURL) + newURL, err := ParseURL("Admin Panel URL", adminURL) if err != nil { return nil, err } diff --git a/client/internal/connect.go b/client/internal/connect.go index ab7126d88..fee57695d 100644 --- a/client/internal/connect.go +++ b/client/internal/connect.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/netbirdio/netbird/client/ssh" nbStatus "github.com/netbirdio/netbird/client/status" + mgmtcmd "github.com/netbirdio/netbird/management/cmd" "strings" "time" @@ -239,3 +240,67 @@ func connectToManagement(ctx context.Context, managementAddr string, ourPrivateK return client, loginResp, nil } + +// UpdateOldManagementPort checks whether client can switch to the new Management port 443. +// If it can switch, then it updates the config and returns a new one. Otherwise, it returns the provided config. +// The check is performed only for the NetBird's managed version. +func UpdateOldManagementPort(ctx context.Context, config *Config, configPath string) (*Config, error) { + + if config.ManagementURL.Hostname() != ManagementURLDefault().Hostname() { + // only do the check for the NetBird's managed version + return config, nil + } + + var mgmTlsEnabled bool + if config.ManagementURL.Scheme == "https" { + mgmTlsEnabled = true + } + + if !mgmTlsEnabled { + // only do the check for HTTPs scheme (the hosted version of the Management service is always HTTPs) + return config, nil + } + + if mgmTlsEnabled && config.ManagementURL.Port() == fmt.Sprintf("%d", mgmtcmd.ManagementLegacyPort) { + + newURL, err := ParseURL("Management URL", fmt.Sprintf("%s://%s:%d", + config.ManagementURL.Scheme, config.ManagementURL.Hostname(), 443)) + if err != nil { + return nil, err + } + // here we check whether we could switch from the legacy 33073 port to the new 443 + log.Infof("attempting to switch from the legacy Management URL %s to the new one %s", + config.ManagementURL.String(), newURL.String()) + key, err := wgtypes.ParseKey(config.PrivateKey) + if err != nil { + log.Infof("couldn't switch to the new Management %s", newURL.String()) + return config, err + } + + client, err := mgm.NewClient(ctx, newURL.Host, key, mgmTlsEnabled) + if err != nil { + log.Infof("couldn't switch to the new Management %s", newURL.String()) + return config, err + } + defer client.Close() //nolint + + // gRPC check + _, err = client.GetServerPublicKey() + if err != nil { + log.Infof("couldn't switch to the new Management %s", newURL.String()) + return nil, err + } + + // everything is alright => update the config + newConfig, err := ReadConfig(newURL.String(), "", configPath, nil) + if err != nil { + log.Infof("couldn't switch to the new Management %s", newURL.String()) + return config, fmt.Errorf("failed updating config file: %v", err) + } + log.Infof("successfully switched to the new Management URL: %s", newURL.String()) + + return newConfig, nil + } + + return config, nil +} diff --git a/client/internal/login.go b/client/internal/login.go index a09bd3c21..2064a8b7e 100644 --- a/client/internal/login.go +++ b/client/internal/login.go @@ -49,6 +49,7 @@ func Login(ctx context.Context, config *Config, setupKey string, jwtToken string log.Errorf("failed logging-in peer on Management Service : %v", err) return err } + log.Infof("peer has successfully logged-in to the Management service %s", config.ManagementURL.String()) err = mgmClient.Close() if err != nil { @@ -72,8 +73,6 @@ func loginPeer(ctx context.Context, serverPublicKey wgtypes.Key, client *mgm.Grp } } - log.Info("peer has successfully logged-in to Management Service") - return loginResp, nil } diff --git a/client/server/server.go b/client/server/server.go index 6116bfca6..e8387d40a 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -92,6 +92,7 @@ func (s *Server) Start() error { } // if configuration exists, we just start connections. + config, _ = internal.UpdateOldManagementPort(ctx, config, s.configPath) s.config = config @@ -168,6 +169,12 @@ func (s *Server) Login(callerCtx context.Context, msg *proto.LoginRequest) (*pro return nil, err } + if msg.ManagementUrl == "" { + config, _ = internal.UpdateOldManagementPort(ctx, config, s.configPath) + s.config = config + s.managementURL = config.ManagementURL.String() + } + s.mutex.Lock() s.config = config s.mutex.Unlock()