diff --git a/cli/configssh.go b/cli/configssh.go index 65f36697d873f..e3e168d2b198c 100644 --- a/cli/configssh.go +++ b/cli/configssh.go @@ -440,6 +440,11 @@ func (r *RootCmd) configSSH() *serpent.Command { } if !bytes.Equal(configRaw, configModified) { + sshDir := filepath.Dir(sshConfigFile) + if err := os.MkdirAll(sshDir, 0700); 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..60c93b8e94f4b 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(0700), sshDirInfo.Mode().Perm(), "directory should have 0700 permissions") +} + func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) { t.Parallel() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy