diff options
Diffstat (limited to 'go/internal')
-rw-r--r-- | go/internal/command/command.go | 3 | ||||
-rw-r--r-- | go/internal/command/command_test.go | 13 | ||||
-rw-r--r-- | go/internal/command/commandargs/command_args.go | 1 | ||||
-rw-r--r-- | go/internal/command/commandargs/command_args_test.go | 7 | ||||
-rw-r--r-- | go/internal/command/uploadarchive/gitalycall.go | 32 | ||||
-rw-r--r-- | go/internal/command/uploadarchive/gitalycall_test.go | 40 | ||||
-rw-r--r-- | go/internal/command/uploadarchive/uploadarchive.go | 36 | ||||
-rw-r--r-- | go/internal/command/uploadarchive/uploadarchive_test.go | 31 | ||||
-rw-r--r-- | go/internal/gitlabnet/testserver/gitalyserver.go | 8 |
9 files changed, 171 insertions, 0 deletions
diff --git a/go/internal/command/command.go b/go/internal/command/command.go index 8b02f16..7bc1994 100644 --- a/go/internal/command/command.go +++ b/go/internal/command/command.go @@ -7,6 +7,7 @@ import ( "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/receivepack" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/twofactorrecover" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadarchive" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadpack" "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" ) @@ -41,6 +42,8 @@ func buildCommand(args *commandargs.CommandArgs, config *config.Config, readWrit return &receivepack.Command{Config: config, Args: args, ReadWriter: readWriter} case commandargs.UploadPack: return &uploadpack.Command{Config: config, Args: args, ReadWriter: readWriter} + case commandargs.UploadArchive: + return &uploadarchive.Command{Config: config, Args: args, ReadWriter: readWriter} } return nil diff --git a/go/internal/command/command_test.go b/go/internal/command/command_test.go index 37db89f..cbdfc56 100644 --- a/go/internal/command/command_test.go +++ b/go/internal/command/command_test.go @@ -9,6 +9,7 @@ import ( "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/fallback" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/receivepack" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/twofactorrecover" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadarchive" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/uploadpack" "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" "gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper" @@ -82,6 +83,18 @@ func TestNew(t *testing.T) { expectedType: &uploadpack.Command{}, }, { + desc: "it returns a UploadArchive command if the feature is enabled", + config: &config.Config{ + GitlabUrl: "http+unix://gitlab.socket", + Migration: config.MigrationConfig{Enabled: true, Features: []string{"git-upload-archive"}}, + }, + environment: map[string]string{ + "SSH_CONNECTION": "1", + "SSH_ORIGINAL_COMMAND": "git-upload-archive", + }, + expectedType: &uploadarchive.Command{}, + }, + { desc: "it returns a Fallback command if the feature is unimplemented", config: &config.Config{ GitlabUrl: "http+unix://gitlab.socket", diff --git a/go/internal/command/commandargs/command_args.go b/go/internal/command/commandargs/command_args.go index 6789c5b..fd9d741 100644 --- a/go/internal/command/commandargs/command_args.go +++ b/go/internal/command/commandargs/command_args.go @@ -15,6 +15,7 @@ const ( TwoFactorRecover CommandType = "2fa_recovery_codes" ReceivePack CommandType = "git-receive-pack" UploadPack CommandType = "git-upload-pack" + UploadArchive CommandType = "git-upload-archive" ) var ( diff --git a/go/internal/command/commandargs/command_args_test.go b/go/internal/command/commandargs/command_args_test.go index c3c6ff2..7c360ad 100644 --- a/go/internal/command/commandargs/command_args_test.go +++ b/go/internal/command/commandargs/command_args_test.go @@ -83,6 +83,13 @@ func TestParseSuccess(t *testing.T) { "SSH_ORIGINAL_COMMAND": `git upload-pack "group/repo"`, }, expectedArgs: &CommandArgs{SshArgs: []string{"git-upload-pack", "group/repo"}, CommandType: UploadPack}, + }, { + desc: "It parses git-upload-archive command", + environment: map[string]string{ + "SSH_CONNECTION": "1", + "SSH_ORIGINAL_COMMAND": "git-upload-archive 'group/repo'", + }, + expectedArgs: &CommandArgs{SshArgs: []string{"git-upload-archive", "group/repo"}, CommandType: UploadArchive}, }, } diff --git a/go/internal/command/uploadarchive/gitalycall.go b/go/internal/command/uploadarchive/gitalycall.go new file mode 100644 index 0000000..c899588 --- /dev/null +++ b/go/internal/command/uploadarchive/gitalycall.go @@ -0,0 +1,32 @@ +package uploadarchive + +import ( + "context" + + "google.golang.org/grpc" + + pb "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" + "gitlab.com/gitlab-org/gitaly/client" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/accessverifier" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/handler" +) + +func (c *Command) performGitalyCall(response *accessverifier.Response) error { + gc := &handler.GitalyCommand{ + Config: c.Config, + ServiceName: string(commandargs.UploadArchive), + Address: response.Gitaly.Address, + Token: response.Gitaly.Token, + } + + request := &pb.SSHUploadArchiveRequest{Repository: &response.Gitaly.Repo} + + return gc.RunGitalyCommand(func(ctx context.Context, conn *grpc.ClientConn) (int32, error) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + rw := c.ReadWriter + return client.UploadArchive(ctx, conn, rw.In, rw.Out, rw.ErrOut, request) + }) +} diff --git a/go/internal/command/uploadarchive/gitalycall_test.go b/go/internal/command/uploadarchive/gitalycall_test.go new file mode 100644 index 0000000..78953a7 --- /dev/null +++ b/go/internal/command/uploadarchive/gitalycall_test.go @@ -0,0 +1,40 @@ +package uploadarchive + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/testserver" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper/requesthandlers" +) + +func TestUploadPack(t *testing.T) { + gitalyAddress, cleanup := testserver.StartGitalyServer(t) + defer cleanup() + + requests := requesthandlers.BuildAllowedWithGitalyHandlers(t, gitalyAddress) + url, cleanup := testserver.StartHttpServer(t, requests) + defer cleanup() + + output := &bytes.Buffer{} + input := &bytes.Buffer{} + + userId := "1" + repo := "group/repo" + + cmd := &Command{ + Config: &config.Config{GitlabUrl: url}, + Args: &commandargs.CommandArgs{GitlabKeyId: userId, CommandType: commandargs.UploadArchive, SshArgs: []string{"git-upload-archive", repo}}, + ReadWriter: &readwriter.ReadWriter{ErrOut: output, Out: output, In: input}, + } + + err := cmd.Execute() + require.NoError(t, err) + + require.Equal(t, "UploadArchive: "+repo, output.String()) +} diff --git a/go/internal/command/uploadarchive/uploadarchive.go b/go/internal/command/uploadarchive/uploadarchive.go new file mode 100644 index 0000000..93a52c0 --- /dev/null +++ b/go/internal/command/uploadarchive/uploadarchive.go @@ -0,0 +1,36 @@ +package uploadarchive + +import ( + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/shared/accessverifier" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/shared/disallowedcommand" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" +) + +type Command struct { + Config *config.Config + Args *commandargs.CommandArgs + ReadWriter *readwriter.ReadWriter +} + +func (c *Command) Execute() error { + args := c.Args.SshArgs + if len(args) != 2 { + return disallowedcommand.Error + } + + repo := args[1] + response, err := c.verifyAccess(repo) + if err != nil { + return err + } + + return c.performGitalyCall(response) +} + +func (c *Command) verifyAccess(repo string) (*accessverifier.Response, error) { + cmd := accessverifier.Command{c.Config, c.Args, c.ReadWriter} + + return cmd.Verify(c.Args.CommandType, repo) +} diff --git a/go/internal/command/uploadarchive/uploadarchive_test.go b/go/internal/command/uploadarchive/uploadarchive_test.go new file mode 100644 index 0000000..369bee7 --- /dev/null +++ b/go/internal/command/uploadarchive/uploadarchive_test.go @@ -0,0 +1,31 @@ +package uploadarchive + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/gitlabnet/testserver" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper/requesthandlers" +) + +func TestForbiddenAccess(t *testing.T) { + requests := requesthandlers.BuildDisallowedByApiHandlers(t) + url, cleanup := testserver.StartHttpServer(t, requests) + defer cleanup() + + output := &bytes.Buffer{} + + cmd := &Command{ + Config: &config.Config{GitlabUrl: url}, + Args: &commandargs.CommandArgs{GitlabKeyId: "disallowed", SshArgs: []string{"git-upload-archive", "group/repo"}}, + ReadWriter: &readwriter.ReadWriter{ErrOut: output, Out: output}, + } + + err := cmd.Execute() + require.Equal(t, "Disallowed by API call", err.Error()) +} diff --git a/go/internal/gitlabnet/testserver/gitalyserver.go b/go/internal/gitlabnet/testserver/gitalyserver.go index a31dfe2..35234c1 100644 --- a/go/internal/gitlabnet/testserver/gitalyserver.go +++ b/go/internal/gitlabnet/testserver/gitalyserver.go @@ -41,6 +41,14 @@ func (s *testGitalyServer) SSHUploadPack(stream pb.SSHService_SSHUploadPackServe } func (s *testGitalyServer) SSHUploadArchive(stream pb.SSHService_SSHUploadArchiveServer) error { + req, err := stream.Recv() + if err != nil { + return err + } + + response := []byte("UploadArchive: " + req.Repository.GlRepository) + stream.Send(&pb.SSHUploadArchiveResponse{Stdout: response}) + return nil } |