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

transport: made public all the fields and standardized AuthMethod #649

Merged
merged 1 commit into from
Nov 21, 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
15 changes: 5 additions & 10 deletions plumbing/transport/http/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,25 +151,20 @@ func basicAuthFromEndpoint(ep *transport.Endpoint) *BasicAuth {
return nil
}

return NewBasicAuth(u, ep.Password)
return &BasicAuth{u, ep.Password}
}

// BasicAuth represent a HTTP basic auth
type BasicAuth struct {
username, password string
}

// NewBasicAuth returns a basicAuth base on the given user and password
func NewBasicAuth(username, password string) *BasicAuth {
return &BasicAuth{username, password}
Username, Password string
}

func (a *BasicAuth) setAuth(r *http.Request) {
if a == nil {
return
}

r.SetBasicAuth(a.username, a.password)
r.SetBasicAuth(a.Username, a.Password)
}

// Name is name of the auth
Expand All @@ -179,11 +174,11 @@ func (a *BasicAuth) Name() string {

func (a *BasicAuth) String() string {
masked := "*******"
if a.password == "" {
if a.Password == "" {
masked = "<empty>"
}

return fmt.Sprintf("%s - %s:%s", a.Name(), a.username, masked)
return fmt.Sprintf("%s - %s:%s", a.Name(), a.Username, masked)
}

// Err is a dedicated error to return errors based on status code
Expand Down
2 changes: 1 addition & 1 deletion plumbing/transport/http/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (s *UploadPackSuite) TestNewClient(c *C) {
}

func (s *ClientSuite) TestNewBasicAuth(c *C) {
a := NewBasicAuth("foo", "qux")
a := &BasicAuth{"foo", "qux"}

c.Assert(a.Name(), Equals, "http-basic-auth")
c.Assert(a.String(), Equals, "http-basic-auth - foo:*******")
Expand Down
82 changes: 48 additions & 34 deletions plumbing/transport/ssh/auth_method.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ const DefaultUsername = "git"
// configuration needed to establish an ssh connection.
type AuthMethod interface {
transport.AuthMethod
clientConfig() *ssh.ClientConfig
hostKeyCallback() (ssh.HostKeyCallback, error)
// ClientConfig should return a valid ssh.ClientConfig to be used to create
// a connection to the SSH server.
ClientConfig() (*ssh.ClientConfig, error)
}

// The names of the AuthMethod implementations. To be returned by the
Expand All @@ -45,7 +46,7 @@ const (
type KeyboardInteractive struct {
User string
Challenge ssh.KeyboardInteractiveChallenge
baseAuthMethod
HostKeyCallbackHelper
}

func (a *KeyboardInteractive) Name() string {
Expand All @@ -56,18 +57,20 @@ func (a *KeyboardInteractive) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}

func (a *KeyboardInteractive) clientConfig() *ssh.ClientConfig {
return &ssh.ClientConfig{
func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.KeyboardInteractiveChallenge(a.Challenge)},
}
Auth: []ssh.AuthMethod{
ssh.KeyboardInteractiveChallenge(a.Challenge),
},
})
}

// Password implements AuthMethod by using the given password.
type Password struct {
User string
Pass string
baseAuthMethod
User string
Password string
HostKeyCallbackHelper
}

func (a *Password) Name() string {
Expand All @@ -78,19 +81,19 @@ func (a *Password) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}

func (a *Password) clientConfig() *ssh.ClientConfig {
return &ssh.ClientConfig{
func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.Password(a.Pass)},
}
Auth: []ssh.AuthMethod{ssh.Password(a.Password)},
})
}

// PasswordCallback implements AuthMethod by using a callback
// to fetch the password.
type PasswordCallback struct {
User string
Callback func() (pass string, err error)
baseAuthMethod
HostKeyCallbackHelper
}

func (a *PasswordCallback) Name() string {
Expand All @@ -101,25 +104,25 @@ func (a *PasswordCallback) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}

func (a *PasswordCallback) clientConfig() *ssh.ClientConfig {
return &ssh.ClientConfig{
func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)},
}
})
}

// PublicKeys implements AuthMethod by using the given key pairs.
type PublicKeys struct {
User string
Signer ssh.Signer
baseAuthMethod
HostKeyCallbackHelper
}

// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An
// encryption password should be given if the pemBytes contains a password
// encrypted PEM block otherwise password should be empty. It supports RSA
// (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
func NewPublicKeys(user string, pemBytes []byte, password string) (AuthMethod, error) {
func NewPublicKeys(user string, pemBytes []byte, password string) (*PublicKeys, error) {
block, _ := pem.Decode(pemBytes)
if x509.IsEncryptedPEMBlock(block) {
key, err := x509.DecryptPEMBlock(block, []byte(password))
Expand All @@ -142,7 +145,7 @@ func NewPublicKeys(user string, pemBytes []byte, password string) (AuthMethod, e
// NewPublicKeysFromFile returns a PublicKeys from a file containing a PEM
// encoded private key. An encryption password should be given if the pemBytes
// contains a password encrypted PEM block otherwise password should be empty.
func NewPublicKeysFromFile(user, pemFile, password string) (AuthMethod, error) {
func NewPublicKeysFromFile(user, pemFile, password string) (*PublicKeys, error) {
bytes, err := ioutil.ReadFile(pemFile)
if err != nil {
return nil, err
Expand All @@ -159,11 +162,11 @@ func (a *PublicKeys) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}

func (a *PublicKeys) clientConfig() *ssh.ClientConfig {
return &ssh.ClientConfig{
func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)},
}
})
}

func username() (string, error) {
Expand All @@ -173,9 +176,11 @@ func username() (string, error) {
} else {
username = os.Getenv("USER")
}

if username == "" {
return "", errors.New("failed to get username")
}

return username, nil
}

Expand All @@ -184,13 +189,13 @@ func username() (string, error) {
type PublicKeysCallback struct {
User string
Callback func() (signers []ssh.Signer, err error)
baseAuthMethod
HostKeyCallbackHelper
}

// 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(u string) (AuthMethod, error) {
func NewSSHAgentAuth(u string) (*PublicKeysCallback, error) {
var err error
if u == "" {
u, err = username()
Expand Down Expand Up @@ -218,11 +223,11 @@ 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{
func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
}
})
}

// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a
Expand Down Expand Up @@ -287,17 +292,26 @@ func filterKnownHostsFiles(files ...string) ([]string, error) {
return out, nil
}

type baseAuthMethod struct {
// HostKeyCallbackHelper is a helper that provides common functionality to
// configure HostKeyCallback into a ssh.ClientConfig.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ssh.ClientConfig should be ssh.HostKeyCallback ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the field is called HostKeyCallback inside of the cfg

type HostKeyCallbackHelper struct {
// HostKeyCallback is the function type used for verifying server keys.
// If nil default callback will be create using NewKnownHostsHostKeyCallback
// If nil default callback will be create using NewKnownHostsCallback
// without argument.
HostKeyCallback ssh.HostKeyCallback
}

func (m *baseAuthMethod) hostKeyCallback() (ssh.HostKeyCallback, error) {
// SetHostKeyCallback sets the field HostKeyCallback in the given cfg. If
// HostKeyCallback is empty a default callback is created using
// NewKnownHostsCallback.
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
var err error
if m.HostKeyCallback == nil {
return NewKnownHostsCallback()
if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil {
return cfg, err
}
}

return m.HostKeyCallback, nil
cfg.HostKeyCallback = m.HostKeyCallback
return cfg, nil
}
8 changes: 4 additions & 4 deletions plumbing/transport/ssh/auth_method_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ func (s *SuiteCommon) TestKeyboardInteractiveString(c *C) {

func (s *SuiteCommon) TestPasswordName(c *C) {
a := &Password{
User: "test",
Pass: "",
User: "test",
Password: "",
}
c.Assert(a.Name(), Equals, PasswordName)
}

func (s *SuiteCommon) TestPasswordString(c *C) {
a := &Password{
User: "test",
Pass: "",
User: "test",
Password: "",
}
c.Assert(a.String(), Equals, fmt.Sprintf("user: test, name: %s", PasswordName))
}
Expand Down
7 changes: 1 addition & 6 deletions plumbing/transport/ssh/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ func (c *command) connect() error {
}

var err error
config := c.auth.clientConfig()
config.HostKeyCallback, err = c.auth.hostKeyCallback()
config, err := c.auth.ClientConfig()
if err != nil {
return err
}
Expand Down Expand Up @@ -159,7 +158,3 @@ func overrideConfig(overrides *ssh.ClientConfig, c *ssh.ClientConfig) {

*c = vc.Interface().(ssh.ClientConfig)
}

func isZeroValue(v reflect.Value) bool {
return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
}