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

Commit 8e282db

Browse files
committed
clients: default Auth methods
1 parent 9fbfd39 commit 8e282db

File tree

9 files changed

+115
-61
lines changed

9 files changed

+115
-61
lines changed

clients/common/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const GitUploadPackServiceName = "git-upload-pack"
2626

2727
type GitUploadPackService interface {
2828
Connect() error
29-
ConnectWithAuth(AuthMethod) error
29+
SetAuth(AuthMethod) error
3030
Info() (*GitUploadPackInfo, error)
3131
Fetch(*GitUploadPackRequest) (io.ReadCloser, error)
3232
Disconnect() error

clients/common_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (s *dummyProtocolService) Connect() error {
6464
return nil
6565
}
6666

67-
func (s *dummyProtocolService) ConnectWithAuth(auth common.AuthMethod) error {
67+
func (s *dummyProtocolService) SetAuth(auth common.AuthMethod) error {
6868
return nil
6969
}
7070

clients/http/common.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ import (
99
"gopkg.in/src-d/go-git.v4/core"
1010
)
1111

12+
// HTTPAuthMethod concrete implementation of common.AuthMethod for HTTP services
1213
type HTTPAuthMethod interface {
1314
common.AuthMethod
1415
setAuth(r *http.Request)
1516
}
1617

18+
// BasicAuth represent a HTTP basic auth
1719
type BasicAuth struct {
1820
username, password string
1921
}
2022

23+
// NewBasicAuth returns a BasicAuth base on the given user and password
2124
func NewBasicAuth(username, password string) *BasicAuth {
2225
return &BasicAuth{username, password}
2326
}
@@ -26,6 +29,7 @@ func (a *BasicAuth) setAuth(r *http.Request) {
2629
r.SetBasicAuth(a.username, a.password)
2730
}
2831

32+
// Name name of the auth
2933
func (a *BasicAuth) Name() string {
3034
return "http-basic-auth"
3135
}
@@ -39,10 +43,12 @@ func (a *BasicAuth) String() string {
3943
return fmt.Sprintf("%s - %s:%s", a.Name(), a.username, masked)
4044
}
4145

46+
// HTTPError a dedicated error to return errors bases on status codes
4247
type HTTPError struct {
4348
Response *http.Response
4449
}
4550

51+
// NewHTTPError returns a new HTTPError based on a http response
4652
func NewHTTPError(r *http.Response) error {
4753
if r.StatusCode >= 200 && r.StatusCode < 300 {
4854
return nil
@@ -59,6 +65,7 @@ func NewHTTPError(r *http.Response) error {
5965
return core.NewUnexpectedError(err)
6066
}
6167

68+
// StatusCode returns the status code of the response
6269
func (e *HTTPError) StatusCode() int {
6370
return e.Response.StatusCode
6471
}

clients/http/git_upload_pack.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,47 @@ import (
1212
"gopkg.in/src-d/go-git.v4/formats/pktline"
1313
)
1414

15+
// GitUploadPackService git-upoad-pack service over HTTP
1516
type GitUploadPackService struct {
1617
client *http.Client
1718
endpoint common.Endpoint
1819
auth HTTPAuthMethod
1920
}
2021

22+
// NewGitUploadPackService connects to a git-upload-pack service over HTTP, the
23+
// auth is extracted from the URL, or can be provided using the SetAuth method
2124
func NewGitUploadPackService(endpoint common.Endpoint) common.GitUploadPackService {
22-
return &GitUploadPackService{
25+
s := &GitUploadPackService{
2326
client: http.DefaultClient,
2427
endpoint: endpoint,
2528
}
29+
30+
s.setBasicAuthFromEndpoint()
31+
return s
2632
}
2733

34+
// Connect has not any effect, is here just for meet the interface
2835
func (s *GitUploadPackService) Connect() error {
2936
return nil
3037
}
3138

32-
func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error {
39+
func (s *GitUploadPackService) setBasicAuthFromEndpoint() {
40+
info := s.endpoint.User
41+
if info == nil {
42+
return
43+
}
44+
45+
p, ok := info.Password()
46+
if !ok {
47+
return
48+
}
49+
50+
u := info.Username()
51+
s.auth = NewBasicAuth(u, p)
52+
}
53+
54+
// SetAuth sets the AuthMethod
55+
func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
3356
httpAuth, ok := auth.(HTTPAuthMethod)
3457
if !ok {
3558
return common.ErrInvalidAuthMethod
@@ -39,6 +62,7 @@ func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error {
3962
return nil
4063
}
4164

65+
// Info returns the references info and capabilities from the service
4266
func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
4367
url := fmt.Sprintf(
4468
"%s/info/refs?service=%s",
@@ -56,6 +80,7 @@ func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
5680
return i, i.Decode(pktline.NewDecoder(res.Body))
5781
}
5882

83+
// Fetch request and returns a reader to a packfile
5984
func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
6085
url := fmt.Sprintf(
6186
"%s/%s",
@@ -98,6 +123,7 @@ func (s *GitUploadPackService) discardResponseInfo(r io.Reader) error {
98123

99124
return nil
100125
}
126+
101127
func (s *GitUploadPackService) doRequest(method, url string, content *strings.Reader) (*http.Response, error) {
102128
var body io.Reader
103129
if content != nil {
@@ -145,6 +171,7 @@ func (s *GitUploadPackService) applyAuthToRequest(req *http.Request) {
145171
s.auth.setAuth(req)
146172
}
147173

174+
// Disconnect do nothing
148175
func (s *GitUploadPackService) Disconnect() (err error) {
149176
return nil
150177
}

clients/http/git_upload_pack_test.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,40 @@ var _ = Suite(&RemoteSuite{})
1616

1717
func (s *RemoteSuite) SetUpSuite(c *C) {
1818
var err error
19-
s.Endpoint, err = common.NewEndpoint("https://github.com/tyba/git-fixture")
19+
s.Endpoint, err = common.NewEndpoint("https://github.com/git-fixtures/basic")
2020
c.Assert(err, IsNil)
2121
}
2222

23+
func (s *RemoteSuite) TestNewGitUploadPackServiceAuth(c *C) {
24+
e, err := common.NewEndpoint("https://foo:[email protected]/git-fixtures/basic")
25+
c.Assert(err, IsNil)
26+
27+
r := NewGitUploadPackService(e)
28+
auth := r.(*GitUploadPackService).auth
29+
30+
c.Assert(auth.String(), Equals, "http-basic-auth - foo:*******")
31+
}
32+
2333
func (s *RemoteSuite) TestConnect(c *C) {
2434
r := NewGitUploadPackService(s.Endpoint)
2535
c.Assert(r.Connect(), IsNil)
2636
}
2737

28-
func (s *RemoteSuite) TestConnectWithAuth(c *C) {
38+
func (s *RemoteSuite) TestSetAuth(c *C) {
2939
auth := &BasicAuth{}
3040
r := NewGitUploadPackService(s.Endpoint)
31-
c.Assert(r.ConnectWithAuth(auth), IsNil)
41+
r.SetAuth(auth)
42+
c.Assert(auth, Equals, r.(*GitUploadPackService).auth)
3243
}
3344

3445
type mockAuth struct{}
3546

3647
func (*mockAuth) Name() string { return "" }
3748
func (*mockAuth) String() string { return "" }
3849

39-
func (s *RemoteSuite) TestConnectWithAuthWrongType(c *C) {
50+
func (s *RemoteSuite) TestSetAuthWrongType(c *C) {
4051
r := NewGitUploadPackService(s.Endpoint)
41-
c.Assert(r.ConnectWithAuth(&mockAuth{}), Equals, common.ErrInvalidAuthMethod)
52+
c.Assert(r.SetAuth(&mockAuth{}), Equals, common.ErrInvalidAuthMethod)
4253
}
4354

4455
func (s *RemoteSuite) TestInfoEmpty(c *C) {

clients/ssh/auth_method.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,22 @@ func (a *PublicKeysCallback) clientConfig() *ssh.ClientConfig {
138138
}
139139
}
140140

141+
const DefaultSSHUsername = "git"
142+
141143
// Opens a pipe with the ssh agent and uses the pipe
142144
// as the implementer of the public key callback function.
143-
func NewSSHAgentAuth() (*PublicKeysCallback, error) {
145+
func NewSSHAgentAuth(user string) (*PublicKeysCallback, error) {
146+
if user == "" {
147+
user = DefaultSSHUsername
148+
}
149+
144150
pipe, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
145151
if err != nil {
146152
return nil, err
147153
}
148154

149155
return &PublicKeysCallback{
150-
User: "git",
156+
User: user,
151157
Callback: agent.NewClient(pipe).Signers,
152158
}, nil
153159
}

clients/ssh/git_upload_pack.go

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
// Package ssh implements a ssh client for go-git.
2-
//
3-
// The Connect() method is not allowed in ssh, use ConnectWithAuth() instead.
42
package ssh
53

64
import (
@@ -10,13 +8,12 @@ import (
108
"fmt"
119
"io"
1210
"io/ioutil"
13-
"net/url"
11+
"strings"
1412

1513
"gopkg.in/src-d/go-git.v4/clients/common"
1614
"gopkg.in/src-d/go-git.v4/formats/pktline"
1715

1816
"golang.org/x/crypto/ssh"
19-
"gopkg.in/sourcegraph/go-vcsurl.v1"
2017
)
2118

2219
// New errors introduced by this package.
@@ -32,79 +29,79 @@ var (
3229

3330
// GitUploadPackService holds the service information.
3431
// The zero value is safe to use.
35-
// TODO: remove NewGitUploadPackService().
3632
type GitUploadPackService struct {
3733
connected bool
3834
endpoint common.Endpoint
39-
vcs *vcsurl.RepoInfo
4035
client *ssh.Client
4136
auth AuthMethod
4237
}
4338

44-
// NewGitUploadPackService initialises a GitUploadPackService.
39+
// NewGitUploadPackService initialises a GitUploadPackService,
4540
func NewGitUploadPackService(endpoint common.Endpoint) common.GitUploadPackService {
4641
return &GitUploadPackService{endpoint: endpoint}
4742
}
4843

49-
// Connect cannot be used with SSH clients and always return
50-
// ErrAuthRequired. Use ConnectWithAuth instead.
44+
// Connect connects to the SSH server, unless a AuthMethod was set with SetAuth
45+
// method, by default uses an auth method based on PublicKeysCallback, it
46+
// connects to a SSH agent, using the address stored in the SSH_AUTH_SOCK
47+
// environment var
5148
func (s *GitUploadPackService) Connect() error {
52-
auth, err := NewSSHAgentAuth()
53-
if err != nil {
54-
return err
55-
}
56-
57-
return s.ConnectWithAuth(auth)
58-
}
59-
60-
// ConnectWithAuth connects to ep using SSH. Authentication is handled
61-
// by auth.
62-
func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) (err error) {
6349
if s.connected {
6450
return ErrAlreadyConnected
6551
}
6652

67-
s.vcs, err = vcsurl.Parse(s.endpoint.String())
68-
if err != nil {
53+
if err := s.setAuthFromEndpoint(); err != nil {
6954
return err
7055
}
7156

72-
url, err := vcsToURL(s.vcs)
57+
var err error
58+
s.client, err = ssh.Dial("tcp", s.getHostWithPort(), s.auth.clientConfig())
7359
if err != nil {
74-
return
60+
return err
7561
}
7662

77-
var ok bool
78-
s.auth, ok = auth.(AuthMethod)
79-
if !ok {
80-
return ErrInvalidAuthMethod
63+
s.connected = true
64+
return nil
65+
}
66+
67+
func (s *GitUploadPackService) getHostWithPort() string {
68+
host := s.endpoint.Host
69+
if strings.Index(s.endpoint.Host, ":") == -1 {
70+
host += ":22"
8171
}
8272

83-
s.client, err = ssh.Dial("tcp", url.Host, s.auth.clientConfig())
73+
return host
74+
}
75+
76+
func (s *GitUploadPackService) setAuthFromEndpoint() error {
77+
var u string
78+
if info := s.endpoint.User; info != nil {
79+
u = info.Username()
80+
}
81+
82+
var err error
83+
s.auth, err = NewSSHAgentAuth(u)
8484
if err != nil {
8585
return err
8686
}
8787

88-
s.connected = true
89-
return
88+
return nil
9089
}
9190

92-
func vcsToURL(vcs *vcsurl.RepoInfo) (u *url.URL, err error) {
93-
if vcs.VCS != vcsurl.Git {
94-
return nil, ErrUnsupportedVCS
95-
}
96-
if vcs.RepoHost != vcsurl.GitHub {
97-
return nil, ErrUnsupportedRepo
91+
// SetAuth sets the AuthMethod
92+
func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
93+
var ok bool
94+
s.auth, ok = auth.(AuthMethod)
95+
if !ok {
96+
return ErrInvalidAuthMethod
9897
}
99-
s := "ssh://git@" + string(vcs.RepoHost) + ":22/" + vcs.FullName
100-
u, err = url.Parse(s)
101-
return
98+
99+
return nil
102100
}
103101

104-
// Info returns the GitUploadPackInfo of the repository.
105-
// The client must be connected with the repository (using
106-
// the ConnectWithAuth() method) before using this
107-
// method.
102+
// Info returns the GitUploadPackInfo of the repository. The client must be
103+
// connected with the repository (using the ConnectWithAuth() method) before
104+
// using this method.
108105
func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
109106
if !s.connected {
110107
return nil, ErrNotConnected
@@ -120,7 +117,7 @@ func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
120117
_ = session.Close()
121118
}()
122119

123-
out, err := session.Output("git-upload-pack " + s.vcs.FullName + ".git")
120+
out, err := session.Output(s.getCommand())
124121
if err != nil {
125122
return nil, err
126123
}
@@ -169,7 +166,7 @@ func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (rc io.Read
169166
return nil, err
170167
}
171168

172-
if err := session.Start("git-upload-pack " + s.vcs.FullName + ".git"); err != nil {
169+
if err := session.Start(s.getCommand()); err != nil {
173170
return nil, err
174171
}
175172

@@ -209,3 +206,10 @@ func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (rc io.Read
209206
buf := bytes.NewBuffer(data)
210207
return ioutil.NopCloser(buf), nil
211208
}
209+
210+
func (s *GitUploadPackService) getCommand() string {
211+
directory := s.endpoint.Path
212+
directory = directory[1:len(directory)]
213+
214+
return fmt.Sprintf("git-upload-pack %s", directory)
215+
}

0 commit comments

Comments
 (0)