Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix auto-update re-exec arguments modified by aliases #50228

Merged
merged 7 commits into from
Jan 17, 2025
2 changes: 1 addition & 1 deletion integration/autoupdate/tools/updater/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func main() {
}

// Re-execute client tools with the correct version of client tools.
code, err := updater.Exec()
code, err := updater.Exec(os.Args[1:])
if err != nil {
log.Fatalf("Failed to re-exec client tool: %v\n", err)
} else {
Expand Down
12 changes: 6 additions & 6 deletions lib/autoupdate/tools/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
// with the updated version.
// If $TELEPORT_HOME/bin contains downloaded client tools, it always re-executes
// using the version from the home directory.
func CheckAndUpdateLocal(ctx context.Context, currentVersion string) error {
func CheckAndUpdateLocal(ctx context.Context, currentVersion string, reExecArgs []string) error {
toolsDir, err := Dir()
if err != nil {
slog.WarnContext(ctx, "Client tools update is disabled", "error", err)
Expand All @@ -51,7 +51,7 @@ func CheckAndUpdateLocal(ctx context.Context, currentVersion string) error {
return trace.Wrap(err)
}
if reExec {
return trace.Wrap(updateAndReExec(ctx, updater, toolsVersion))
return trace.Wrap(updateAndReExec(ctx, updater, toolsVersion, reExecArgs))
}

return nil
Expand All @@ -64,7 +64,7 @@ func CheckAndUpdateLocal(ctx context.Context, currentVersion string) error {
// with the updated version.
// If $TELEPORT_HOME/bin contains downloaded client tools, it always re-executes
// using the version from the home directory.
func CheckAndUpdateRemote(ctx context.Context, currentVersion string, proxy string, insecure bool) error {
func CheckAndUpdateRemote(ctx context.Context, currentVersion string, proxy string, insecure bool, reExecArgs []string) error {
toolsDir, err := Dir()
if err != nil {
slog.WarnContext(ctx, "Client tools update is disabled", "error", err)
Expand All @@ -81,13 +81,13 @@ func CheckAndUpdateRemote(ctx context.Context, currentVersion string, proxy stri
return trace.Wrap(err)
}
if reExec {
return trace.Wrap(updateAndReExec(ctx, updater, toolsVersion))
return trace.Wrap(updateAndReExec(ctx, updater, toolsVersion, reExecArgs))
}

return nil
}

func updateAndReExec(ctx context.Context, updater *Updater, toolsVersion string) error {
func updateAndReExec(ctx context.Context, updater *Updater, toolsVersion string, args []string) error {
ctxUpdate, cancel := stacksignal.GetSignalHandler().NotifyContext(ctx)
defer cancel()
// Download the version of client tools required by the cluster. This
Expand All @@ -99,7 +99,7 @@ func updateAndReExec(ctx context.Context, updater *Updater, toolsVersion string)
}

// Re-execute client tools with the correct version of client tools.
code, err := updater.Exec()
code, err := updater.Exec(args)
if err != nil && !errors.Is(err, os.ErrNotExist) {
slog.DebugContext(ctx, "Failed to re-exec client tool", "error", err)
os.Exit(code)
Expand Down
9 changes: 4 additions & 5 deletions lib/autoupdate/tools/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const (
)

var (
// // pattern is template for response on version command for client tools {tsh, tctl}.
// pattern is template for response on version command for client tools {tsh, tctl}.
pattern = regexp.MustCompile(`(?m)Teleport v(.*) git`)
)

Expand Down Expand Up @@ -327,7 +327,7 @@ func (u *Updater) update(ctx context.Context, pkg packageURL, pkgName string) er
}

// Exec re-executes tool command with same arguments and environ variables.
func (u *Updater) Exec() (int, error) {
func (u *Updater) Exec(args []string) (int, error) {
path, err := toolName(u.toolsDir)
if err != nil {
return 0, trace.Wrap(err)
Expand All @@ -336,7 +336,7 @@ func (u *Updater) Exec() (int, error) {
env := append(os.Environ(), teleportToolsVersionEnv+"=off")

if runtime.GOOS == constants.WindowsOS {
cmd := exec.Command(path, os.Args[1:]...)
cmd := exec.Command(path, args...)
cmd.Env = env
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
Expand All @@ -348,7 +348,7 @@ func (u *Updater) Exec() (int, error) {
return cmd.ProcessState.ExitCode(), nil
}

if err := syscall.Exec(path, append([]string{path}, os.Args[1:]...), env); err != nil {
if err := syscall.Exec(path, append([]string{path}, args...), env); err != nil {
return 0, trace.Wrap(err)
}

Expand Down Expand Up @@ -415,7 +415,6 @@ func (u *Updater) downloadArchive(ctx context.Context, url string, f io.Writer)
return nil, trace.Wrap(err)
}
}

h := sha256.New()
// It is a little inefficient to download the file to disk and then re-load
// it into memory to unarchive later, but this is safer as it allows client
Expand Down
2 changes: 1 addition & 1 deletion lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ func RetryWithRelogin(ctx context.Context, tc *TeleportClient, fn func() error,
return trace.Wrap(err)
}

if err := tools.CheckAndUpdateRemote(ctx, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify); err != nil {
if err := tools.CheckAndUpdateRemote(ctx, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify, os.Args[1:]); err != nil {
return trace.Wrap(err)
}

Expand Down
2 changes: 1 addition & 1 deletion tool/tctl/common/tctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type CLICommand interface {
//
// distribution: name of the Teleport distribution
func Run(ctx context.Context, commands []CLICommand) {
if err := tools.CheckAndUpdateLocal(ctx, teleport.Version); err != nil {
if err := tools.CheckAndUpdateLocal(ctx, teleport.Version, os.Args[1:]); err != nil {
utils.FatalError(err)
}

Expand Down
14 changes: 7 additions & 7 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ func initLogger(cf *CLIConf) {
//
// DO NOT RUN TESTS that call Run() in parallel (unless you taken precautions).
func Run(ctx context.Context, args []string, opts ...CliOption) error {
if err := tools.CheckAndUpdateLocal(ctx, teleport.Version); err != nil {
if err := tools.CheckAndUpdateLocal(ctx, teleport.Version, args); err != nil {
return trace.Wrap(err)
}

Expand Down Expand Up @@ -1490,7 +1490,7 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {
case sessionsList.FullCommand():
err = onListSessions(&cf)
case login.FullCommand():
err = onLogin(&cf)
err = onLogin(&cf, args...)
case logout.FullCommand():
err = onLogout(&cf)
case show.FullCommand():
Expand Down Expand Up @@ -1845,7 +1845,7 @@ func serializeVersion(format string, proxyVersion string, proxyPublicAddress str
}

// onLogin logs in with remote proxy and gets signed certificates
func onLogin(cf *CLIConf) error {
func onLogin(cf *CLIConf, reExecArgs ...string) error {
autoRequest := true
// special case: --request-roles=no disables auto-request behavior.
if cf.DesiredRoles == "no" {
Expand Down Expand Up @@ -1886,7 +1886,7 @@ func onLogin(cf *CLIConf) error {
// The user is not logged in and has typed in `tsh --proxy=... login`, if
// the running binary needs to be updated, update and re-exec.
if profile == nil {
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify); err != nil {
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify, reExecArgs); err != nil {
return trace.Wrap(err)
}
}
Expand All @@ -1904,7 +1904,7 @@ func onLogin(cf *CLIConf) error {

// The user has typed `tsh login`, if the running binary needs to
// be updated, update and re-exec.
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify); err != nil {
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify, reExecArgs); err != nil {
return trace.Wrap(err)
}

Expand All @@ -1924,7 +1924,7 @@ func onLogin(cf *CLIConf) error {

// The user has typed `tsh login`, if the running binary needs to
// be updated, update and re-exec.
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify); err != nil {
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify, reExecArgs); err != nil {
return trace.Wrap(err)
}

Expand Down Expand Up @@ -2000,7 +2000,7 @@ func onLogin(cf *CLIConf) error {
default:
// The user is logged in and has typed in `tsh --proxy=... login`, if
// the running binary needs to be updated, update and re-exec.
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify); err != nil {
if err := tools.CheckAndUpdateRemote(cf.Context, teleport.Version, tc.WebProxyAddr, tc.InsecureSkipVerify, reExecArgs); err != nil {
return trace.Wrap(err)
}
}
Expand Down
Loading