Skip to content

Commit

Permalink
Refactor the control-master-mkdir behavior (see #173)
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Dec 3, 2016
1 parent 7b589da commit 348c30f
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 33 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ hosts:

* Automatically regenerates `~/.ssh/config` file when needed
* Inspect parent process to determine log level (if you use `ssh -vv`, **assh** will automatically run in debug mode)
* Automatically creates `ControlPath` directories so you can use *slashes* in your `ControlPath` option, can be disabled with the `NoControlMasterMkdir: true` configuration in host or globally.
* Automatically creates `ControlPath` directories so you can use *slashes* in your `ControlPath` option, can be enabled with the `ControlMasterMkdir: true` configuration in host or globally.

### Hooks

Expand Down Expand Up @@ -419,7 +419,7 @@ hosts:
Gateways: schoolgw
Inherits: schooltemplate
# do not automatically create `ControlPath` -> may result in error
NoControlMasterMkdir: true
ControlMasterMkdir: true

"*.shortcut1":
ResolveCommand: /bin/sh -c "echo %h | sed s/.shortcut1/.my-long-domain-name.com/"
Expand Down Expand Up @@ -689,6 +689,7 @@ With the wrapper, `ssh` will *always* be called with an updated `~/.ssh/config`

### master (unreleased)

* Remove the `NoControlMasterMkdir` option, and add the `ControlMasterMkdir` option instead ([#173](https://github.com/moul/advanced-ssh-config/issues/173))
* Accepting string or slices for list options ([#119](https://github.com/moul/advanced-ssh-config/issues/119))
* Add new `PubkeyAcceptedKeyTypes` OpenSSH 7+ field ([#175](https://github.com/moul/advanced-ssh-config/issues/175))
* Gracefully report an error when calling assh without configuration file ([#171](https://github.com/moul/advanced-ssh-config/issues/171))
Expand Down
2 changes: 0 additions & 2 deletions contrib/dummy-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ hosts:
- schoolgw
Inherits:
- schooltemplate
# do not automatically create `ControlPath` -> may result in error
NoControlMasterMkdir: true

"*.shortcut1":
ResolveCommand: /bin/sh -c "echo %h | sed s/.shortcut1/.my-long-domain-name.com/"
Expand Down
6 changes: 3 additions & 3 deletions pkg/commands/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ func computeHost(dest string, portOverride int, conf *config.Config) (*config.Ho
func prepareHostControlPath(host, gateway *config.Host) error {
controlPathDir := path.Dir(os.ExpandEnv(strings.Replace(host.ControlPath, "~", "$HOME", -1)))
gatewayControlPath := path.Join(controlPathDir, gateway.Name())
if config.BoolVal(host.NoControlMasterMkdir) {
return nil
if config.BoolVal(host.ControlMasterMkdir) {
return os.MkdirAll(gatewayControlPath, 0700)
}
return os.MkdirAll(gatewayControlPath, 0700)
return nil
}

func proxy(host *config.Host, conf *config.Config, dryRun bool) error {
Expand Down
26 changes: 13 additions & 13 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ hosts:
- aaa
- bbb
- aaa
NoControlMasterMkdir: true
ControlMasterMkdir: true
fff:
Inherits:
Expand Down Expand Up @@ -128,11 +128,11 @@ func dummyConfig() *Config {
HostName: "1.2.3.4",
}
config.Hosts["titi"] = &Host{
HostName: "tata",
Port: "23",
User: "moul",
ProxyCommand: "nc -v 4242",
NoControlMasterMkdir: "true",
HostName: "tata",
Port: "23",
User: "moul",
ProxyCommand: "nc -v 4242",
ControlMasterMkdir: "true",
}
config.Hosts["tonton"] = &Host{
ResolveNameservers: []string{"a.com", "1.2.3.4"},
Expand Down Expand Up @@ -302,7 +302,7 @@ func TestConfig(t *testing.T) {
So(config.Hosts["titi"].HostName, ShouldEqual, "tata")
So(config.Hosts["titi"].User, ShouldEqual, "moul")
So(config.Hosts["titi"].ProxyCommand, ShouldEqual, "nc -v 4242")
So(BoolVal(config.Hosts["titi"].NoControlMasterMkdir), ShouldBeTrue)
So(BoolVal(config.Hosts["titi"].ControlMasterMkdir), ShouldBeTrue)
So(config.Hosts["titi"].Port, ShouldEqual, "23")
So(config.Hosts["titi"].isDefault, ShouldEqual, false)

Expand Down Expand Up @@ -404,7 +404,7 @@ func TestConfig_JsonString(t *testing.T) {
"User": "moul",
"HostName": "tata",
"ProxyCommand": "nc -v 4242",
"NoControlMasterMkdir": "true"
"ControlMasterMkdir": "true"
},
"tonton": {
"ResolveNameservers": [
Expand Down Expand Up @@ -622,7 +622,7 @@ func TestConfig_JsonString(t *testing.T) {
"bbb",
"aaa"
],
"NoControlMasterMkdir": "true"
"ControlMasterMkdir": "true"
},
"fff": {
"Inherits": [
Expand Down Expand Up @@ -1243,7 +1243,7 @@ func TestConfig_GetHostSafe(t *testing.T) {
func TestConfig_String(t *testing.T) {
Convey("Testing Config.String", t, func() {
config := dummyConfig()
So(config.String(), ShouldEqual, `{"hosts":{"*.ddd":{"PasswordAuthentication":"yes","HostName":"1.3.5.7"},"empty":{},"nnn":{"Port":"26","Inherits":["mmm"]},"ooo1":{"Port":"23","Aliases":["ooo11","ooo12"]},"ooo2":{"Port":"24","Aliases":["ooo21","ooo22"]},"tata":{"Inherits":["tutu","titi","toto","tutu"]},"titi":{"Port":"23","User":"moul","HostName":"tata","ProxyCommand":"nc -v 4242","NoControlMasterMkdir":"true"},"tonton":{"ResolveNameservers":["a.com","1.2.3.4"]},"toto":{"HostName":"1.2.3.4"},"toto[1-5]toto":{"User":"toto1"},"toto[7-9]toto":{"User":"toto2"},"toutou":{"ResolveCommand":"dig -t %h"},"tutu":{"Inherits":["toto","tutu","*.ddd"],"Gateways":["titi","direct","1.2.3.4"]},"zzz":{"AddressFamily":"any","AskPassGUI":"yes","BatchMode":"no","CanonicalDomains":"42.am","CanonicalizeFallbackLocal":"no","CanonicalizeHostname":"yes","CanonicalizeMaxDots":"1","CanonicalizePermittedCNAMEs":"*.a.example.com:*.b.example.com:*.c.example.com","ChallengeResponseAuthentication":"yes","CheckHostIP":"yes","Cipher":"blowfish","Ciphers":["aes128-ctr,aes192-ctr","aes256-ctr"],"ClearAllForwardings":"yes","Compression":"yes","CompressionLevel":6,"ConnectionAttempts":"1","ConnectTimeout":10,"ControlMaster":"yes","ControlPath":"/tmp/%L-%l-%n-%p-%u-%r-%C-%h","ControlPersist":"yes","DynamicForward":["0.0.0.0:4242","0.0.0.0:4343"],"EnableSSHKeysign":"yes","EscapeChar":"~","ExitOnForwardFailure":"yes","FingerprintHash":"sha256","ForwardAgent":"yes","ForwardX11":"yes","ForwardX11Timeout":42,"ForwardX11Trusted":"yes","GatewayPorts":"yes","GlobalKnownHostsFile":["/etc/ssh/ssh_known_hosts","/tmp/ssh_known_hosts"],"GSSAPIAuthentication":"no","GSSAPIClientIdentity":"moul","GSSAPIDelegateCredentials":"no","GSSAPIKeyExchange":"no","GSSAPIRenewalForcesRekey":"no","GSSAPIServerIdentity":"gssapi.example.com","GSSAPITrustDns":"no","HashKnownHosts":"no","HostbasedAuthentication":"no","HostbasedKeyTypes":"*","HostKeyAlgorithms":"ecdsa-sha2-nistp256-cert-v01@openssh.com","HostKeyAlias":"z","IdentitiesOnly":"yes","IdentityFile":["~/.ssh/identity","~/.ssh/identity2"],"IgnoreUnknown":"testtest","IPQoS":["lowdelay","highdelay"],"KbdInteractiveAuthentication":"yes","KbdInteractiveDevices":["bsdauth","test"],"KexAlgorithms":["curve25519-sha256@libssh.org","test"],"KeychainIntegration":"yes","LocalCommand":"echo %h \u003e /tmp/logs","LocalForward":["0.0.0.0:1234","0.0.0.0:1235"],"LogLevel":"DEBUG3","MACs":["umac-64-etm@openssh.com,umac-128-etm@openssh.com","test"],"Match":"all","NoHostAuthenticationForLocalhost":"yes","NumberOfPasswordPrompts":"3","PasswordAuthentication":"yes","PermitLocalCommand":"yes","PKCS11Provider":"/a/b/c/pkcs11.so","Port":"22","PreferredAuthentications":"gssapi-with-mic,hostbased,publickey","Protocol":["2","3"],"ProxyUseFdpass":"no","PubkeyAuthentication":"yes","RekeyLimit":"default none","RemoteForward":["0.0.0.0:1234","0.0.0.0:1255"],"RequestTTY":"yes","RevokedHostKeys":"/a/revoked-keys","RhostsRSAAuthentication":"no","RSAAuthentication":"yes","SendEnv":["CUSTOM_*,TEST","TEST2"],"ServerAliveCountMax":3,"StreamLocalBindMask":"0177","StreamLocalBindUnlink":"no","StrictHostKeyChecking":"ask","TCPKeepAlive":"yes","Tunnel":"yes","TunnelDevice":"any:any","UpdateHostKeys":"ask","UsePrivilegedPort":"no","User":"moul","UserKnownHostsFile":["~/.ssh/known_hosts ~/.ssh/known_hosts2","/tmp/known_hosts"],"VerifyHostKeyDNS":"no","VisualHostKey":"yes","XAuthLocation":"xauth","HostName":"zzz.com","ProxyCommand":"nc %h %p"}},"templates":{"mmm":{"Port":"25","User":"mmmm","HostName":"5.5.5.5","Inherits":["tata"]}},"defaults":{"Port":"22","User":"root"},"asshknownhostfile":"~/.ssh/assh_known_hosts"}`)
So(config.String(), ShouldEqual, `{"hosts":{"*.ddd":{"PasswordAuthentication":"yes","HostName":"1.3.5.7"},"empty":{},"nnn":{"Port":"26","Inherits":["mmm"]},"ooo1":{"Port":"23","Aliases":["ooo11","ooo12"]},"ooo2":{"Port":"24","Aliases":["ooo21","ooo22"]},"tata":{"Inherits":["tutu","titi","toto","tutu"]},"titi":{"Port":"23","User":"moul","HostName":"tata","ProxyCommand":"nc -v 4242","ControlMasterMkdir":"true"},"tonton":{"ResolveNameservers":["a.com","1.2.3.4"]},"toto":{"HostName":"1.2.3.4"},"toto[1-5]toto":{"User":"toto1"},"toto[7-9]toto":{"User":"toto2"},"toutou":{"ResolveCommand":"dig -t %h"},"tutu":{"Inherits":["toto","tutu","*.ddd"],"Gateways":["titi","direct","1.2.3.4"]},"zzz":{"AddressFamily":"any","AskPassGUI":"yes","BatchMode":"no","CanonicalDomains":"42.am","CanonicalizeFallbackLocal":"no","CanonicalizeHostname":"yes","CanonicalizeMaxDots":"1","CanonicalizePermittedCNAMEs":"*.a.example.com:*.b.example.com:*.c.example.com","ChallengeResponseAuthentication":"yes","CheckHostIP":"yes","Cipher":"blowfish","Ciphers":["aes128-ctr,aes192-ctr","aes256-ctr"],"ClearAllForwardings":"yes","Compression":"yes","CompressionLevel":6,"ConnectionAttempts":"1","ConnectTimeout":10,"ControlMaster":"yes","ControlPath":"/tmp/%L-%l-%n-%p-%u-%r-%C-%h","ControlPersist":"yes","DynamicForward":["0.0.0.0:4242","0.0.0.0:4343"],"EnableSSHKeysign":"yes","EscapeChar":"~","ExitOnForwardFailure":"yes","FingerprintHash":"sha256","ForwardAgent":"yes","ForwardX11":"yes","ForwardX11Timeout":42,"ForwardX11Trusted":"yes","GatewayPorts":"yes","GlobalKnownHostsFile":["/etc/ssh/ssh_known_hosts","/tmp/ssh_known_hosts"],"GSSAPIAuthentication":"no","GSSAPIClientIdentity":"moul","GSSAPIDelegateCredentials":"no","GSSAPIKeyExchange":"no","GSSAPIRenewalForcesRekey":"no","GSSAPIServerIdentity":"gssapi.example.com","GSSAPITrustDns":"no","HashKnownHosts":"no","HostbasedAuthentication":"no","HostbasedKeyTypes":"*","HostKeyAlgorithms":"ecdsa-sha2-nistp256-cert-v01@openssh.com","HostKeyAlias":"z","IdentitiesOnly":"yes","IdentityFile":["~/.ssh/identity","~/.ssh/identity2"],"IgnoreUnknown":"testtest","IPQoS":["lowdelay","highdelay"],"KbdInteractiveAuthentication":"yes","KbdInteractiveDevices":["bsdauth","test"],"KexAlgorithms":["curve25519-sha256@libssh.org","test"],"KeychainIntegration":"yes","LocalCommand":"echo %h \u003e /tmp/logs","LocalForward":["0.0.0.0:1234","0.0.0.0:1235"],"LogLevel":"DEBUG3","MACs":["umac-64-etm@openssh.com,umac-128-etm@openssh.com","test"],"Match":"all","NoHostAuthenticationForLocalhost":"yes","NumberOfPasswordPrompts":"3","PasswordAuthentication":"yes","PermitLocalCommand":"yes","PKCS11Provider":"/a/b/c/pkcs11.so","Port":"22","PreferredAuthentications":"gssapi-with-mic,hostbased,publickey","Protocol":["2","3"],"ProxyUseFdpass":"no","PubkeyAuthentication":"yes","RekeyLimit":"default none","RemoteForward":["0.0.0.0:1234","0.0.0.0:1255"],"RequestTTY":"yes","RevokedHostKeys":"/a/revoked-keys","RhostsRSAAuthentication":"no","RSAAuthentication":"yes","SendEnv":["CUSTOM_*,TEST","TEST2"],"ServerAliveCountMax":3,"StreamLocalBindMask":"0177","StreamLocalBindUnlink":"no","StrictHostKeyChecking":"ask","TCPKeepAlive":"yes","Tunnel":"yes","TunnelDevice":"any:any","UpdateHostKeys":"ask","UsePrivilegedPort":"no","User":"moul","UserKnownHostsFile":["~/.ssh/known_hosts ~/.ssh/known_hosts2","/tmp/known_hosts"],"VerifyHostKeyDNS":"no","VisualHostKey":"yes","XAuthLocation":"xauth","HostName":"zzz.com","ProxyCommand":"nc %h %p"}},"templates":{"mmm":{"Port":"25","User":"mmmm","HostName":"5.5.5.5","Inherits":["tata"]}},"defaults":{"Port":"22","User":"root"},"asshknownhostfile":"~/.ssh/assh_known_hosts"}`)
})
}

Expand Down Expand Up @@ -1278,7 +1278,7 @@ Host nnn
User mmmm
# ProxyCommand nc -v 4242
# HostName: 5.5.5.5
# NoControlMasterMkdir: true
# ControlMasterMkdir: true
# Inherits: [mmm]
# Gateways: [titi, direct, 1.2.3.4]
Expand Down Expand Up @@ -1312,7 +1312,7 @@ Host tata
User moul
# ProxyCommand nc -v 4242
# HostName: 1.2.3.4
# NoControlMasterMkdir: true
# ControlMasterMkdir: true
# Inherits: [tutu, titi, toto, tutu]
# Gateways: [titi, direct, 1.2.3.4]
Expand All @@ -1321,7 +1321,7 @@ Host titi
User moul
# ProxyCommand nc -v 4242
# HostName: tata
# NoControlMasterMkdir: true
# ControlMasterMkdir: true
Host tonton
# ResolveNameservers: [a.com, 1.2.3.4]
Expand Down
26 changes: 13 additions & 13 deletions pkg/config/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ type Host struct {
ProxyCommand string `yaml:"proxycommand,omitempty,flow" json:"ProxyCommand,omitempty"`

// exposed assh fields
Inherits composeyaml.Stringorslice `yaml:"inherits,omitempty,flow" json:"Inherits,omitempty"`
Gateways composeyaml.Stringorslice `yaml:"gateways,omitempty,flow" json:"Gateways,omitempty"`
ResolveNameservers composeyaml.Stringorslice `yaml:"resolvenameservers,omitempty,flow" json:"ResolveNameservers,omitempty"`
ResolveCommand string `yaml:"resolvecommand,omitempty,flow" json:"ResolveCommand,omitempty"`
NoControlMasterMkdir string `yaml:"nocontrolmastermkdir,omitempty,flow" json:"NoControlMasterMkdir,omitempty"`
Aliases composeyaml.Stringorslice `yaml:"aliases,omitempty,flow" json:"Aliases,omitempty"`
Hooks *HostHooks `yaml:"hooks,omitempty,flow" json:"Hooks,omitempty"`
Inherits composeyaml.Stringorslice `yaml:"inherits,omitempty,flow" json:"Inherits,omitempty"`
Gateways composeyaml.Stringorslice `yaml:"gateways,omitempty,flow" json:"Gateways,omitempty"`
ResolveNameservers composeyaml.Stringorslice `yaml:"resolvenameservers,omitempty,flow" json:"ResolveNameservers,omitempty"`
ResolveCommand string `yaml:"resolvecommand,omitempty,flow" json:"ResolveCommand,omitempty"`
ControlMasterMkdir string `yaml:"controlmastermkdir,omitempty,flow" json:"ControlMasterMkdir,omitempty"`
Aliases composeyaml.Stringorslice `yaml:"aliases,omitempty,flow" json:"Aliases,omitempty"`
Hooks *HostHooks `yaml:"hooks,omitempty,flow" json:"Hooks,omitempty"`

// private assh fields
knownHosts []string
Expand Down Expand Up @@ -474,7 +474,7 @@ func (h *Host) Options() OptionsList {
//Gateways
//ResolveNameservers
//ResolveCommand
//NoControlMasterMkdir
//ControlMasterMkdir
//Aliases
//Hooks

Expand Down Expand Up @@ -970,10 +970,10 @@ func (h *Host) ApplyDefaults(defaults *Host) {
}
h.ResolveCommand = utils.ExpandField(h.ResolveCommand)

if h.NoControlMasterMkdir == "" {
h.NoControlMasterMkdir = defaults.NoControlMasterMkdir
if h.ControlMasterMkdir == "" {
h.ControlMasterMkdir = defaults.ControlMasterMkdir
}
h.NoControlMasterMkdir = utils.ExpandField(h.NoControlMasterMkdir)
h.ControlMasterMkdir = utils.ExpandField(h.ControlMasterMkdir)

if len(h.Gateways) == 0 {
h.Gateways = defaults.Gateways
Expand Down Expand Up @@ -1313,8 +1313,8 @@ func (h *Host) WriteSSHConfigTo(w io.Writer) error {
if h.HostName != "" {
fmt.Fprintf(w, " # HostName: %s\n", h.HostName)
}
if BoolVal(h.NoControlMasterMkdir) {
fmt.Fprintf(w, " # NoControlMasterMkdir: true\n")
if BoolVal(h.ControlMasterMkdir) {
fmt.Fprintf(w, " # ControlMasterMkdir: true\n")
}
if len(h.Inherits) > 0 {
fmt.Fprintf(w, " # Inherits: [%s]\n", strings.Join(h.Inherits, ", "))
Expand Down

0 comments on commit 348c30f

Please sign in to comment.