@@ -33,23 +33,25 @@ const sshEndToken = "# ------------END-CODER-ENTERPRISE------------"
3333
3434func 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
271282func writeStr (filename , data string ) error {
0 commit comments