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

Commit 3af8385

Browse files
authored
feat: Enable arbitrary SSH options passed via config-ssh (#410)
* feat: Add option to disable SSH connection cache * Refactor to enable arbitrary options * Generate docs * Add comment for duplicated values
1 parent edc273f commit 3af8385

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

docs/coder_config-ssh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ coder config-ssh [flags]
1515
```
1616
--filepath string override the default path of your ssh config file (default "~/.ssh/config")
1717
-h, --help help for config-ssh
18+
-o, --option strings additional options injected in the ssh config (ex. disable caching with "-o ControlPath=none")
1819
--remove remove the auto-generated Coder ssh config
1920
```
2021

internal/cmd/configssh.go

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,25 @@ const sshEndToken = "# ------------END-CODER-ENTERPRISE------------"
3333

3434
func configSSHCmd() *cobra.Command {
3535
var (
36-
configpath string
37-
remove = false
36+
configpath string
37+
remove = false
38+
additionalOptions []string
3839
)
3940

4041
cmd := &cobra.Command{
4142
Use: "config-ssh",
4243
Short: "Configure SSH to access Coder workspaces",
4344
Long: "Inject the proper OpenSSH configuration into your local SSH config file.",
44-
RunE: configSSH(&configpath, &remove),
45+
RunE: configSSH(&configpath, &remove, &additionalOptions),
4546
}
4647
cmd.Flags().StringVar(&configpath, "filepath", filepath.Join("~", ".ssh", "config"), "override the default path of your ssh config file")
48+
cmd.Flags().StringSliceVarP(&additionalOptions, "option", "o", []string{}, "additional options injected in the ssh config (ex. disable caching with \"-o ControlPath=none\")")
4749
cmd.Flags().BoolVar(&remove, "remove", false, "remove the auto-generated Coder ssh config")
4850

4951
return cmd
5052
}
5153

52-
func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []string) error {
54+
func configSSH(configpath *string, remove *bool, additionalOptions *[]string) func(cmd *cobra.Command, _ []string) error {
5355
return func(cmd *cobra.Command, _ []string) error {
5456
ctx := cmd.Context()
5557
usr, err := user.Current()
@@ -118,7 +120,7 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
118120
return xerrors.Errorf("Failed to get executable path: %w", err)
119121
}
120122

121-
newConfig := makeNewConfigs(binPath, workspacesWithProviders, privateKeyFilepath)
123+
newConfig := makeNewConfigs(binPath, workspacesWithProviders, privateKeyFilepath, *additionalOptions)
122124

123125
err = os.MkdirAll(filepath.Dir(*configpath), os.ModePerm)
124126
if err != nil {
@@ -226,7 +228,7 @@ func writeSSHKey(ctx context.Context, client coder.Client, privateKeyPath string
226228
return ioutil.WriteFile(privateKeyPath, []byte(key.PrivateKey), 0600)
227229
}
228230

229-
func makeNewConfigs(binPath string, workspaces []coderutil.WorkspaceWithWorkspaceProvider, privateKeyFilepath string) string {
231+
func makeNewConfigs(binPath string, workspaces []coderutil.WorkspaceWithWorkspaceProvider, privateKeyFilepath string, additionalOptions []string) string {
230232
newConfig := fmt.Sprintf("\n%s\n%s\n\n", sshStartToken, sshStartMessage)
231233

232234
sort.Slice(workspaces, func(i, j int) bool { return workspaces[i].Workspace.Name < workspaces[j].Workspace.Name })
@@ -240,32 +242,41 @@ func makeNewConfigs(binPath string, workspaces []coderutil.WorkspaceWithWorkspac
240242
continue
241243
}
242244

243-
newConfig += makeSSHConfig(binPath, workspace.Workspace.Name, privateKeyFilepath)
245+
newConfig += makeSSHConfig(binPath, workspace.Workspace.Name, privateKeyFilepath, additionalOptions)
244246
}
245247
newConfig += fmt.Sprintf("\n%s\n", sshEndToken)
246248

247249
return newConfig
248250
}
249251

250-
func makeSSHConfig(binPath, workspaceName, privateKeyFilepath string) string {
251-
entry := fmt.Sprintf(
252-
`Host coder.%s
253-
HostName coder.%s
254-
ProxyCommand "%s" tunnel %s 12213 stdio
255-
StrictHostKeyChecking no
256-
ConnectTimeout=0
257-
IdentitiesOnly yes
258-
IdentityFile="%s"
259-
`, workspaceName, workspaceName, binPath, workspaceName, privateKeyFilepath)
252+
func makeSSHConfig(binPath, workspaceName, privateKeyFilepath string, additionalOptions []string) string {
253+
// Custom user options come first to maximizessh customization.
254+
options := []string{}
255+
if len(additionalOptions) > 0 {
256+
options = []string{
257+
"# Custom options. Duplicated values will always prefer the first!",
258+
}
259+
options = append(options, additionalOptions...)
260+
options = append(options, "# End custom options.")
261+
}
262+
options = append(options,
263+
fmt.Sprintf("HostName coder.%s", workspaceName),
264+
fmt.Sprintf("ProxyCommand %q tunnel %s 12213 stdio", binPath, workspaceName),
265+
"StrictHostKeyChecking no",
266+
"ConnectTimeout=0",
267+
"IdentitiesOnly yes",
268+
fmt.Sprintf("IdentityFile=%q", privateKeyFilepath),
269+
)
260270

261271
if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
262-
entry += ` ControlMaster auto
263-
ControlPath ~/.ssh/.connection-%r@%h:%p
264-
ControlPersist 600
265-
`
272+
options = append(options,
273+
"ControlMaster auto",
274+
"ControlPath ~/.ssh/.connection-%r@%h:%p",
275+
"ControlPersist 600",
276+
)
266277
}
267278

268-
return entry
279+
return fmt.Sprintf("Host coder.%s\n\t%s\n\n", workspaceName, strings.Join(options, "\n\t"))
269280
}
270281

271282
func writeStr(filename, data string) error {

0 commit comments

Comments
 (0)
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