diff --git a/internal/command/uploadpack/git_workhorse_call.go b/internal/command/uploadpack/git_workhorse_call.go new file mode 100644 index 0000000000000000000000000000000000000000..fa8902f0a0ad143e5ea40a2f5bfcab1b3ab9d7a8 --- /dev/null +++ b/internal/command/uploadpack/git_workhorse_call.go @@ -0,0 +1,30 @@ +package uploadpack + +import ( + "context" + "io" + + "gitlab.com/gitlab-org/gitlab-shell/v14/internal/command/shared/accessverifier" + "gitlab.com/gitlab-org/gitlab-shell/v14/internal/gitlabnet/git" +) + +func (c *Command) performWorkhorseCall(ctx context.Context, response *accessverifier.Response) error { + client := &git.Client{ + URL: response.GitRpcUrl, + Headers: map[string]string{ + "Gitlab-Shell-Api-Request": response.GitRpcAuthHeader, + "Git-Protocol": c.Args.Env.GitProtocolVersion, + }, + } + + resp, err := client.SshUploadPack(ctx, io.NopCloser(c.ReadWriter.In)) + + if err != nil { + return err + } + defer resp.Body.Close() + + _, err = io.Copy(c.ReadWriter.Out, resp.Body) + + return err +} diff --git a/internal/command/uploadpack/uploadpack.go b/internal/command/uploadpack/uploadpack.go index 4ac80c481e14aeaa721aceef6d8ff7478999c5ae..6e973d820a470fab251116b999f8b2167c49fa99 100644 --- a/internal/command/uploadpack/uploadpack.go +++ b/internal/command/uploadpack/uploadpack.go @@ -65,6 +65,10 @@ func (c *Command) Execute(ctx context.Context) (context.Context, error) { return ctxWithLogData, customAction.Execute(ctx, response) } + if response.GitRpcUrl != "" { + return ctxWithLogData, c.performWorkhorseCall(ctx, response) + } + stats, err := c.performGitalyCall(ctx, response) if err != nil { return ctxWithLogData, err @@ -73,6 +77,7 @@ func (c *Command) Execute(ctx context.Context) (context.Context, error) { if response.NeedAudit { gitauditevent.Audit(ctx, c.Args.CommandType, c.Config, response, stats) } + return ctxWithLogData, nil } diff --git a/internal/gitlabnet/accessverifier/client.go b/internal/gitlabnet/accessverifier/client.go index 8ab5060a4a76096ee6f03274189c17b1dc08fd8f..b9843d68edcbd7cb95fb3583852809e5c1ba53fa 100644 --- a/internal/gitlabnet/accessverifier/client.go +++ b/internal/gitlabnet/accessverifier/client.go @@ -84,6 +84,9 @@ type Response struct { StatusCode int // NeedAudit indicates whether git event should be audited to rails. NeedAudit bool `json:"need_audit"` + // GitRpcUrl is the url to fetch Git SSH data via HTTP + GitRpcUrl string `json:"git_rpc_url"` + GitRpcAuthHeader string `json:"git_rpc_auth_header"` } // NewClient creates a new instance of Client diff --git a/internal/gitlabnet/git/client.go b/internal/gitlabnet/git/client.go index 35d6a740189534c13eefbf071f5702438ea56ad2..54c5a81e128aa6a4704813d512b408d840ce123f 100644 --- a/internal/gitlabnet/git/client.go +++ b/internal/gitlabnet/git/client.go @@ -56,6 +56,16 @@ func (c *Client) UploadPack(ctx context.Context, body io.Reader) (*http.Response return c.do(request) } +// SshUploadPack sends a SSH over HTTPS request to the server +func (c *Client) SshUploadPack(ctx context.Context, body io.Reader) (*http.Response, error) { + request, err := http.NewRequestWithContext(ctx, http.MethodPost, c.URL, body) + if err != nil { + return nil, err + } + + return c.do(request) +} + func (c *Client) do(request *http.Request) (*http.Response, error) { for k, v := range c.Headers { request.Header.Add(k, v)