Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 2b838a9

Browse files
committed
Enforce coder-cli in PATH on Windows
1 parent 4850266 commit 2b838a9

File tree

1 file changed

+42
-2
lines changed

1 file changed

+42
-2
lines changed

internal/cmd/configssh.go

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io/ioutil"
77
"net/url"
88
"os"
9+
"os/exec"
910
"os/user"
1011
"path/filepath"
1112
"runtime"
@@ -114,8 +115,11 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
114115
return xerrors.New("SSH is disabled or not available for any workspaces in your Coder deployment.")
115116
}
116117

117-
binPath, err := os.Executable()
118+
binPath, err := binPath()
118119
if err != nil {
120+
if runtime.GOOS == "windows" {
121+
return xerrors.Errorf("Failed to ensure `coder` is in $PATH, please move the `coder` binary to a location in $PATH (such as System32): %w", err)
122+
}
119123
return xerrors.Errorf("Failed to get executable path: %w", err)
120124
}
121125

@@ -147,6 +151,42 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
147151
}
148152
}
149153

154+
// binPath returns the path to the coder binary suitable for use in ssh
155+
// ProxyCommand.
156+
func binPath() (string, error) {
157+
exePath, err := os.Executable()
158+
if err != nil {
159+
return "", xerrors.Errorf("get executable path: %w", err)
160+
}
161+
162+
// On Windows, the coder-cli executable must be in $PATH for Msys2 and Git
163+
// Bash to function correctly. To prevent weird behavior when people switch
164+
// between the two, we require this for all users.
165+
if runtime.GOOS == "windows" {
166+
binName := filepath.Base(exePath)
167+
pathPath, err := exec.LookPath(exePath)
168+
if err != nil {
169+
return "", xerrors.Errorf("locate %q in $PATH: %w", binName, err)
170+
}
171+
172+
// Warn the user if the current executable is not the same as the one in
173+
// $PATH.
174+
if filepath.Clean(pathPath) != filepath.Clean(exePath) {
175+
clog.LogWarn(
176+
"The current executable path does not match the executable path found in $PATH.",
177+
"This may lead to problems connecting to your workspace via SSH.",
178+
fmt.Sprintf("\t Current executable path: %q", exePath),
179+
fmt.Sprintf("\tExecutable path in $PATH: %q", pathPath),
180+
)
181+
}
182+
183+
return binName, nil
184+
}
185+
186+
// On platforms other than Windows we can use the full path to the binary.
187+
return exePath, nil
188+
}
189+
150190
// removeOldConfig removes the old ssh configuration from the user's sshconfig.
151191
// Returns true if the config was modified.
152192
func removeOldConfig(config string) (string, bool) {
@@ -212,7 +252,7 @@ func makeSSHConfig(binPath, host, userName, workspaceName, privateKeyFilepath st
212252
host := fmt.Sprintf(
213253
`Host coder.%s
214254
HostName coder.%s
215-
ProxyCommand %s tunnel %s 12213 stdio
255+
ProxyCommand "%s" tunnel %s 12213 stdio
216256
StrictHostKeyChecking no
217257
ConnectTimeout=0
218258
IdentitiesOnly yes

0 commit comments

Comments
 (0)