mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(agent): unify working directory resolution (#26102)
agentssh's CommandEnv, sftpHandler, and agentproc each resolved the session working directory on their own and had drifted: sftpHandler used the configured directory without checking it exists and bypassed the injected EnvInfoer, while the others stat-checked and fell back to home. Home and shell lookups could also skip the EnvInfoer seam through the exported usershell.HomeDir and Get. Resolve through a single usershell.ResolveWorkingDirectory and confine host home and shell lookups to usershell, so SSH sessions, the process API, and tests can no longer diverge and the injected environment is always honored. This also fixes SFTP landing in a configured directory that no longer exists. Refs coder/coder#26099
This commit is contained in:
@@ -4,13 +4,15 @@ import (
|
||||
"os"
|
||||
"os/user"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// HomeDir returns the home directory of the current user, giving
|
||||
// priority to the $HOME environment variable.
|
||||
// Deprecated: use EnvInfoer.HomeDir() instead.
|
||||
func HomeDir() (string, error) {
|
||||
// homeDir returns the home directory of the current user, giving
|
||||
// priority to the $HOME environment variable. It backs
|
||||
// SystemEnvInfo.HomeDir. Callers outside this package resolve the home
|
||||
// directory through an EnvInfoer so the injected environment is honored.
|
||||
func homeDir() (string, error) {
|
||||
// First we check the environment.
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err == nil {
|
||||
@@ -25,6 +27,20 @@ func HomeDir() (string, error) {
|
||||
return u.HomeDir, nil
|
||||
}
|
||||
|
||||
// ResolveWorkingDirectory returns dir when it is non-empty and an existing
|
||||
// directory on fs. Otherwise it falls back to the home directory
|
||||
// reported by ei. SSH sessions and the process API share this so their
|
||||
// working directory resolution cannot drift, and the home fallback goes
|
||||
// through the injected EnvInfoer rather than the host directly.
|
||||
func ResolveWorkingDirectory(fs afero.Fs, ei EnvInfoer, dir string) (string, error) {
|
||||
if dir != "" {
|
||||
if info, err := fs.Stat(dir); err == nil && info.IsDir() {
|
||||
return dir, nil
|
||||
}
|
||||
}
|
||||
return ei.HomeDir()
|
||||
}
|
||||
|
||||
// EnvInfoer encapsulates external information about the environment.
|
||||
type EnvInfoer interface {
|
||||
// User returns the current user.
|
||||
@@ -64,11 +80,11 @@ func (SystemEnvInfo) Environ() []string {
|
||||
}
|
||||
|
||||
func (SystemEnvInfo) HomeDir() (string, error) {
|
||||
return HomeDir()
|
||||
return homeDir()
|
||||
}
|
||||
|
||||
func (SystemEnvInfo) Shell(username string) (string, error) {
|
||||
return Get(username)
|
||||
return get(username)
|
||||
}
|
||||
|
||||
func (SystemEnvInfo) ModifyCommand(name string, args ...string) (string, []string) {
|
||||
|
||||
Reference in New Issue
Block a user