aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plumbing/transport/ssh/auth_method.go69
-rw-r--r--plumbing/transport/ssh/auth_method_test.go22
2 files changed, 68 insertions, 23 deletions
diff --git a/plumbing/transport/ssh/auth_method.go b/plumbing/transport/ssh/auth_method.go
index 82e3453..ad92ee1 100644
--- a/plumbing/transport/ssh/auth_method.go
+++ b/plumbing/transport/ssh/auth_method.go
@@ -3,6 +3,7 @@ package ssh
import (
"errors"
"fmt"
+ "io/ioutil"
"net"
"os"
"os/user"
@@ -13,6 +14,8 @@ import (
"golang.org/x/crypto/ssh/agent"
)
+const DefaultUsername = "git"
+
var ErrEmptySSHAgentAddr = errors.New("SSH_AUTH_SOCK env variable is required")
// AuthMethod is the interface all auth methods for the ssh client
@@ -102,14 +105,35 @@ func (a *PasswordCallback) clientConfig() *ssh.ClientConfig {
}
}
-// PublicKeys implements AuthMethod by using the given
-// key pairs.
+// PublicKeys implements AuthMethod by using the given key pairs.
type PublicKeys struct {
User string
Signer ssh.Signer
baseAuthMethod
}
+// NewPublicKeys returns a PublicKeys from a PEM encoded private key. It
+// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
+func NewPublicKeys(user string, pemBytes []byte) (AuthMethod, error) {
+ signer, err := ssh.ParsePrivateKey(pemBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ return &PublicKeys{User: user, Signer: signer}, nil
+}
+
+// NewPublicKeysFromFile returns a PublicKeys from a file containing a PEM
+// encoded private key.
+func NewPublicKeysFromFile(user string, pemFile string) (AuthMethod, error) {
+ bytes, err := ioutil.ReadFile(pemFile)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewPublicKeys(user, bytes)
+}
+
func (a *PublicKeys) Name() string {
return PublicKeysName
}
@@ -133,28 +157,12 @@ type PublicKeysCallback struct {
baseAuthMethod
}
-func (a *PublicKeysCallback) Name() string {
- return PublicKeysCallbackName
-}
-
-func (a *PublicKeysCallback) String() string {
- return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
-}
-
-func (a *PublicKeysCallback) clientConfig() *ssh.ClientConfig {
- return &ssh.ClientConfig{
- User: a.User,
- Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
- }
-}
-
-const DefaultSSHUsername = "git"
-
-// NewSSHAgentAuth opens a pipe with the SSH agent and uses the pipe
-// as the implementer of the public key callback function.
-func NewSSHAgentAuth(user string) (*PublicKeysCallback, error) {
+// NewSSHAgentAuth returns a PublicKeysCallback based on a SSH agent, it opens
+// a pipe with the SSH agent and uses the pipe as the implementer of the public
+// key callback function.
+func NewSSHAgentAuth(user string) (AuthMethod, error) {
if user == "" {
- user = DefaultSSHUsername
+ user = DefaultUsername
}
sshAgentAddr := os.Getenv("SSH_AUTH_SOCK")
@@ -173,6 +181,21 @@ func NewSSHAgentAuth(user string) (*PublicKeysCallback, error) {
}, nil
}
+func (a *PublicKeysCallback) Name() string {
+ return PublicKeysCallbackName
+}
+
+func (a *PublicKeysCallback) String() string {
+ return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
+}
+
+func (a *PublicKeysCallback) clientConfig() *ssh.ClientConfig {
+ return &ssh.ClientConfig{
+ User: a.User,
+ Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
+ }
+}
+
// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a
// know_hosts file. http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT
//
diff --git a/plumbing/transport/ssh/auth_method_test.go b/plumbing/transport/ssh/auth_method_test.go
index 412e721..43b34df 100644
--- a/plumbing/transport/ssh/auth_method_test.go
+++ b/plumbing/transport/ssh/auth_method_test.go
@@ -2,8 +2,11 @@ package ssh
import (
"fmt"
+ "io/ioutil"
"os"
+ "golang.org/x/crypto/ssh/testdata"
+
. "gopkg.in/check.v1"
)
@@ -104,3 +107,22 @@ func (s *SuiteCommon) TestNewSSHAgentAuth(c *C) {
c.Assert(k, IsNil)
c.Assert(err, Equals, ErrEmptySSHAgentAddr)
}
+
+func (*SuiteCommon) TestNewPublicKeys(c *C) {
+ auth, err := NewPublicKeys("foo", testdata.PEMBytes["rsa"])
+ c.Assert(err, IsNil)
+ c.Assert(auth, NotNil)
+}
+
+func (*SuiteCommon) TestNewPublicKeysFromFile(c *C) {
+ f, err := ioutil.TempFile("", "ssh-test")
+ c.Assert(err, IsNil)
+ _, err = f.Write(testdata.PEMBytes["rsa"])
+ c.Assert(err, IsNil)
+ c.Assert(f.Close(), IsNil)
+ defer os.RemoveAll(f.Name())
+
+ auth, err := NewPublicKeysFromFile("foo", f.Name())
+ c.Assert(err, IsNil)
+ c.Assert(auth, NotNil)
+}