@@ -33,23 +33,25 @@ const sshEndToken = "# ------------END-CODER-ENTERPRISE------------"
33
33
34
34
func configSSHCmd () * cobra.Command {
35
35
var (
36
- configpath string
37
- remove = false
36
+ configpath string
37
+ remove = false
38
+ additionalOptions []string
38
39
)
39
40
40
41
cmd := & cobra.Command {
41
42
Use : "config-ssh" ,
42
43
Short : "Configure SSH to access Coder workspaces" ,
43
44
Long : "Inject the proper OpenSSH configuration into your local SSH config file." ,
44
- RunE : configSSH (& configpath , & remove ),
45
+ RunE : configSSH (& configpath , & remove , & additionalOptions ),
45
46
}
46
47
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\" )" )
47
49
cmd .Flags ().BoolVar (& remove , "remove" , false , "remove the auto-generated Coder ssh config" )
48
50
49
51
return cmd
50
52
}
51
53
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 {
53
55
return func (cmd * cobra.Command , _ []string ) error {
54
56
ctx := cmd .Context ()
55
57
usr , err := user .Current ()
@@ -118,7 +120,7 @@ func configSSH(configpath *string, remove *bool) func(cmd *cobra.Command, _ []st
118
120
return xerrors .Errorf ("Failed to get executable path: %w" , err )
119
121
}
120
122
121
- newConfig := makeNewConfigs (binPath , workspacesWithProviders , privateKeyFilepath )
123
+ newConfig := makeNewConfigs (binPath , workspacesWithProviders , privateKeyFilepath , * additionalOptions )
122
124
123
125
err = os .MkdirAll (filepath .Dir (* configpath ), os .ModePerm )
124
126
if err != nil {
@@ -226,7 +228,7 @@ func writeSSHKey(ctx context.Context, client coder.Client, privateKeyPath string
226
228
return ioutil .WriteFile (privateKeyPath , []byte (key .PrivateKey ), 0600 )
227
229
}
228
230
229
- func makeNewConfigs (binPath string , workspaces []coderutil.WorkspaceWithWorkspaceProvider , privateKeyFilepath string ) string {
231
+ func makeNewConfigs (binPath string , workspaces []coderutil.WorkspaceWithWorkspaceProvider , privateKeyFilepath string , additionalOptions [] string ) string {
230
232
newConfig := fmt .Sprintf ("\n %s\n %s\n \n " , sshStartToken , sshStartMessage )
231
233
232
234
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
240
242
continue
241
243
}
242
244
243
- newConfig += makeSSHConfig (binPath , workspace .Workspace .Name , privateKeyFilepath )
245
+ newConfig += makeSSHConfig (binPath , workspace .Workspace .Name , privateKeyFilepath , additionalOptions )
244
246
}
245
247
newConfig += fmt .Sprintf ("\n %s\n " , sshEndToken )
246
248
247
249
return newConfig
248
250
}
249
251
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
+ )
260
270
261
271
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
+ )
266
277
}
267
278
268
- return entry
279
+ return fmt . Sprintf ( "Host coder.%s \n \t %s \n \n " , workspaceName , strings . Join ( options , " \n \t " ))
269
280
}
270
281
271
282
func writeStr (filename , data string ) error {
0 commit comments