As we reevaluate how to best support and maintain Staging Ref in the future, we encourage development teams using this environment to highlight their use cases in the following issue: https://gitlab.com/gitlab-com/gl-infra/software-delivery/framework/software-delivery-framework-issue-tracker/-/issues/36.

Skip to content
Snippets Groups Projects
Commit aab85f36 authored by Patrick Bajao's avatar Patrick Bajao
Browse files

Support falling back to ruby version of checkers

Rename the ruby scripts to have `-ruby` suffix and add a symlink
for both to `./gitlab-shell`. The executable name will be used to
determine how args will be parsed.

For now, we only parse the arguments for gitlab-shell commands. If
the executable is `gitlab-shell-authorized-keys-check` or
`gitlab-shell-authorized-principals-check`, it'll always fallback
to the ruby version.

Ruby specs test the ruby script, the fallback from go to ruby and
go implementation of both (still pending).
parent ed046037
No related branches found
No related tags found
No related merge requests found
Showing
with 333 additions and 245 deletions
Loading
Loading
@@ -16,8 +16,14 @@ test_ruby:
# bin/gitlab-shell must exist and needs to be the Ruby version for
# rspec to be able to test.
cp bin/gitlab-shell-ruby bin/gitlab-shell
# bin/gitlab-shell-authorized-keys-check and bin/gitlab-shell-authorized-principals-check
# should link to ruby scripts for rspec to be able to test.
ln -sf ./gitlab-shell-authorized-keys-check-ruby bin/gitlab-shell-authorized-keys-check
ln -sf ./gitlab-shell-authorized-principals-check-ruby bin/gitlab-shell-authorized-principals-check
bundle exec rspec --color --tag '~go' --format d spec
rm -f bin/gitlab-shell
ln -sf ./gitlab-shell bin/gitlab-shell-authorized-keys-check
ln -sf ./gitlab-shell bin/gitlab-shell-authorized-principals-check
test_golang:
support/go-test
Loading
Loading
#!/usr/bin/env ruby
#
# GitLab shell authorized_keys helper. Query GitLab API to get the authorized
# command for a given ssh key fingerprint
#
# Ex.
# bin/gitlab-shell-authorized-keys-check <username> <public-key>
#
# Returns
# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...
#
# Expects to be called by the SSH daemon, via configuration like:
# AuthorizedKeysCommandUser git
# AuthorizedKeysCommand /bin/gitlab-shell-authorized-keys-check git %u %k
abort "# Wrong number of arguments. #{ARGV.size}. Usage:
# gitlab-shell-authorized-keys-check <expected-username> <actual-username> <key>" unless ARGV.size == 3
expected_username = ARGV[0]
abort '# No username provided' if expected_username.nil? || expected_username == ''
actual_username = ARGV[1]
abort '# No username provided' if actual_username.nil? || actual_username == ''
# Only check access if the requested username matches the configured username.
# Normally, these would both be 'git', but it can be configured by the user
exit 0 unless expected_username == actual_username
key = ARGV[2]
abort "# No key provided" if key.nil? || key == ''
require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net'
require_relative '../lib/gitlab_keys'
authorized_key = GitlabNet.new.authorized_key(key)
if authorized_key.nil?
puts "# No key was found for #{key}"
else
puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key['key'])
end
./gitlab-shell
\ No newline at end of file
#!/usr/bin/env ruby
#
# GitLab shell authorized_keys helper. Query GitLab API to get the authorized
# command for a given ssh key fingerprint
#
# Ex.
# bin/gitlab-shell-authorized-keys-check <username> <public-key>
#
# Returns
# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...
#
# Expects to be called by the SSH daemon, via configuration like:
# AuthorizedKeysCommandUser git
# AuthorizedKeysCommand /bin/gitlab-shell-authorized-keys-check git %u %k
abort "# Wrong number of arguments. #{ARGV.size}. Usage:
# gitlab-shell-authorized-keys-check <expected-username> <actual-username> <key>" unless ARGV.size == 3
expected_username = ARGV[0]
abort '# No username provided' if expected_username.nil? || expected_username == ''
actual_username = ARGV[1]
abort '# No username provided' if actual_username.nil? || actual_username == ''
# Only check access if the requested username matches the configured username.
# Normally, these would both be 'git', but it can be configured by the user
exit 0 unless expected_username == actual_username
key = ARGV[2]
abort "# No key provided" if key.nil? || key == ''
require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net'
require_relative '../lib/gitlab_keys'
authorized_key = GitlabNet.new.authorized_key(key)
if authorized_key.nil?
puts "# No key was found for #{key}"
else
puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key['key'])
end
#!/usr/bin/env ruby
#
# GitLab shell authorized principals helper. Emits the same sort of
# command="..." line as gitlab-shell-authorized-principals-check, with
# the right options.
#
# Ex.
# bin/gitlab-shell-authorized-keys-check <key-id> <principal1> [<principal2>...]
#
# Returns one line per principal passed in, e.g.:
# command="/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL}
# [command="/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL2}]
#
# Expects to be called by the SSH daemon, via configuration like:
# AuthorizedPrincipalsCommandUser root
# AuthorizedPrincipalsCommand /bin/gitlab-shell-authorized-principals-check git %i sshUsers
abort "# Wrong number of arguments. #{ARGV.size}. Usage:
# gitlab-shell-authorized-principals-check <key-id> <principal1> [<principal2>...]" unless ARGV.size >= 2
key_id = ARGV[0]
abort '# No key_id provided' if key_id.nil? || key_id == ''
principals = ARGV[1..-1]
principals.each { |principal|
abort '# An invalid principal was provided' if principal.nil? || principal == ''
}
require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net'
require_relative '../lib/gitlab_keys'
principals.each { |principal|
puts GitlabKeys.principal_line("username-#{key_id}", principal.dup)
}
./gitlab-shell
\ No newline at end of file
#!/usr/bin/env ruby
#
# GitLab shell authorized principals helper. Emits the same sort of
# command="..." line as gitlab-shell-authorized-principals-check, with
# the right options.
#
# Ex.
# bin/gitlab-shell-authorized-keys-check <key-id> <principal1> [<principal2>...]
#
# Returns one line per principal passed in, e.g.:
# command="/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL}
# [command="/bin/gitlab-shell username-{KEY_ID}",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty {PRINCIPAL2}]
#
# Expects to be called by the SSH daemon, via configuration like:
# AuthorizedPrincipalsCommandUser root
# AuthorizedPrincipalsCommand /bin/gitlab-shell-authorized-principals-check git %i sshUsers
abort "# Wrong number of arguments. #{ARGV.size}. Usage:
# gitlab-shell-authorized-principals-check <key-id> <principal1> [<principal2>...]" unless ARGV.size >= 2
key_id = ARGV[0]
abort '# No key_id provided' if key_id.nil? || key_id == ''
principals = ARGV[1..-1]
principals.each { |principal|
abort '# An invalid principal was provided' if principal.nil? || principal == ''
}
require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net'
require_relative '../lib/gitlab_keys'
principals.each { |principal|
puts GitlabKeys.principal_line("username-#{key_id}", principal.dup)
}
Loading
Loading
@@ -6,7 +6,6 @@ import (
"path/filepath"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/fallback"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/readwriter"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/config"
)
Loading
Loading
@@ -28,17 +27,6 @@ func findRootDir() (string, error) {
return filepath.Dir(filepath.Dir(path)), nil
}
// rubyExec will never return. It either replaces the current process with a
// Ruby interpreter, or outputs an error and kills the process.
func execRuby(rootDir string, readWriter *readwriter.ReadWriter) {
cmd := &fallback.Command{RootDir: rootDir, Args: os.Args}
if err := cmd.Execute(); err != nil {
fmt.Fprintf(readWriter.ErrOut, "Failed to exec: %v\n", err)
os.Exit(1)
}
}
func main() {
readWriter := &readwriter.ReadWriter{
Out: os.Stdout,
Loading
Loading
@@ -52,12 +40,10 @@ func main() {
os.Exit(1)
}
// Fall back to Ruby in case of problems reading the config, but issue a
// warning as this isn't something we can sustain indefinitely
config, err := config.NewFromDir(rootDir)
if err != nil {
fmt.Fprintln(readWriter.ErrOut, "Failed to read config, falling back to gitlab-shell-ruby")
execRuby(rootDir, readWriter)
fmt.Fprintln(readWriter.ErrOut, "Failed to read config, exiting")
os.Exit(1)
}
cmd, err := command.New(os.Args, config, readWriter)
Loading
Loading
Loading
Loading
@@ -19,7 +19,6 @@ type Command interface {
func New(arguments []string, config *config.Config, readWriter *readwriter.ReadWriter) (Command, error) {
args, err := commandargs.Parse(arguments)
if err != nil {
return nil, err
}
Loading
Loading
@@ -30,7 +29,7 @@ func New(arguments []string, config *config.Config, readWriter *readwriter.ReadW
}
}
return &fallback.Command{RootDir: config.RootDir, Args: arguments}, nil
return &fallback.Command{RootDir: config.RootDir, Args: args}, nil
}
func buildCommand(args *commandargs.CommandArgs, config *config.Config, readWriter *readwriter.ReadWriter) Command {
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@ import (
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/discover"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/fallback"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/lfsauthenticate"
Loading
Loading
@@ -21,6 +22,7 @@ func TestNew(t *testing.T) {
desc string
config *config.Config
environment map[string]string
arguments []string
expectedType interface{}
}{
{
Loading
Loading
@@ -33,6 +35,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &discover.Command{},
},
{
Loading
Loading
@@ -45,6 +48,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &fallback.Command{},
},
{
Loading
Loading
@@ -57,6 +61,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "2fa_recovery_codes",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &twofactorrecover.Command{},
},
{
Loading
Loading
@@ -69,6 +74,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-lfs-authenticate",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &lfsauthenticate.Command{},
},
{
Loading
Loading
@@ -81,6 +87,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-receive-pack",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &receivepack.Command{},
},
{
Loading
Loading
@@ -93,6 +100,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-upload-pack",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &uploadpack.Command{},
},
{
Loading
Loading
@@ -105,6 +113,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-upload-archive",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &uploadarchive.Command{},
},
{
Loading
Loading
@@ -117,6 +126,7 @@ func TestNew(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-unimplemented-feature",
},
arguments: []string{string(commandargs.GitlabShell)},
expectedType: &fallback.Command{},
},
}
Loading
Loading
@@ -126,7 +136,7 @@ func TestNew(t *testing.T) {
restoreEnv := testhelper.TempEnv(tc.environment)
defer restoreEnv()
command, err := New([]string{}, tc.config, nil)
command, err := New(tc.arguments, tc.config, nil)
require.NoError(t, err)
require.IsType(t, tc.expectedType, command)
Loading
Loading
@@ -139,7 +149,7 @@ func TestFailingNew(t *testing.T) {
restoreEnv := testhelper.TempEnv(map[string]string{})
defer restoreEnv()
_, err := New([]string{}, &config.Config{}, nil)
_, err := New([]string{string(commandargs.GitlabShell)}, &config.Config{}, nil)
require.Error(t, err, "Only ssh allowed")
})
Loading
Loading
Loading
Loading
@@ -3,12 +3,14 @@ package commandargs
import (
"errors"
"os"
"path/filepath"
"regexp"
"github.com/mattn/go-shellwords"
)
type CommandType string
type Executable string
const (
Discover CommandType = "discover"
Loading
Loading
@@ -17,6 +19,7 @@ const (
ReceivePack CommandType = "git-receive-pack"
UploadPack CommandType = "git-upload-pack"
UploadArchive CommandType = "git-upload-archive"
GitlabShell Executable = "gitlab-shell"
)
var (
Loading
Loading
@@ -25,6 +28,7 @@ var (
)
type CommandArgs struct {
arguments []string
GitlabUsername string
GitlabKeyId string
SshArgs []string
Loading
Loading
@@ -32,23 +36,36 @@ type CommandArgs struct {
}
func Parse(arguments []string) (*CommandArgs, error) {
if sshConnection := os.Getenv("SSH_CONNECTION"); sshConnection == "" {
return nil, errors.New("Only ssh allowed")
}
args := &CommandArgs{arguments: arguments}
if args.Executable() == GitlabShell {
if sshConnection := os.Getenv("SSH_CONNECTION"); sshConnection == "" {
return nil, errors.New("Only ssh allowed")
}
args := &CommandArgs{}
args.parseWho(arguments)
args.parseWho()
if err := args.parseCommand(os.Getenv("SSH_ORIGINAL_COMMAND")); err != nil {
return nil, errors.New("Invalid ssh command")
}
args.defineCommandType()
if err := args.parseCommand(os.Getenv("SSH_ORIGINAL_COMMAND")); err != nil {
return nil, errors.New("Invalid ssh command")
return args, nil
} else {
return args, nil
}
args.defineCommandType()
}
func (c *CommandArgs) Executable() Executable {
return Executable(filepath.Base(c.arguments[0]))
}
return args, nil
func (c *CommandArgs) Arguments() []string {
return c.arguments[1:]
}
func (c *CommandArgs) parseWho(arguments []string) {
for _, argument := range arguments {
func (c *CommandArgs) parseWho() {
for _, argument := range c.arguments {
if keyId := tryParseKeyId(argument); keyId != "" {
c.GitlabKeyId = keyId
break
Loading
Loading
Loading
Loading
@@ -3,16 +3,16 @@ package commandargs
import (
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/testhelper"
"github.com/stretchr/testify/require"
)
func TestParseSuccess(t *testing.T) {
testCases := []struct {
desc string
arguments []string
environment map[string]string
arguments []string
expectedArgs *CommandArgs
}{
// Setting the used env variables for every case to ensure we're
Loading
Loading
@@ -23,7 +23,8 @@ func TestParseSuccess(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "",
},
expectedArgs: &CommandArgs{SshArgs: []string{}, CommandType: Discover},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{}, CommandType: Discover},
},
{
desc: "It finds the key id in any passed arguments",
Loading
Loading
@@ -31,72 +32,80 @@ func TestParseSuccess(t *testing.T) {
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "",
},
arguments: []string{"hello", "key-123"},
expectedArgs: &CommandArgs{SshArgs: []string{}, CommandType: Discover, GitlabKeyId: "123"},
arguments: []string{string(GitlabShell), "hello", "key-123"},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell), "hello", "key-123"}, SshArgs: []string{}, CommandType: Discover, GitlabKeyId: "123"},
}, {
desc: "It finds the username in any passed arguments",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "",
},
arguments: []string{"hello", "username-jane-doe"},
expectedArgs: &CommandArgs{SshArgs: []string{}, CommandType: Discover, GitlabUsername: "jane-doe"},
arguments: []string{string(GitlabShell), "hello", "username-jane-doe"},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell), "hello", "username-jane-doe"}, SshArgs: []string{}, CommandType: Discover, GitlabUsername: "jane-doe"},
}, {
desc: "It parses 2fa_recovery_codes command",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "2fa_recovery_codes",
},
expectedArgs: &CommandArgs{SshArgs: []string{"2fa_recovery_codes"}, CommandType: TwoFactorRecover},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"2fa_recovery_codes"}, CommandType: TwoFactorRecover},
}, {
desc: "It parses git-receive-pack command",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-receive-pack group/repo",
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
}, {
desc: "It parses git-receive-pack command and a project with single quotes",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git receive-pack 'group/repo'",
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
}, {
desc: `It parses "git receive-pack" command`,
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": `git receive-pack "group/repo"`,
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
}, {
desc: `It parses a command followed by control characters`,
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": `git-receive-pack group/repo; any command`,
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-receive-pack", "group/repo"}, CommandType: ReceivePack},
}, {
desc: "It parses git-upload-pack command",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": `git upload-pack "group/repo"`,
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-upload-pack", "group/repo"}, CommandType: UploadPack},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, 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},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-upload-archive", "group/repo"}, CommandType: UploadArchive},
}, {
desc: "It parses git-lfs-authenticate command",
environment: map[string]string{
"SSH_CONNECTION": "1",
"SSH_ORIGINAL_COMMAND": "git-lfs-authenticate 'group/repo' download",
},
expectedArgs: &CommandArgs{SshArgs: []string{"git-lfs-authenticate", "group/repo", "download"}, CommandType: LfsAuthenticate},
arguments: []string{string(GitlabShell)},
expectedArgs: &CommandArgs{arguments: []string{string(GitlabShell)}, SshArgs: []string{"git-lfs-authenticate", "group/repo", "download"}, CommandType: LfsAuthenticate},
},
}
Loading
Loading
@@ -115,7 +124,7 @@ func TestParseSuccess(t *testing.T) {
func TestParseFailure(t *testing.T) {
t.Run("It fails if SSH connection is not set", func(t *testing.T) {
_, err := Parse([]string{})
_, err := Parse([]string{string(GitlabShell)})
require.Error(t, err, "Only ssh allowed")
})
Loading
Loading
@@ -128,7 +137,7 @@ func TestParseFailure(t *testing.T) {
restoreEnv := testhelper.TempEnv(environment)
defer restoreEnv()
_, err := Parse([]string{})
_, err := Parse([]string{string(GitlabShell)})
require.Error(t, err, "Invalid ssh command")
})
Loading
Loading
package fallback
import (
"fmt"
"os"
"path/filepath"
"syscall"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
)
type CommandArgs interface {
Executable() commandargs.Executable
Arguments() []string
}
type Command struct {
RootDir string
Args []string
Args CommandArgs
}
var (
Loading
Loading
@@ -16,15 +24,15 @@ var (
execFunc = syscall.Exec
)
const (
RubyProgram = "gitlab-shell-ruby"
)
func (c *Command) Execute() error {
rubyCmd := filepath.Join(c.RootDir, "bin", RubyProgram)
rubyCmd := filepath.Join(c.RootDir, "bin", c.fallbackProgram())
// Ensure rubyArgs[0] is the full path to gitlab-shell-ruby
rubyArgs := append([]string{rubyCmd}, c.Args[1:]...)
rubyArgs := append([]string{rubyCmd}, c.Args.Arguments()...)
return execFunc(rubyCmd, rubyArgs, os.Environ())
}
func (c *Command) fallbackProgram() string {
return fmt.Sprintf("%s-ruby", c.Args.Executable())
}
Loading
Loading
@@ -6,6 +6,8 @@ import (
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/go/internal/command/commandargs"
)
type fakeExec struct {
Loading
Loading
@@ -18,8 +20,21 @@ type fakeExec struct {
Env []string
}
type FakeCommandArgs struct {
executable commandargs.Executable
arguments []string
}
func (f *FakeCommandArgs) Executable() commandargs.Executable {
return f.executable
}
func (f *FakeCommandArgs) Arguments() []string {
return f.arguments
}
var (
fakeArgs = []string{"./test", "foo", "bar"}
fakeArgs = &FakeCommandArgs{executable: commandargs.GitlabShell, arguments: []string{"foo", "bar"}}
)
func (f *fakeExec) Exec(filename string, args []string, env []string) error {
Loading
Loading
Loading
Loading
@@ -21,54 +21,84 @@ describe 'bin/gitlab-shell-authorized-keys-check' do
end
end
before(:all) do
write_config(
"gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
)
end
let(:authorized_keys_check_path) { File.join(tmp_root_path, 'bin', 'gitlab-shell-authorized-keys-check') }
it 'succeeds when a valid key is given' do
output, status = run!
shared_examples 'authorized keys check' do
it 'succeeds when a valid key is given' do
output, status = run!
expect(output).to eq("command=\"#{gitlab_shell_path} key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty known-rsa-key\n")
expect(status).to be_success
end
expect(output).to eq("command=\"#{gitlab_shell_path} key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty known-rsa-key\n")
expect(status).to be_success
end
it 'returns nothing when an unknown key is given' do
output, status = run!(key: 'unknown-key')
it 'returns nothing when an unknown key is given' do
output, status = run!(key: 'unknown-key')
expect(output).to eq("# No key was found for unknown-key\n")
expect(status).to be_success
end
expect(output).to eq("# No key was found for unknown-key\n")
expect(status).to be_success
end
it' fails when not enough arguments are given' do
output, status = run!(key: nil)
it' fails when not enough arguments are given' do
output, status = run!(key: nil)
expect(output).to eq('')
expect(status).not_to be_success
end
expect(output).to eq('')
expect(status).not_to be_success
it' fails when too many arguments are given' do
output, status = run!(key: ['a', 'b'])
expect(output).to eq('')
expect(status).not_to be_success
end
it 'skips when run as the wrong user' do
output, status = run!(expected_user: 'unknown-user')
expect(output).to eq('')
expect(status).to be_success
end
it 'skips when the wrong users connects' do
output, status = run!(actual_user: 'unknown-user')
expect(output).to eq('')
expect(status).to be_success
end
end
it' fails when too many arguments are given' do
output, status = run!(key: ['a', 'b'])
describe 'without go features' do
before(:all) do
write_config(
"gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
)
end
expect(output).to eq('')
expect(status).not_to be_success
it_behaves_like 'authorized keys check'
end
it 'skips when run as the wrong user' do
output, status = run!(expected_user: 'unknown-user')
describe 'without go features (via go)', :go do
before(:all) do
write_config(
"gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
)
end
expect(output).to eq('')
expect(status).to be_success
it_behaves_like 'authorized keys check'
end
it 'skips when the wrong users connects' do
output, status = run!(actual_user: 'unknown-user')
pending 'with the go authorized-keys-check feature', :go do
before(:all) do
write_config(
'gitlab_url' => "http+unix://#{CGI.escape(tmp_socket_path)}",
'migration' => {
'enabled' => true,
'features' => ['authorized-keys-check']
}
)
end
expect(output).to eq('')
expect(status).to be_success
it_behaves_like 'authorized keys check'
end
def run!(expected_user: 'git', actual_user: 'git', key: 'known-rsa-key')
Loading
Loading
require_relative 'spec_helper'
describe 'bin/gitlab-shell-authorized-principals-check' do
include_context 'gitlab shell'
def mock_server(server)
# Do nothing as we're not connecting to a server in this check.
end
let(:authorized_principals_check_path) { File.join(tmp_root_path, 'bin', 'gitlab-shell-authorized-principals-check') }
shared_examples 'authorized principals check' do
it 'succeeds when a valid principal is given' do
output, status = run!
expect(output).to eq("command=\"#{gitlab_shell_path} username-key\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty principal\n")
expect(status).to be_success
end
it 'fails when not enough arguments are given' do
output, status = run!(key_id: nil, principals: [])
expect(output).to eq('')
expect(status).not_to be_success
end
it 'fails when key_id is blank' do
output, status = run!(key_id: '')
expect(output).to eq('')
expect(status).not_to be_success
end
it 'fails when principals include an empty item' do
output, status = run!(principals: ['principal', ''])
expect(output).to eq('')
expect(status).not_to be_success
end
end
describe 'without go features' do
before(:all) do
write_config({})
end
it_behaves_like 'authorized principals check'
end
describe 'without go features (via go)', :go do
before(:all) do
write_config({})
end
it_behaves_like 'authorized principals check'
end
pending 'with the go authorized-principals-check feature', :go do
before(:all) do
write_config(
'migration' => {
'enabled' => true,
'features' => ['authorized-principals-check']
}
)
end
it_behaves_like 'authorized principals check'
end
def run!(key_id: 'key', principals: ['principal'])
cmd = [
authorized_principals_check_path,
key_id,
principals,
].flatten.compact
output = IO.popen(cmd, &:read)
[output, $?]
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment