From 873e320b5f0d4885924eac61d6dbdda9fd0f4a92 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 7 May 2025 21:02:17 +0000 Subject: [PATCH 1/6] fix: create ssh conf directory if it doesn't exist --- cli/configssh.go | 6 ++++++ cli/configssh_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/cli/configssh.go b/cli/configssh.go index 65f36697d873f..535c63d1ad244 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -440,6 +440,12 @@ func (r *RootCmd) configSSH() *serpent.Command { } if !bytes.Equal(configRaw, configModified) { + // Ensure the parent directory exists before writing the file + sshDir := filepath.Dir(sshConfigFile) + if err := os.MkdirAll(sshDir, os.ModePerm); err != nil { + return xerrors.Errorf("failed to create directory %q: %w", sshDir, err) + } + err = atomic.WriteFile(sshConfigFile, bytes.NewReader(configModified)) if err != nil { return xerrors.Errorf("write ssh config failed: %w", err) diff --git a/cli/configssh_test.go b/cli/configssh_test.go index 72faaa00c1ca0..c75dcc3c61799 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -169,6 +169,47 @@ func TestConfigSSH(t *testing.T) { <-copyDone } +func TestConfigSSH_MissingDirectory(t *testing.T) { + t.Parallel() + + if runtime.GOOS == "windows" { + t.Skip("See coder/internal#117") + } + + client := coderdtest.New(t, nil) + _ = coderdtest.CreateFirstUser(t, client) + + // Create a temporary directory but don't create .ssh subdirectory + tmpdir := t.TempDir() + sshConfigPath := filepath.Join(tmpdir, ".ssh", "config") + + // Run config-ssh with a non-existent .ssh directory + args := []string{ + "config-ssh", + "--ssh-config-file", sshConfigPath, + "--yes", // Skip confirmation prompts + } + inv, root := clitest.New(t, args...) + clitest.SetupConfig(t, client, root) + + err := inv.Run() + require.NoError(t, err, "config-ssh should succeed with non-existent directory") + + // Verify that the .ssh directory was created + sshDir := filepath.Dir(sshConfigPath) + _, err = os.Stat(sshDir) + require.NoError(t, err, ".ssh directory should exist") + + // Verify that the config file was created + _, err = os.Stat(sshConfigPath) + require.NoError(t, err, "config file should exist") + + // Check that the directory has proper permissions (0700) + sshDirInfo, err := os.Stat(sshDir) + require.NoError(t, err) + require.Equal(t, os.FileMode(os.ModePerm), sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") +} + func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) { t.Parallel() From 0b3b85a50f932a2ce20dbf322a74c072b3efff72 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 7 May 2025 21:06:01 +0000 Subject: [PATCH 2/6] chore: remove comment --- cli/configssh.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/configssh.go b/cli/configssh.go index 535c63d1ad244..bf90754a15ef9 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -440,7 +440,6 @@ func (r *RootCmd) configSSH() *serpent.Command { } if !bytes.Equal(configRaw, configModified) { - // Ensure the parent directory exists before writing the file sshDir := filepath.Dir(sshConfigFile) if err := os.MkdirAll(sshDir, os.ModePerm); err != nil { return xerrors.Errorf("failed to create directory %q: %w", sshDir, err) From c7455b99fd76d81fd250bd26a4288b5ea5cd934a Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 7 May 2025 21:19:00 +0000 Subject: [PATCH 3/6] chore: lint --- cli/configssh_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/configssh_test.go b/cli/configssh_test.go index c75dcc3c61799..700fcdfd9e492 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -207,7 +207,7 @@ func TestConfigSSH_MissingDirectory(t *testing.T) { // Check that the directory has proper permissions (0700) sshDirInfo, err := os.Stat(sshDir) require.NoError(t, err) - require.Equal(t, os.FileMode(os.ModePerm), sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") + require.Equal(t, os.ModePerm, sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") } func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) { From 49e5e75d79fecc260e1b1a6e4c1e6ffeb53efff9 Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Wed, 7 May 2025 21:36:28 +0000 Subject: [PATCH 4/6] fix: properly check file perms --- cli/configssh.go | 2 +- cli/configssh_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/configssh.go b/cli/configssh.go index bf90754a15ef9..e3e168d2b198c 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -441,7 +441,7 @@ func (r *RootCmd) configSSH() *serpent.Command { if !bytes.Equal(configRaw, configModified) { sshDir := filepath.Dir(sshConfigFile) - if err := os.MkdirAll(sshDir, os.ModePerm); err != nil { + if err := os.MkdirAll(sshDir, 0700); err != nil { return xerrors.Errorf("failed to create directory %q: %w", sshDir, err) } diff --git a/cli/configssh_test.go b/cli/configssh_test.go index 700fcdfd9e492..60c93b8e94f4b 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -207,7 +207,7 @@ func TestConfigSSH_MissingDirectory(t *testing.T) { // Check that the directory has proper permissions (0700) sshDirInfo, err := os.Stat(sshDir) require.NoError(t, err) - require.Equal(t, os.ModePerm, sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") + require.Equal(t, os.FileMode(0700), sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") } func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) { From 0dfaade3d459968cfea21683b87699cdfa1f49db Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Thu, 8 May 2025 13:02:20 +0000 Subject: [PATCH 5/6] chore: allow test on windows --- cli/configssh_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cli/configssh_test.go b/cli/configssh_test.go index 60c93b8e94f4b..46fcff4afacf2 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -172,10 +172,6 @@ func TestConfigSSH(t *testing.T) { func TestConfigSSH_MissingDirectory(t *testing.T) { t.Parallel() - if runtime.GOOS == "windows" { - t.Skip("See coder/internal#117") - } - client := coderdtest.New(t, nil) _ = coderdtest.CreateFirstUser(t, client) From 7c320b44589baa5b201b214676168a801f067dfd Mon Sep 17 00:00:00 2001 From: Brett Kolodny Date: Thu, 8 May 2025 13:18:15 +0000 Subject: [PATCH 6/6] fix: skip test on windows --- cli/configssh_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cli/configssh_test.go b/cli/configssh_test.go index 46fcff4afacf2..60c93b8e94f4b 100644 --- a/cli/configssh_test.go +++ b/cli/configssh_test.go @@ -172,6 +172,10 @@ func TestConfigSSH(t *testing.T) { func TestConfigSSH_MissingDirectory(t *testing.T) { t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("See coder/internal#117") + } + client := coderdtest.New(t, nil) _ = coderdtest.CreateFirstUser(t, client)