Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3073db4

Browse files
committed
feat: modifies config-ssh to check for Coder Connect
1 parent169ab02 commit3073db4

File tree

2 files changed

+169
-133
lines changed

2 files changed

+169
-133
lines changed

‎cli/configssh.go

Lines changed: 155 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import (
2222
"golang.org/x/exp/constraints"
2323
"golang.org/x/xerrors"
2424

25+
"github.com/coder/serpent"
26+
2527
"github.com/coder/coder/v2/cli/cliui"
2628
"github.com/coder/coder/v2/codersdk"
27-
"github.com/coder/serpent"
2829
)
2930

3031
const (
@@ -47,13 +48,17 @@ const (
4748
typesshConfigOptionsstruct {
4849
waitEnumstring
4950
// Deprecated: moving away from prefix to hostnameSuffix
50-
userHostPrefixstring
51-
hostnameSuffixstring
52-
sshOptions []string
53-
disableAutostartbool
54-
header []string
55-
headerCommandstring
56-
removedKeysmap[string]bool
51+
userHostPrefixstring
52+
hostnameSuffixstring
53+
sshOptions []string
54+
disableAutostartbool
55+
header []string
56+
headerCommandstring
57+
removedKeysmap[string]bool
58+
globalConfigPathstring
59+
coderBinaryPathstring
60+
skipProxyCommandbool
61+
forceUnixSeparatorsbool
5762
}
5863

5964
// addOptions expects options in the form of "option=value" or "option value".
@@ -106,6 +111,78 @@ func (o sshConfigOptions) equal(other sshConfigOptions) bool {
106111
o.hostnameSuffix==other.hostnameSuffix
107112
}
108113

114+
func (osshConfigOptions)writeToBuffer(buf*bytes.Buffer)error {
115+
escapedCoderBinary,err:=sshConfigExecEscape(o.coderBinaryPath,o.forceUnixSeparators)
116+
iferr!=nil {
117+
returnxerrors.Errorf("escape coder binary for ssh failed: %w",err)
118+
}
119+
120+
escapedGlobalConfig,err:=sshConfigExecEscape(o.globalConfigPath,o.forceUnixSeparators)
121+
iferr!=nil {
122+
returnxerrors.Errorf("escape global config for ssh failed: %w",err)
123+
}
124+
125+
rootFlags:=fmt.Sprintf("--global-config %s",escapedGlobalConfig)
126+
for_,h:=rangeo.header {
127+
rootFlags+=fmt.Sprintf(" --header %q",h)
128+
}
129+
ifo.headerCommand!="" {
130+
rootFlags+=fmt.Sprintf(" --header-command %q",o.headerCommand)
131+
}
132+
133+
flags:=""
134+
ifo.waitEnum!="auto" {
135+
flags+=" --wait="+o.waitEnum
136+
}
137+
ifo.disableAutostart {
138+
flags+=" --disable-autostart=true"
139+
}
140+
141+
// Prefix block:
142+
ifo.userHostPrefix!="" {
143+
_,_=buf.WriteString("Host")
144+
145+
_,_=buf.WriteString(" ")
146+
_,_=buf.WriteString(o.userHostPrefix)
147+
_,_=buf.WriteString("*\n")
148+
149+
for_,v:=rangeo.sshOptions {
150+
_,_=buf.WriteString("\t")
151+
_,_=buf.WriteString(v)
152+
_,_=buf.WriteString("\n")
153+
}
154+
if!o.skipProxyCommand&&o.userHostPrefix!="" {
155+
_,_=buf.WriteString("\t")
156+
_,_=buf.WriteString(fmt.Sprintf(
157+
"ProxyCommand %s %s ssh --stdio%s --ssh-host-prefix %s %%h",
158+
escapedCoderBinary,rootFlags,flags,o.userHostPrefix,
159+
))
160+
_,_=buf.WriteString("\n")
161+
}
162+
}
163+
164+
// Suffix block
165+
ifo.hostnameSuffix=="" {
166+
returnnil
167+
}
168+
_,_=buf.WriteString(fmt.Sprintf("\nMatch host *.%s !exec\"%s connect exists %%h\"\n",
169+
o.hostnameSuffix,escapedCoderBinary))
170+
for_,v:=rangeo.sshOptions {
171+
_,_=buf.WriteString("\t")
172+
_,_=buf.WriteString(v)
173+
_,_=buf.WriteString("\n")
174+
}
175+
if!o.skipProxyCommand {
176+
_,_=buf.WriteString("\t")
177+
_,_=buf.WriteString(fmt.Sprintf(
178+
"ProxyCommand %s %s ssh --stdio%s --hostname-suffix %s %%h",
179+
escapedCoderBinary,rootFlags,flags,o.hostnameSuffix,
180+
))
181+
_,_=buf.WriteString("\n")
182+
}
183+
returnnil
184+
}
185+
109186
// slicesSortedEqual compares two slices without side-effects or regard to order.
110187
funcslicesSortedEqual[S~[]E,E constraints.Ordered](a,bS)bool {
111188
iflen(a)!=len(b) {
@@ -146,13 +223,11 @@ func (o sshConfigOptions) asList() (list []string) {
146223

147224
func (r*RootCmd)configSSH()*serpent.Command {
148225
var (
149-
sshConfigFilestring
150-
sshConfigOptssshConfigOptions
151-
usePreviousOptsbool
152-
dryRunbool
153-
skipProxyCommandbool
154-
forceUnixSeparatorsbool
155-
coderCliPathstring
226+
sshConfigFilestring
227+
sshConfigOptssshConfigOptions
228+
usePreviousOptsbool
229+
dryRunbool
230+
coderCliPathstring
156231
)
157232
client:=new(codersdk.Client)
158233
cmd:=&serpent.Command{
@@ -176,7 +251,7 @@ func (r *RootCmd) configSSH() *serpent.Command {
176251
Handler:func(inv*serpent.Invocation)error {
177252
ctx:=inv.Context()
178253

179-
ifsshConfigOpts.waitEnum!="auto"&&skipProxyCommand {
254+
ifsshConfigOpts.waitEnum!="auto"&&sshConfigOpts.skipProxyCommand {
180255
// The wait option is applied to the ProxyCommand. If the user
181256
// specifies skip-proxy-command, then wait cannot be applied.
182257
returnxerrors.Errorf("cannot specify both --skip-proxy-command and --wait")
@@ -206,18 +281,7 @@ func (r *RootCmd) configSSH() *serpent.Command {
206281
returnerr
207282
}
208283
}
209-
210-
escapedCoderBinary,err:=sshConfigExecEscape(coderBinary,forceUnixSeparators)
211-
iferr!=nil {
212-
returnxerrors.Errorf("escape coder binary for ssh failed: %w",err)
213-
}
214-
215284
root:=r.createConfig()
216-
escapedGlobalConfig,err:=sshConfigExecEscape(string(root),forceUnixSeparators)
217-
iferr!=nil {
218-
returnxerrors.Errorf("escape global config for ssh failed: %w",err)
219-
}
220-
221285
homedir,err:=os.UserHomeDir()
222286
iferr!=nil {
223287
returnxerrors.Errorf("user home dir failed: %w",err)
@@ -319,94 +383,15 @@ func (r *RootCmd) configSSH() *serpent.Command {
319383
coderdConfig.HostnamePrefix="coder."
320384
}
321385

322-
ifsshConfigOpts.userHostPrefix!="" {
323-
// Override with user flag.
324-
coderdConfig.HostnamePrefix=sshConfigOpts.userHostPrefix
325-
}
326-
ifsshConfigOpts.hostnameSuffix!="" {
327-
// Override with user flag.
328-
coderdConfig.HostnameSuffix=sshConfigOpts.hostnameSuffix
329-
}
330-
331-
// Write agent configuration.
332-
defaultOptions:= []string{
333-
"ConnectTimeout=0",
334-
"StrictHostKeyChecking=no",
335-
// Without this, the "REMOTE HOST IDENTITY CHANGED"
336-
// message will appear.
337-
"UserKnownHostsFile=/dev/null",
338-
// This disables the "Warning: Permanently added 'hostname' (RSA) to the list of known hosts."
339-
// message from appearing on every SSH. This happens because we ignore the known hosts.
340-
"LogLevel ERROR",
341-
}
342-
343-
if!skipProxyCommand {
344-
rootFlags:=fmt.Sprintf("--global-config %s",escapedGlobalConfig)
345-
for_,h:=rangesshConfigOpts.header {
346-
rootFlags+=fmt.Sprintf(" --header %q",h)
347-
}
348-
ifsshConfigOpts.headerCommand!="" {
349-
rootFlags+=fmt.Sprintf(" --header-command %q",sshConfigOpts.headerCommand)
350-
}
351-
352-
flags:=""
353-
ifsshConfigOpts.waitEnum!="auto" {
354-
flags+=" --wait="+sshConfigOpts.waitEnum
355-
}
356-
ifsshConfigOpts.disableAutostart {
357-
flags+=" --disable-autostart=true"
358-
}
359-
ifcoderdConfig.HostnamePrefix!="" {
360-
flags+=" --ssh-host-prefix "+coderdConfig.HostnamePrefix
361-
}
362-
ifcoderdConfig.HostnameSuffix!="" {
363-
flags+=" --hostname-suffix "+coderdConfig.HostnameSuffix
364-
}
365-
defaultOptions=append(defaultOptions,fmt.Sprintf(
366-
"ProxyCommand %s %s ssh --stdio%s %%h",
367-
escapedCoderBinary,rootFlags,flags,
368-
))
369-
}
370-
371-
// Create a copy of the options so we can modify them.
372-
configOptions:=sshConfigOpts
373-
configOptions.sshOptions=nil
374-
375-
// User options first (SSH only uses the first
376-
// option unless it can be given multiple times)
377-
for_,opt:=rangesshConfigOpts.sshOptions {
378-
err:=configOptions.addOptions(opt)
379-
iferr!=nil {
380-
returnxerrors.Errorf("add flag config option %q: %w",opt,err)
381-
}
382-
}
383-
384-
// Deployment options second, allow them to
385-
// override standard options.
386-
fork,v:=rangecoderdConfig.SSHConfigOptions {
387-
opt:=fmt.Sprintf("%s %s",k,v)
388-
err:=configOptions.addOptions(opt)
389-
iferr!=nil {
390-
returnxerrors.Errorf("add coderd config option %q: %w",opt,err)
391-
}
392-
}
393-
394-
// Finally, add the standard options.
395-
iferr:=configOptions.addOptions(defaultOptions...);err!=nil {
386+
configOptions,err:=mergeSSHOptions(sshConfigOpts,coderdConfig,string(root),coderBinary)
387+
iferr!=nil {
396388
returnerr
397389
}
398-
399-
hostBlock:= []string{
400-
sshConfigHostLinePatterns(coderdConfig),
401-
}
402-
// Prefix with '\t'
403-
for_,v:=rangeconfigOptions.sshOptions {
404-
hostBlock=append(hostBlock,"\t"+v)
390+
err=configOptions.writeToBuffer(buf)
391+
iferr!=nil {
392+
returnerr
405393
}
406394

407-
_,_=buf.WriteString(strings.Join(hostBlock,"\n"))
408-
_=buf.WriteByte('\n')
409-
410395
sshConfigWriteSectionEnd(buf)
411396

412397
// Write the remainder of the users config file to buf.
@@ -522,7 +507,7 @@ func (r *RootCmd) configSSH() *serpent.Command {
522507
Flag:"skip-proxy-command",
523508
Env:"CODER_SSH_SKIP_PROXY_COMMAND",
524509
Description:"Specifies whether the ProxyCommand option should be skipped. Useful for testing.",
525-
Value:serpent.BoolOf(&skipProxyCommand),
510+
Value:serpent.BoolOf(&sshConfigOpts.skipProxyCommand),
526511
Hidden:true,
527512
},
528513
{
@@ -563,7 +548,7 @@ func (r *RootCmd) configSSH() *serpent.Command {
563548
Description:"By default, 'config-ssh' uses the os path separator when writing the ssh config. "+
564549
"This might be an issue in Windows machine that use a unix-like shell. "+
565550
"This flag forces the use of unix file paths (the forward slash '/').",
566-
Value:serpent.BoolOf(&forceUnixSeparators),
551+
Value:serpent.BoolOf(&sshConfigOpts.forceUnixSeparators),
567552
// On non-windows showing this command is useless because it is a noop.
568553
// Hide vs disable it though so if a command is copied from a Windows
569554
// machine to a unix machine it will still work and not throw an
@@ -576,6 +561,63 @@ func (r *RootCmd) configSSH() *serpent.Command {
576561
returncmd
577562
}
578563

564+
funcmergeSSHOptions(
565+
usersshConfigOptions,coderd codersdk.SSHConfigResponse,globalConfigPath,coderBinaryPathstring,
566+
) (
567+
sshConfigOptions,error,
568+
) {
569+
// Write agent configuration.
570+
defaultOptions:= []string{
571+
"ConnectTimeout=0",
572+
"StrictHostKeyChecking=no",
573+
// Without this, the "REMOTE HOST IDENTITY CHANGED"
574+
// message will appear.
575+
"UserKnownHostsFile=/dev/null",
576+
// This disables the "Warning: Permanently added 'hostname' (RSA) to the list of known hosts."
577+
// message from appearing on every SSH. This happens because we ignore the known hosts.
578+
"LogLevel ERROR",
579+
}
580+
581+
// Create a copy of the options so we can modify them.
582+
configOptions:=user
583+
configOptions.sshOptions=nil
584+
585+
configOptions.globalConfigPath=globalConfigPath
586+
configOptions.coderBinaryPath=coderBinaryPath
587+
// user config takes precedence
588+
ifuser.userHostPrefix=="" {
589+
configOptions.userHostPrefix=coderd.HostnamePrefix
590+
}
591+
ifuser.hostnameSuffix=="" {
592+
configOptions.hostnameSuffix=coderd.HostnameSuffix
593+
}
594+
595+
// User options first (SSH only uses the first
596+
// option unless it can be given multiple times)
597+
for_,opt:=rangeuser.sshOptions {
598+
err:=configOptions.addOptions(opt)
599+
iferr!=nil {
600+
returnsshConfigOptions{},xerrors.Errorf("add flag config option %q: %w",opt,err)
601+
}
602+
}
603+
604+
// Deployment options second, allow them to
605+
// override standard options.
606+
fork,v:=rangecoderd.SSHConfigOptions {
607+
opt:=fmt.Sprintf("%s %s",k,v)
608+
err:=configOptions.addOptions(opt)
609+
iferr!=nil {
610+
returnsshConfigOptions{},xerrors.Errorf("add coderd config option %q: %w",opt,err)
611+
}
612+
}
613+
614+
// Finally, add the standard options.
615+
iferr:=configOptions.addOptions(defaultOptions...);err!=nil {
616+
returnsshConfigOptions{},err
617+
}
618+
returnconfigOptions,nil
619+
}
620+
579621
//nolint:revive
580622
funcsshConfigWriteSectionHeader(w io.Writer,addNewlinebool,osshConfigOptions) {
581623
nl:="\n"
@@ -843,19 +885,3 @@ func diffBytes(name string, b1, b2 []byte, color bool) ([]byte, error) {
843885
}
844886
returnb,nil
845887
}
846-
847-
funcsshConfigHostLinePatterns(config codersdk.SSHConfigResponse)string {
848-
builder:= strings.Builder{}
849-
// by inspection, WriteString always returns nil error
850-
_,_=builder.WriteString("Host")
851-
ifconfig.HostnamePrefix!="" {
852-
_,_=builder.WriteString(" ")
853-
_,_=builder.WriteString(config.HostnamePrefix)
854-
_,_=builder.WriteString("*")
855-
}
856-
ifconfig.HostnameSuffix!="" {
857-
_,_=builder.WriteString(" *.")
858-
_,_=builder.WriteString(config.HostnameSuffix)
859-
}
860-
returnbuilder.String()
861-
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp