Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

check .ssh/config for host and port overrides; fixes #629 #687

Merged
merged 2 commits into from
Dec 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions plumbing/transport/ssh/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,26 @@ package ssh
import (
"fmt"
"reflect"
"strconv"

"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common"

"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 @@ -121,6 +131,10 @@ 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 {
Expand All @@ -130,6 +144,35 @@ func (c *command) getHostWithPort() string {
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

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
}
}

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

func (c *command) setAuthFromEndpoint() error {
var err error
c.auth, err = DefaultAuthBuilder(c.endpoint.User)
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("[email protected]: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("[email protected]: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("[email protected]: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]
}