From 1d9c414ac84a3ce4b94d696c592800033dfac870 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 11 Mar 2025 01:20:55 +0200 Subject: [PATCH 1/3] feat(agent): set additional login vars, LOGNAME and SHELL This change stes additional env vars. This is useful for programs that assume their presence (for instance, Zed remote relies on SHELL). See `man login`. --- agent/agent_test.go | 47 ++++++++++++++++++++++++++++++++++++++ agent/agentssh/agentssh.go | 3 +++ 2 files changed, 50 insertions(+) diff --git a/agent/agent_test.go b/agent/agent_test.go index d6c8e4d97644c..ef67a4a8b9f7a 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -51,6 +51,7 @@ import ( "github.com/coder/coder/v2/agent/agentssh" "github.com/coder/coder/v2/agent/agenttest" "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/agent/usershell" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" "github.com/coder/coder/v2/codersdk/workspacesdk" @@ -1193,6 +1194,52 @@ func TestAgent_SSHConnectionEnvVars(t *testing.T) { } } +func TestAgent_SSHConnectionLoginVars(t *testing.T) { + t.Parallel() + + envInfo := usershell.SystemEnvInfo{} + u, err := envInfo.User() + require.NoError(t, err, "get current user") + shell, err := envInfo.Shell(u.Username) + require.NoError(t, err, "get current shell") + + tests := []struct { + key string + want string + }{ + { + key: "USER", + want: u.Username, + }, + { + key: "LOGNAME", + want: u.Username, + }, + { + key: "HOME", + want: u.HomeDir, + }, + { + key: "SHELL", + want: shell, + }, + } + for _, tt := range tests { + t.Run(tt.key, func(t *testing.T) { + t.Parallel() + + session := setupSSHSession(t, agentsdk.Manifest{}, codersdk.ServiceBannerConfig{}, nil) + command := "sh -c 'echo $" + tt.key + "'" + if runtime.GOOS == "windows" { + command = "cmd.exe /c echo %" + tt.key + "%" + } + output, err := session.Output(command) + require.NoError(t, err) + require.Equal(t, tt.want, strings.TrimSpace(string(output))) + }) + } +} + func TestAgent_Metadata(t *testing.T) { t.Parallel() diff --git a/agent/agentssh/agentssh.go b/agent/agentssh/agentssh.go index 816bdf55556e9..7a1a6f0c7d41d 100644 --- a/agent/agentssh/agentssh.go +++ b/agent/agentssh/agentssh.go @@ -900,7 +900,10 @@ func (s *Server) CreateCommand(ctx context.Context, script string, env []string, cmd.Dir = homedir } cmd.Env = append(ei.Environ(), env...) + // Set login variables. cmd.Env = append(cmd.Env, fmt.Sprintf("USER=%s", username)) + cmd.Env = append(cmd.Env, fmt.Sprintf("LOGNAME=%s", username)) + cmd.Env = append(cmd.Env, fmt.Sprintf("SHELL=%s", shell)) // Set SSH connection environment variables (these are also set by OpenSSH // and thus expected to be present by SSH clients). Since the agent does From 83f44b6a04a27f1a148e99ff8a0bf0a81dca1176 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 11 Mar 2025 12:02:34 +0200 Subject: [PATCH 2/3] Update agent/agent_test.go --- agent/agent_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/agent/agent_test.go b/agent/agent_test.go index ef67a4a8b9f7a..73b31dd6efe72 100644 --- a/agent/agent_test.go +++ b/agent/agent_test.go @@ -1225,6 +1225,7 @@ func TestAgent_SSHConnectionLoginVars(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.key, func(t *testing.T) { t.Parallel() From 4d29e93940603fbfe638396f774c8e43667ced0d Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 11 Mar 2025 12:04:06 +0200 Subject: [PATCH 3/3] Update agent/agentssh/agentssh.go --- agent/agentssh/agentssh.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/agentssh/agentssh.go b/agent/agentssh/agentssh.go index 7a1a6f0c7d41d..c4aa53f4a550b 100644 --- a/agent/agentssh/agentssh.go +++ b/agent/agentssh/agentssh.go @@ -900,7 +900,7 @@ func (s *Server) CreateCommand(ctx context.Context, script string, env []string, cmd.Dir = homedir } cmd.Env = append(ei.Environ(), env...) - // Set login variables. + // Set login variables (see `man login`). cmd.Env = append(cmd.Env, fmt.Sprintf("USER=%s", username)) cmd.Env = append(cmd.Env, fmt.Sprintf("LOGNAME=%s", username)) cmd.Env = append(cmd.Env, fmt.Sprintf("SHELL=%s", shell))