summaryrefslogtreecommitdiff
path: root/internal/command/receivepack
diff options
context:
space:
mode:
Diffstat (limited to 'internal/command/receivepack')
-rw-r--r--internal/command/receivepack/customaction.go88
-rw-r--r--internal/command/receivepack/customaction_test.go103
-rw-r--r--internal/command/receivepack/receivepack.go4
-rw-r--r--internal/command/receivepack/receivepack_test.go22
4 files changed, 21 insertions, 196 deletions
diff --git a/internal/command/receivepack/customaction.go b/internal/command/receivepack/customaction.go
deleted file mode 100644
index 6693d23..0000000
--- a/internal/command/receivepack/customaction.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package receivepack
-
-import (
- "bytes"
- "errors"
-
- "io"
- "io/ioutil"
- "net/http"
-
- "gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet"
- "gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/accessverifier"
-)
-
-type Request struct {
- SecretToken []byte `json:"secret_token"`
- Data accessverifier.CustomPayloadData `json:"data"`
- Output []byte `json:"output"`
-}
-
-type Response struct {
- Result []byte `json:"result"`
- Message string `json:"message"`
-}
-
-func (c *Command) processCustomAction(response *accessverifier.Response) error {
- data := response.Payload.Data
- apiEndpoints := data.ApiEndpoints
-
- if len(apiEndpoints) == 0 {
- return errors.New("Custom action error: Empty API endpoints")
- }
-
- return c.processApiEndpoints(response)
-}
-
-func (c *Command) processApiEndpoints(response *accessverifier.Response) error {
- client, err := gitlabnet.GetClient(c.Config)
-
- if err != nil {
- return err
- }
-
- data := response.Payload.Data
- request := &Request{Data: data}
- request.Data.UserId = response.Who
-
- for _, endpoint := range data.ApiEndpoints {
- response, err := c.performRequest(client, endpoint, request)
- if err != nil {
- return err
- }
-
- if err = c.displayResult(response.Result); err != nil {
- return err
- }
-
- // In the context of the git push sequence of events, it's necessary to read
- // stdin in order to capture output to pass onto subsequent commands
- output, err := ioutil.ReadAll(c.ReadWriter.In)
- if err != nil {
- return err
- }
- request.Output = output
- }
-
- return nil
-}
-
-func (c *Command) performRequest(client *gitlabnet.GitlabClient, endpoint string, request *Request) (*Response, error) {
- response, err := client.DoRequest(http.MethodPost, endpoint, request)
- if err != nil {
- return nil, err
- }
- defer response.Body.Close()
-
- cr := &Response{}
- if err := gitlabnet.ParseJSON(response, cr); err != nil {
- return nil, err
- }
-
- return cr, nil
-}
-
-func (c *Command) displayResult(result []byte) error {
- _, err := io.Copy(c.ReadWriter.Out, bytes.NewReader(result))
- return err
-}
diff --git a/internal/command/receivepack/customaction_test.go b/internal/command/receivepack/customaction_test.go
deleted file mode 100644
index c55a8f3..0000000
--- a/internal/command/receivepack/customaction_test.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package receivepack
-
-import (
- "bytes"
- "encoding/json"
- "io/ioutil"
- "net/http"
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "gitlab.com/gitlab-org/gitlab-shell/internal/command/commandargs"
- "gitlab.com/gitlab-org/gitlab-shell/internal/command/readwriter"
- "gitlab.com/gitlab-org/gitlab-shell/internal/config"
- "gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/accessverifier"
- "gitlab.com/gitlab-org/gitlab-shell/internal/gitlabnet/testserver"
-)
-
-func TestCustomReceivePack(t *testing.T) {
- repo := "group/repo"
- keyId := "1"
-
- requests := []testserver.TestRequestHandler{
- {
- Path: "/api/v4/internal/allowed",
- Handler: func(w http.ResponseWriter, r *http.Request) {
- b, err := ioutil.ReadAll(r.Body)
- require.NoError(t, err)
-
- var request *accessverifier.Request
- require.NoError(t, json.Unmarshal(b, &request))
-
- require.Equal(t, "1", request.KeyId)
-
- body := map[string]interface{}{
- "status": true,
- "gl_id": "1",
- "payload": map[string]interface{}{
- "action": "geo_proxy_to_primary",
- "data": map[string]interface{}{
- "api_endpoints": []string{"/geo/proxy_git_push_ssh/info_refs", "/geo/proxy_git_push_ssh/push"},
- "gl_username": "custom",
- "primary_repo": "https://repo/path",
- },
- },
- }
- w.WriteHeader(http.StatusMultipleChoices)
- require.NoError(t, json.NewEncoder(w).Encode(body))
- },
- },
- {
- Path: "/geo/proxy_git_push_ssh/info_refs",
- Handler: func(w http.ResponseWriter, r *http.Request) {
- b, err := ioutil.ReadAll(r.Body)
- require.NoError(t, err)
-
- var request *Request
- require.NoError(t, json.Unmarshal(b, &request))
-
- require.Equal(t, request.Data.UserId, "key-"+keyId)
- require.Empty(t, request.Output)
-
- err = json.NewEncoder(w).Encode(Response{Result: []byte("custom")})
- require.NoError(t, err)
- },
- },
- {
- Path: "/geo/proxy_git_push_ssh/push",
- Handler: func(w http.ResponseWriter, r *http.Request) {
- b, err := ioutil.ReadAll(r.Body)
- require.NoError(t, err)
-
- var request *Request
- require.NoError(t, json.Unmarshal(b, &request))
-
- require.Equal(t, request.Data.UserId, "key-"+keyId)
- require.Equal(t, "input", string(request.Output))
-
- err = json.NewEncoder(w).Encode(Response{Result: []byte("output")})
- require.NoError(t, err)
- },
- },
- }
-
- url, cleanup := testserver.StartSocketHttpServer(t, requests)
- defer cleanup()
-
- outBuf := &bytes.Buffer{}
- errBuf := &bytes.Buffer{}
- input := bytes.NewBufferString("input")
-
- cmd := &Command{
- Config: &config.Config{GitlabUrl: url},
- Args: &commandargs.Shell{GitlabKeyId: keyId, CommandType: commandargs.ReceivePack, SshArgs: []string{"git-receive-pack", repo}},
- ReadWriter: &readwriter.ReadWriter{ErrOut: errBuf, Out: outBuf, In: input},
- }
-
- require.NoError(t, cmd.Execute())
-
- // expect printing of info message, "custom" string from the first request
- // and "output" string from the second request
- require.Equal(t, "customoutput", outBuf.String())
-}
diff --git a/internal/command/receivepack/receivepack.go b/internal/command/receivepack/receivepack.go
index aaaf7b0..3af3941 100644
--- a/internal/command/receivepack/receivepack.go
+++ b/internal/command/receivepack/receivepack.go
@@ -4,6 +4,7 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/shared/accessverifier"
+ "gitlab.com/gitlab-org/gitlab-shell/internal/command/shared/customaction"
"gitlab.com/gitlab-org/gitlab-shell/internal/command/shared/disallowedcommand"
"gitlab.com/gitlab-org/gitlab-shell/internal/config"
)
@@ -27,7 +28,8 @@ func (c *Command) Execute() error {
}
if response.IsCustomAction() {
- return c.processCustomAction(response)
+ customAction := customaction.Command{c.Config, c.ReadWriter}
+ return customAction.Execute(response)
}
return c.performGitalyCall(response)
diff --git a/internal/command/receivepack/receivepack_test.go b/internal/command/receivepack/receivepack_test.go
index 1d7bd21..d464e35 100644
--- a/internal/command/receivepack/receivepack_test.go
+++ b/internal/command/receivepack/receivepack_test.go
@@ -15,18 +15,32 @@ import (
func TestForbiddenAccess(t *testing.T) {
requests := requesthandlers.BuildDisallowedByApiHandlers(t)
- url, cleanup := testserver.StartHttpServer(t, requests)
+ cmd, _, cleanup := setup(t, "disallowed", requests)
defer cleanup()
+ err := cmd.Execute()
+ require.Equal(t, "Disallowed by API call", err.Error())
+}
+
+func TestCustomReceivePack(t *testing.T) {
+ cmd, output, cleanup := setup(t, "1", requesthandlers.BuildAllowedWithCustomActionsHandlers(t))
+ defer cleanup()
+
+ require.NoError(t, cmd.Execute())
+ require.Equal(t, "customoutput", output.String())
+}
+
+func setup(t *testing.T, keyId string, requests []testserver.TestRequestHandler) (*Command, *bytes.Buffer, func()) {
+ url, cleanup := testserver.StartSocketHttpServer(t, requests)
+
output := &bytes.Buffer{}
input := bytes.NewBufferString("input")
cmd := &Command{
Config: &config.Config{GitlabUrl: url},
- Args: &commandargs.Shell{GitlabKeyId: "disallowed", SshArgs: []string{"git-receive-pack", "group/repo"}},
+ Args: &commandargs.Shell{GitlabKeyId: keyId, SshArgs: []string{"git-receive-pack", "group/repo"}},
ReadWriter: &readwriter.ReadWriter{ErrOut: output, Out: output, In: input},
}
- err := cmd.Execute()
- require.Equal(t, "Disallowed by API call", err.Error())
+ return cmd, output, cleanup
}