Skip to content

Commit

Permalink
plumbing: transport ssh, ssh_config implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Máximo Cuadros <mcuadros@gmail.com>
  • Loading branch information
mcuadros committed Dec 11, 2017
1 parent 479d38b commit 264d094
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 12 deletions.
52 changes: 40 additions & 12 deletions plumbing/transport/ssh/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,21 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common"

"golang.org/x/crypto/ssh"
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
)

// DefaultClient is the default SSH client.
var DefaultClient = NewClient(nil)

// DefaultSSHConfig is the reader used to access parameters stored in the
// system's ssh_config files. If nil all the ssh_config are ignored.
var DefaultSSHConfig sshConfig = ssh_config.DefaultUserSettings

type sshConfig interface {
Get(alias, key string) string
}

// NewClient creates a new SSH client with an optional *ssh.ClientConfig.
func NewClient(config *ssh.ClientConfig) transport.Transport {
return common.NewClient(&runner{config: config})
Expand Down Expand Up @@ -123,26 +131,46 @@ func (c *command) connect() error {
}

func (c *command) getHostWithPort() string {
if addr, found := c.doGetHostWithPortFromSSHConfig(); found {
return addr
}

host := c.endpoint.Host
port := c.endpoint.Port
if port <= 0 {
port = DefaultPort
}

configHost := ssh_config.Get(host, "Hostname")
if (configHost != "") {
host = configHost
return fmt.Sprintf("%s:%d", host, port)
}

func (c *command) doGetHostWithPortFromSSHConfig() (addr string, found bool) {
if DefaultSSHConfig == nil {
return
}

host := c.endpoint.Host
port := c.endpoint.Port
configPort := ssh_config.Get(host, "Port")
if (configPort != "") {
i, err := strconv.Atoi(configPort)
if err != nil {

configHost := DefaultSSHConfig.Get(c.endpoint.Host, "Hostname")
if configHost != "" {
host = configHost
found = true
}

if !found {
return
}

configPort := DefaultSSHConfig.Get(c.endpoint.Host, "Port")
if configPort != "" {
if i, err := strconv.Atoi(configPort); err == nil {
port = i
}
}
if port <= 0 {
port = DefaultPort
}

return fmt.Sprintf("%s:%d", host, port)
addr = fmt.Sprintf("%s:%d", host, port)
return
}

func (c *command) setAuthFromEndpoint() error {
Expand Down
67 changes: 67 additions & 0 deletions plumbing/transport/ssh/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package ssh
import (
"testing"

"github.com/kevinburke/ssh_config"

"golang.org/x/crypto/ssh"

. "gopkg.in/check.v1"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
)

func Test(t *testing.T) { TestingT(t) }
Expand Down Expand Up @@ -39,3 +42,67 @@ func (s *SuiteCommon) TestOverrideConfigKeep(c *C) {
overrideConfig(config, target)
c.Assert(target.User, Equals, "foo")
}

func (s *SuiteCommon) TestDefaultSSHConfig(c *C) {
defer func() {
DefaultSSHConfig = ssh_config.DefaultUserSettings
}()

DefaultSSHConfig = &mockSSHConfig{map[string]map[string]string{
"github.com": map[string]string{
"Hostname": "foo.local",
"Port": "42",
},
}}

ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
c.Assert(err, IsNil)

cmd := &command{endpoint: ep}
c.Assert(cmd.getHostWithPort(), Equals, "foo.local:42")
}

func (s *SuiteCommon) TestDefaultSSHConfigNil(c *C) {
defer func() {
DefaultSSHConfig = ssh_config.DefaultUserSettings
}()

DefaultSSHConfig = nil

ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
c.Assert(err, IsNil)

cmd := &command{endpoint: ep}
c.Assert(cmd.getHostWithPort(), Equals, "github.com:22")
}

func (s *SuiteCommon) TestDefaultSSHConfigWildcard(c *C) {
defer func() {
DefaultSSHConfig = ssh_config.DefaultUserSettings
}()

DefaultSSHConfig = &mockSSHConfig{Values: map[string]map[string]string{
"*": map[string]string{
"Port": "42",
},
}}

ep, err := transport.NewEndpoint("git@github.com:foo/bar.git")
c.Assert(err, IsNil)

cmd := &command{endpoint: ep}
c.Assert(cmd.getHostWithPort(), Equals, "github.com:22")
}

type mockSSHConfig struct {
Values map[string]map[string]string
}

func (c *mockSSHConfig) Get(alias, key string) string {
a, ok := c.Values[alias]
if !ok {
return c.Values["*"][key]
}

return a[key]
}

0 comments on commit 264d094

Please sign in to comment.