diff options
author | Patrick Bajao <ebajao@gitlab.com> | 2019-07-17 20:41:39 +0800 |
---|---|---|
committer | Patrick Bajao <ebajao@gitlab.com> | 2019-07-18 09:59:07 +0800 |
commit | d809dedf526285619f675867e016dc320c209fd7 (patch) | |
tree | 640fd98385d513c23cb5cb7666b5a1379745bf23 | |
parent | 0c3a85b48bae26976221e9ddb363ff81c1f19cbf (diff) | |
download | gitlab-shell-d809dedf526285619f675867e016dc320c209fd7.tar.gz |
Add KeyLine stuct
This is responsible for creating the key line to be returned
by checkers.
6 files changed, 159 insertions, 43 deletions
diff --git a/go/internal/checker/authorizedkeys/authorized_keys.go b/go/internal/checker/authorizedkeys/authorized_keys.go index 769892e..0f392dd 100644 --- a/go/internal/checker/authorizedkeys/authorized_keys.go +++ b/go/internal/checker/authorizedkeys/authorized_keys.go @@ -3,8 +3,9 @@ package authorizedkeys import ( "errors" "fmt" - "path" + "strconv" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/checker/keyline" "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/authorizedkeys" @@ -28,35 +29,13 @@ func (c *Checker) Execute() error { if expectedUsername == actualUsername { if err := c.printKeyLine(key); err != nil { - return fmt.Errorf("Failed to print key line: %v", err) + return err } } return nil } -func (c *Checker) printKeyLine(key string) error { - client, err := authorizedkeys.NewClient(c.Config) - if err != nil { - return err - } - - response, err := client.GetByKey(key) - if err != nil { - fmt.Fprintln(c.ReadWriter.Out, fmt.Sprintf("# No key was found for %s", key)) - } else { - fmt.Fprintln(c.ReadWriter.Out, c.formatKeyLine(response.Id, response.Key)) - } - - return nil -} - -func (c *Checker) formatKeyLine(id int64, key string) string { - command := fmt.Sprintf("%s key-%d", path.Join(c.Config.RootDir, "bin", "gitlab-shell"), id) - - return fmt.Sprintf(`command="%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s`, command, key) -} - func (c *Checker) validateArguments() error { args := c.Args argsSize := len(args) @@ -79,3 +58,31 @@ func (c *Checker) validateArguments() error { return nil } + +func (c *Checker) printKeyLine(key string) error { + client, err := authorizedkeys.NewClient(c.Config) + if err != nil { + return err + } + + response, err := client.GetByKey(key) + if err != nil { + fmt.Fprintln(c.ReadWriter.Out, fmt.Sprintf("# No key was found for %s", key)) + } else { + keyLine := &keyline.KeyLine{ + Id: strconv.FormatInt(response.Id, 10), + Value: response.Key, + Prefix: "key", + RootDir: c.Config.RootDir, + } + + line, err := keyLine.ToString() + if err != nil { + return err + } + + fmt.Fprintln(c.ReadWriter.Out, line) + } + + return nil +} diff --git a/go/internal/checker/authorizedkeys/authorized_keys_test.go b/go/internal/checker/authorizedkeys/authorized_keys_test.go index e70e06e..4c21092 100644 --- a/go/internal/checker/authorizedkeys/authorized_keys_test.go +++ b/go/internal/checker/authorizedkeys/authorized_keys_test.go @@ -55,18 +55,18 @@ func TestExecute(t *testing.T) { expectedOutput: "command=\"/tmp/bin/gitlab-shell key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty public-key\n", }, { - desc: "When key doesn't match any existing key", - arguments: []string{"user", "user", "not-found"}, + desc: "When key doesn't match any existing key", + arguments: []string{"user", "user", "not-found"}, expectedOutput: "# No key was found for not-found\n", }, { - desc: "When the API returns an error", - arguments: []string{"user", "user", "broken-message"}, + desc: "When the API returns an error", + arguments: []string{"user", "user", "broken-message"}, expectedOutput: "# No key was found for broken-message\n", }, { - desc: "When the API fails", - arguments: []string{"user", "user", "broken"}, + desc: "When the API fails", + arguments: []string{"user", "user", "broken"}, expectedOutput: "# No key was found for broken\n", }, } diff --git a/go/internal/checker/authorizedprincipals/authorized_principals.go b/go/internal/checker/authorizedprincipals/authorized_principals.go index 029bedc..3cd3387 100644 --- a/go/internal/checker/authorizedprincipals/authorized_principals.go +++ b/go/internal/checker/authorizedprincipals/authorized_principals.go @@ -3,8 +3,8 @@ package authorizedprincipals import ( "errors" "fmt" - "path" + "gitlab.com/gitlab-org/gitlab-shell/go/internal/checker/keyline" "gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter" "gitlab.com/gitlab-org/gitlab-shell/go/internal/config" ) @@ -24,21 +24,13 @@ func (c *Checker) Execute() error { keyId := args[0] principals := args[1:] - c.printPrincipalLines(keyId, principals) + if err := c.printPrincipalLines(keyId, principals); err != nil { + return err + } return nil } -func (c *Checker) printPrincipalLines(keyId string, principals []string) { - command := fmt.Sprintf("%s username-%s", path.Join(c.Config.RootDir, "bin", "gitlab-shell"), keyId) - - for _, principal := range principals { - principalLine := fmt.Sprintf(`command="%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s`, command, principal) - - fmt.Fprintln(c.ReadWriter.Out, principalLine) - } -} - func (c *Checker) validateArguments() error { args := c.Args argsSize := len(args) @@ -62,3 +54,23 @@ func (c *Checker) validateArguments() error { return nil } + +func (c *Checker) printPrincipalLines(keyId string, principals []string) error { + for _, principal := range principals { + principalKeyLine := &keyline.KeyLine{ + Id: keyId, + Value: principal, + Prefix: "username", + RootDir: c.Config.RootDir, + } + + line, err := principalKeyLine.ToString() + if err != nil { + return err + } + + fmt.Fprintln(c.ReadWriter.Out, line) + } + + return nil +} diff --git a/go/internal/checker/authorizedprincipals/authorized_principals_test.go b/go/internal/checker/authorizedprincipals/authorized_principals_test.go index 269059a..1339bd5 100644 --- a/go/internal/checker/authorizedprincipals/authorized_principals_test.go +++ b/go/internal/checker/authorizedprincipals/authorized_principals_test.go @@ -22,7 +22,7 @@ func TestExecute(t *testing.T) { expectedOutput: "command=\"/tmp/bin/gitlab-shell username-key\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty principal\n", }, { - desc: "With mulitple principals", + desc: "With mulitple principals", arguments: []string{"key", "principal-1", "principal-2"}, expectedOutput: "command=\"/tmp/bin/gitlab-shell username-key\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty principal-1\ncommand=\"/tmp/bin/gitlab-shell username-key\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty principal-2\n", }, diff --git a/go/internal/checker/keyline/key_line.go b/go/internal/checker/keyline/key_line.go new file mode 100644 index 0000000..28280ae --- /dev/null +++ b/go/internal/checker/keyline/key_line.go @@ -0,0 +1,48 @@ +package keyline + +import ( + "errors" + "fmt" + "path" + "regexp" + "strings" +) + +type KeyLine struct { + Id string + Value string + Prefix string + RootDir string +} + +const ( + GitlabShellDir = "bin" + GitlabShellProgram = "gitlab-shell" +) + +func (k *KeyLine) ToString() (string, error) { + if err := k.validate(); err != nil { + return "", err + } + + command := fmt.Sprintf("%s %s-%s", path.Join(k.RootDir, GitlabShellDir, GitlabShellProgram), k.Prefix, k.Id) + + return fmt.Sprintf(`command="%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s`, command, k.Value), nil +} + +func (k *KeyLine) validate() error { + isMatched, err := regexp.MatchString(`\A[a-z0-9-]+\z`, k.Id) + if err != nil { + return err + } + + if !isMatched { + return errors.New(fmt.Sprintf("Invalid key_id: %s", k.Id)) + } + + if strings.Contains(k.Value, "\n") { + return errors.New(fmt.Sprintf("Invalid value: %s", k.Value)) + } + + return nil +} diff --git a/go/internal/checker/keyline/key_line_test.go b/go/internal/checker/keyline/key_line_test.go new file mode 100644 index 0000000..6c90c22 --- /dev/null +++ b/go/internal/checker/keyline/key_line_test.go @@ -0,0 +1,49 @@ +package keyline + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestToString(t *testing.T) { + keyLine := &KeyLine{ + Id: "1", + Value: "public-key", + Prefix: "key", + RootDir: "/tmp", + } + + result, err := keyLine.ToString() + + require.NoError(t, err) + require.Equal(t, `command="/tmp/bin/gitlab-shell key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty public-key`, result) +} + +func TestFailingToString(t *testing.T) { + testCases := []struct { + desc string + keyLine *KeyLine + expectedError string + }{ + { + desc: "When Id has non-alphanumeric and non-dash characters in it", + keyLine: &KeyLine{Id: "key\n1"}, + expectedError: "Invalid key_id: key\n1", + }, + { + desc: "When Value has newline in it", + keyLine: &KeyLine{Id: "key", Value: "public\nkey"}, + expectedError: "Invalid value: public\nkey", + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + result, err := tc.keyLine.ToString() + + require.Empty(t, result) + require.EqualError(t, err, tc.expectedError) + }) + } +} |