Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-shell
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-shell
Commits
2bdf08e7
Commit
2bdf08e7
authored
Aug 01, 2018
by
Ash McKenzie
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master' into ash.mckenzie/srp-refactor
parents
a686b9a0
e3fead94
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
211 additions
and
103 deletions
+211
-103
CHANGELOG
CHANGELOG
+3
-0
VERSION
VERSION
+1
-1
bin/gitlab-shell
bin/gitlab-shell
+3
-3
bin/gitlab-shell-authorized-principals-check
bin/gitlab-shell-authorized-principals-check
+36
-0
lib/action/api_2fa_recovery.rb
lib/action/api_2fa_recovery.rb
+6
-6
lib/action/git_lfs_authenticate.rb
lib/action/git_lfs_authenticate.rb
+5
-5
lib/actor.rb
lib/actor.rb
+3
-0
lib/actor/base.rb
lib/actor/base.rb
+4
-0
lib/actor/key.rb
lib/actor/key.rb
+1
-1
lib/actor/username.rb
lib/actor/username.rb
+19
-0
lib/gitlab_keys.rb
lib/gitlab_keys.rb
+22
-4
lib/gitlab_net.rb
lib/gitlab_net.rb
+10
-7
lib/gitlab_shell.rb
lib/gitlab_shell.rb
+11
-15
spec/action/api_2fa_recovery.rb_spec.rb
spec/action/api_2fa_recovery.rb_spec.rb
+4
-4
spec/action/git_lfs_authenticate_spec.rb
spec/action/git_lfs_authenticate_spec.rb
+5
-5
spec/actor/key_spec.rb
spec/actor/key_spec.rb
+1
-1
spec/gitlab_keys_spec.rb
spec/gitlab_keys_spec.rb
+31
-3
spec/gitlab_net_spec.rb
spec/gitlab_net_spec.rb
+31
-33
spec/gitlab_shell_spec.rb
spec/gitlab_shell_spec.rb
+15
-15
No files found.
CHANGELOG
View file @
2bdf08e7
v8.0.0
- SSH certificate support (!207)
v7.2.0
v7.2.0
- Update gitaly-proto to 0.109.0 (!216)
- Update gitaly-proto to 0.109.0 (!216)
...
...
VERSION
View file @
2bdf08e7
7.2
.0
8.0
.0
bin/gitlab-shell
View file @
2bdf08e7
...
@@ -5,19 +5,19 @@ unless ENV['SSH_CONNECTION']
...
@@ -5,19 +5,19 @@ unless ENV['SSH_CONNECTION']
exit
exit
end
end
key_str
=
/key-[0-9]+/
.
match
(
ARGV
.
join
).
to_s
original_cmd
=
ENV
.
delete
(
'SSH_ORIGINAL_COMMAND'
)
original_cmd
=
ENV
.
delete
(
'SSH_ORIGINAL_COMMAND'
)
require_relative
'../lib/gitlab_init'
require_relative
'../lib/gitlab_init'
#
#
#
#
# GitLab shell, invoked from ~/.ssh/authorized_keys
# GitLab shell, invoked from ~/.ssh/authorized_keys or from an
# AuthorizedPrincipalsCommand in the key-less SSH CERT mode.
#
#
#
#
require
File
.
join
(
ROOT_PATH
,
'lib'
,
'gitlab_shell'
)
require
File
.
join
(
ROOT_PATH
,
'lib'
,
'gitlab_shell'
)
if
GitlabShell
.
new
(
key_str
).
exec
(
original_cmd
)
if
GitlabShell
.
new
(
ARGV
.
join
).
exec
(
original_cmd
)
exit
0
exit
0
else
else
exit
1
exit
1
...
...
bin/gitlab-shell-authorized-principals-check
0 → 100755
View file @
2bdf08e7
#!/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
)
}
lib/action/api_2fa_recovery.rb
View file @
2bdf08e7
...
@@ -3,8 +3,8 @@ require_relative '../gitlab_logger'
...
@@ -3,8 +3,8 @@ require_relative '../gitlab_logger'
module
Action
module
Action
class
API2FARecovery
<
Base
class
API2FARecovery
<
Base
def
initialize
(
key
)
def
initialize
(
actor
)
@
key
=
key
@
actor
=
actor
end
end
def
execute
(
_
,
_
)
def
execute
(
_
,
_
)
...
@@ -13,7 +13,7 @@ module Action
...
@@ -13,7 +13,7 @@ module Action
private
private
attr_reader
:
key
attr_reader
:
actor
def
continue?
(
question
)
def
continue?
(
question
)
puts
"
#{
question
}
(yes/no)"
puts
"
#{
question
}
(yes/no)"
...
@@ -34,10 +34,10 @@ module Action
...
@@ -34,10 +34,10 @@ module Action
return
return
end
end
resp
=
api
.
two_factor_recovery_codes
(
key
.
key_id
)
resp
=
api
.
two_factor_recovery_codes
(
self
)
if
resp
[
'success'
]
if
resp
[
'success'
]
codes
=
resp
[
'recovery_codes'
].
join
(
"
\n
"
)
codes
=
resp
[
'recovery_codes'
].
join
(
"
\n
"
)
$logger
.
info
(
'API 2FA recovery success'
,
user:
key
.
log_username
)
$logger
.
info
(
'API 2FA recovery success'
,
user:
actor
.
log_username
)
puts
"Your two-factor authentication recovery codes are:
\n\n
"
\
puts
"Your two-factor authentication recovery codes are:
\n\n
"
\
"
#{
codes
}
\n\n
"
\
"
#{
codes
}
\n\n
"
\
"During sign in, use one of the codes above when prompted for
\n
"
\
"During sign in, use one of the codes above when prompted for
\n
"
\
...
@@ -45,7 +45,7 @@ module Action
...
@@ -45,7 +45,7 @@ module Action
"a new device so you do not lose access to your account again."
"a new device so you do not lose access to your account again."
true
true
else
else
$logger
.
info
(
'API 2FA recovery error'
,
user:
key
.
log_username
)
$logger
.
info
(
'API 2FA recovery error'
,
user:
actor
.
log_username
)
puts
"An error occurred while trying to generate new recovery codes.
\n
"
\
puts
"An error occurred while trying to generate new recovery codes.
\n
"
\
"
#{
resp
[
'message'
]
}
"
"
#{
resp
[
'message'
]
}
"
end
end
...
...
lib/action/git_lfs_authenticate.rb
View file @
2bdf08e7
...
@@ -3,15 +3,15 @@ require_relative '../gitlab_logger'
...
@@ -3,15 +3,15 @@ require_relative '../gitlab_logger'
module
Action
module
Action
class
GitLFSAuthenticate
<
Base
class
GitLFSAuthenticate
<
Base
def
initialize
(
key
,
repo_name
)
def
initialize
(
actor
,
repo_name
)
@
key
=
key
@
actor
=
actor
@repo_name
=
repo_name
@repo_name
=
repo_name
end
end
def
execute
(
_
,
_
)
def
execute
(
_
,
_
)
GitlabMetrics
.
measure
(
'lfs-authenticate'
)
do
GitlabMetrics
.
measure
(
'lfs-authenticate'
)
do
$logger
.
info
(
'Processing LFS authentication'
,
user:
key
.
log_username
)
$logger
.
info
(
'Processing LFS authentication'
,
user:
actor
.
log_username
)
lfs_access
=
api
.
lfs_authenticate
(
key
.
key_id
,
repo_name
)
lfs_access
=
api
.
lfs_authenticate
(
self
,
repo_name
)
return
unless
lfs_access
return
unless
lfs_access
puts
lfs_access
.
authentication_payload
puts
lfs_access
.
authentication_payload
...
@@ -21,6 +21,6 @@ module Action
...
@@ -21,6 +21,6 @@ module Action
private
private
attr_reader
:
key
,
:repo_name
attr_reader
:
actor
,
:repo_name
end
end
end
end
lib/actor.rb
View file @
2bdf08e7
require_relative
'actor/base'
require_relative
'actor/base'
require_relative
'actor/key'
require_relative
'actor/key'
require_relative
'actor/user'
require_relative
'actor/user'
require_relative
'actor/username'
module
Actor
module
Actor
class
UnsupportedActorError
<
StandardError
;
end
class
UnsupportedActorError
<
StandardError
;
end
...
@@ -11,6 +12,8 @@ module Actor
...
@@ -11,6 +12,8 @@ module Actor
Key
.
from
(
str
,
audit_usernames:
audit_usernames
)
Key
.
from
(
str
,
audit_usernames:
audit_usernames
)
when
User
.
id_regex
when
User
.
id_regex
User
.
from
(
str
,
audit_usernames:
audit_usernames
)
User
.
from
(
str
,
audit_usernames:
audit_usernames
)
when
Username
.
id_regex
Username
.
from
(
str
,
audit_usernames:
audit_usernames
)
else
else
raise
UnsupportedActorError
raise
UnsupportedActorError
end
end
...
...
lib/actor/base.rb
View file @
2bdf08e7
...
@@ -31,6 +31,10 @@ module Actor
...
@@ -31,6 +31,10 @@ module Actor
"
#{
self
.
class
.
identifier_prefix
}
-
#{
id
}
"
"
#{
self
.
class
.
identifier_prefix
}
-
#{
id
}
"
end
end
def
identifier_key
self
.
class
.
identifier_key
end
def
log_username
def
log_username
audit_usernames?
?
username
:
"
#{
klass_name
.
downcase
}
with identifier
#{
identifier
}
"
audit_usernames?
?
username
:
"
#{
klass_name
.
downcase
}
with identifier
#{
identifier
}
"
end
end
...
...
lib/actor/key.rb
View file @
2bdf08e7
...
@@ -21,7 +21,7 @@ module Actor
...
@@ -21,7 +21,7 @@ module Actor
def
username
def
username
@username
||=
begin
@username
||=
begin
user
=
GitlabNet
.
new
.
discover
(
key_id
)
user
=
GitlabNet
.
new
.
discover
(
self
)
user
?
"@
#{
user
[
'username'
]
}
"
:
ANONYMOUS_USER
user
?
"@
#{
user
[
'username'
]
}
"
:
ANONYMOUS_USER
end
end
end
end
...
...
lib/actor/username.rb
0 → 100644
View file @
2bdf08e7
require_relative
'base'
module
Actor
class
Username
<
Base
alias
username
identifier
def
self
.
identifier_prefix
'username'
.
freeze
end
def
self
.
identifier_key
'username'
.
freeze
end
def
self
.
id_regex
/\Ausername\-\d+\Z/
end
end
end
lib/gitlab_keys.rb
View file @
2bdf08e7
...
@@ -9,12 +9,20 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
...
@@ -9,12 +9,20 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
attr_accessor
:auth_file
,
:key
attr_accessor
:auth_file
,
:key
def
self
.
command
(
key_id
)
def
self
.
command
(
whatever
)
"
#{
ROOT_PATH
}
/bin/gitlab-shell
#{
whatever
}
"
end
def
self
.
command_key
(
key_id
)
unless
/\A[a-z0-9-]+\z/
=~
key_id
unless
/\A[a-z0-9-]+\z/
=~
key_id
raise
KeyError
,
"Invalid key_id:
#{
key_id
.
inspect
}
"
raise
KeyError
,
"Invalid key_id:
#{
key_id
.
inspect
}
"
end
end
"
#{
ROOT_PATH
}
/bin/gitlab-shell
#{
key_id
}
"
command
(
key_id
)
end
def
self
.
whatever_line
(
command
,
trailer
)
"command=
\"
#{
command
}
\"
,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
#{
trailer
}
"
end
end
def
self
.
key_line
(
key_id
,
public_key
)
def
self
.
key_line
(
key_id
,
public_key
)
...
@@ -24,7 +32,17 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
...
@@ -24,7 +32,17 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
raise
KeyError
,
"Invalid public_key:
#{
public_key
.
inspect
}
"
raise
KeyError
,
"Invalid public_key:
#{
public_key
.
inspect
}
"
end
end
"command=
\"
#{
command
(
key_id
)
}
\"
,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
#{
public_key
}
"
whatever_line
(
command_key
(
key_id
),
public_key
)
end
def
self
.
principal_line
(
username_key_id
,
principal
)
principal
.
chomp!
if
principal
.
include?
(
"
\n
"
)
raise
KeyError
,
"Invalid principal:
#{
principal
.
inspect
}
"
end
whatever_line
(
command_key
(
username_key_id
),
principal
)
end
end
def
initialize
def
initialize
...
@@ -119,7 +137,7 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
...
@@ -119,7 +137,7 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
$logger
.
info
(
'Removing key'
,
key_id:
@key_id
)
$logger
.
info
(
'Removing key'
,
key_id:
@key_id
)
open_auth_file
(
'r+'
)
do
|
f
|
open_auth_file
(
'r+'
)
do
|
f
|
while
line
=
f
.
gets
# rubocop:disable Style/AssignmentInCondition
while
line
=
f
.
gets
# rubocop:disable Style/AssignmentInCondition
next
unless
line
.
start_with?
(
"command=
\"
#{
self
.
class
.
command
(
@key_id
)
}
\"
"
)
next
unless
line
.
start_with?
(
"command=
\"
#{
self
.
class
.
command
_key
(
@key_id
)
}
\"
"
)
f
.
seek
(
-
line
.
length
,
IO
::
SEEK_CUR
)
f
.
seek
(
-
line
.
length
,
IO
::
SEEK_CUR
)
# Overwrite the line with #'s. Because the 'line' variable contains
# Overwrite the line with #'s. Because the 'line' variable contains
# a terminating '\n', we write line.length - 1 '#' characters.
# a terminating '\n', we write line.length - 1 '#' characters.
...
...
lib/gitlab_net.rb
View file @
2bdf08e7
...
@@ -26,22 +26,24 @@ class GitlabNet
...
@@ -26,22 +26,24 @@ class GitlabNet
env:
env
env:
env
}
}
params
[
actor
.
class
.
identifier_key
.
to_sym
]
=
actor
.
id
params
[
actor
.
identifier_key
.
to_sym
]
=
actor
.
id
resp
=
post
(
"
#{
internal_api_endpoint
}
/allowed"
,
params
)
resp
=
post
(
"
#{
internal_api_endpoint
}
/allowed"
,
params
)
determine_action
(
actor
,
resp
)
determine_action
(
actor
,
resp
)
end
end
def
discover
(
key_id
)
def
discover
(
actor
)
resp
=
get
(
"
#{
internal_api_endpoint
}
/discover?
key_id=
#{
key_
id
}
"
)
resp
=
get
(
"
#{
internal_api_endpoint
}
/discover?
#{
actor
.
identifier_key
}
=
#{
actor
.
id
}
"
)
JSON
.
parse
(
resp
.
body
)
JSON
.
parse
(
resp
.
body
)
rescue
JSON
::
ParserError
,
ApiUnreachableError
rescue
JSON
::
ParserError
,
ApiUnreachableError
nil
nil
end
end
def
lfs_authenticate
(
key_id
,
repo
)
def
lfs_authenticate
(
actor
,
repo
)
params
=
{
project:
sanitize_path
(
repo
),
key_id:
key_id
}
params
=
{
project:
sanitize_path
(
repo
)
}
params
[
actor
.
identifier_key
.
to_sym
]
=
actor
.
id
resp
=
post
(
"
#{
internal_api_endpoint
}
/lfs_authenticate"
,
params
)
resp
=
post
(
"
#{
internal_api_endpoint
}
/lfs_authenticate"
,
params
)
GitlabLfsAuthentication
.
build_from_json
(
resp
.
body
)
if
resp
.
code
==
HTTP_SUCCESS
GitlabLfsAuthentication
.
build_from_json
(
resp
.
body
)
if
resp
.
code
==
HTTP_SUCCESS
...
@@ -75,8 +77,9 @@ class GitlabNet
...
@@ -75,8 +77,9 @@ class GitlabNet
nil
nil
end
end
def
two_factor_recovery_codes
(
key_id
)
def
two_factor_recovery_codes
(
actor
)
resp
=
post
(
"
#{
internal_api_endpoint
}
/two_factor_recovery_codes"
,
key_id:
key_id
)
params
=
{
actor
.
identifier_key
.
to_sym
=>
actor
.
id
}
resp
=
post
(
"
#{
internal_api_endpoint
}
/two_factor_recovery_codes"
,
params
)
JSON
.
parse
(
resp
.
body
)
if
resp
.
code
==
HTTP_SUCCESS
JSON
.
parse
(
resp
.
body
)
if
resp
.
code
==
HTTP_SUCCESS
rescue
rescue
{}
{}
...
...
lib/gitlab_shell.rb
View file @
2bdf08e7
...
@@ -3,7 +3,7 @@ require 'pathname'
...
@@ -3,7 +3,7 @@ require 'pathname'
require_relative
'gitlab_net'
require_relative
'gitlab_net'
require_relative
'gitlab_metrics'
require_relative
'gitlab_metrics'
require_relative
'actor
/key
'
require_relative
'actor'
class
GitlabShell
class
GitlabShell
API_2FA_RECOVERY_CODES_COMMAND
=
'2fa_recovery_codes'
.
freeze
API_2FA_RECOVERY_CODES_COMMAND
=
'2fa_recovery_codes'
.
freeze
...
@@ -18,9 +18,9 @@ class GitlabShell
...
@@ -18,9 +18,9 @@ class GitlabShell
Struct
.
new
(
'ParsedCommand'
,
:command
,
:git_access_command
,
:repo_name
,
:args
)
Struct
.
new
(
'ParsedCommand'
,
:command
,
:git_access_command
,
:repo_name
,
:args
)
def
initialize
(
key_str
)
def
initialize
(
who
)
@key_str
=
key_str
@config
=
GitlabConfig
.
new
@config
=
GitlabConfig
.
new
@actor
=
Actor
.
new_from
(
who
,
audit_usernames:
@config
.
audit_usernames
)
end
end
# The origin_cmd variable contains UNTRUSTED input. If the user ran
# The origin_cmd variable contains UNTRUSTED input. If the user ran
...
@@ -28,22 +28,22 @@ class GitlabShell
...
@@ -28,22 +28,22 @@ class GitlabShell
# 'evil command'.
# 'evil command'.
def
exec
(
origin_cmd
)
def
exec
(
origin_cmd
)
if
!
origin_cmd
||
origin_cmd
.
empty?
if
!
origin_cmd
||
origin_cmd
.
empty?
puts
"Welcome to GitLab,
#{
key
.
username
}
!"
puts
"Welcome to GitLab,
#{
actor
.
username
}
!"
return
true
return
true
end
end
parsed_command
=
parse_cmd
(
origin_cmd
)
parsed_command
=
parse_cmd
(
origin_cmd
)
action
=
determine_action
(
parsed_command
)
action
=
determine_action
(
parsed_command
)
# FIXME: watch out
action
.
execute
(
parsed_command
.
command
,
parsed_command
.
args
)
action
.
execute
(
parsed_command
.
command
,
parsed_command
.
args
)
rescue
GitlabNet
::
ApiUnreachableError
rescue
GitlabNet
::
ApiUnreachableError
$stderr
.
puts
"GitLab: Failed to authorize your Git request: internal API unreachable"
$stderr
.
puts
"GitLab: Failed to authorize your Git request: internal API unreachable"
false
false
rescue
AccessDeniedError
,
UnknownError
=>
ex
rescue
AccessDeniedError
,
UnknownError
=>
ex
$logger
.
warn
(
'Access denied'
,
command:
origin_cmd
,
user:
key
.
log_username
)
$logger
.
warn
(
'Access denied'
,
command:
origin_cmd
,
user:
actor
.
log_username
)
$stderr
.
puts
"GitLab:
#{
ex
.
message
}
"
$stderr
.
puts
"GitLab:
#{
ex
.
message
}
"
false
false
rescue
DisallowedCommandError
rescue
DisallowedCommandError
$logger
.
warn
(
'Denied disallowed command'
,
command:
origin_cmd
,
user:
key
.
log_username
)
$logger
.
warn
(
'Denied disallowed command'
,
command:
origin_cmd
,
user:
actor
.
log_username
)
$stderr
.
puts
'GitLab: Disallowed command'
$stderr
.
puts
'GitLab: Disallowed command'
false
false
rescue
InvalidRepositoryPathError
rescue
InvalidRepositoryPathError
...
@@ -53,11 +53,7 @@ class GitlabShell
...
@@ -53,11 +53,7 @@ class GitlabShell
private
private
attr_reader
:config
,
:key_str
attr_reader
:config
,
:actor
def
key
@key
||=
Actor
::
Key
.
from
(
key_str
,
audit_usernames:
config
.
audit_usernames
)
end
def
parse_cmd
(
cmd
)
def
parse_cmd
(
cmd
)
args
=
Shellwords
.
shellwords
(
cmd
)
args
=
Shellwords
.
shellwords
(
cmd
)
...
@@ -99,7 +95,7 @@ class GitlabShell
...
@@ -99,7 +95,7 @@ class GitlabShell
end
end
def
determine_action
(
parsed_command
)
def
determine_action
(
parsed_command
)
return
Action
::
API2FARecovery
.
new
(
key
)
if
parsed_command
.
command
==
API_2FA_RECOVERY_CODES_COMMAND
return
Action
::
API2FARecovery
.
new
(
actor
)
if
parsed_command
.
command
==
API_2FA_RECOVERY_CODES_COMMAND
GitlabMetrics
.
measure
(
'verify-access'
)
do
GitlabMetrics
.
measure
(
'verify-access'
)
do
# GitlatNet#check_access will raise exception in the event of a problem
# GitlatNet#check_access will raise exception in the event of a problem
...
@@ -107,13 +103,13 @@ class GitlabShell
...
@@ -107,13 +103,13 @@ class GitlabShell
parsed_command
.
git_access_command
,
parsed_command
.
git_access_command
,
nil
,
nil
,
parsed_command
.
repo_name
,
parsed_command
.
repo_name
,
key
,
actor
,
'_any'
'_any'
)
)
case
parsed_command
.
command
case
parsed_command
.
command
when
GIT_LFS_AUTHENTICATE_COMMAND
when
GIT_LFS_AUTHENTICATE_COMMAND
Action
::
GitLFSAuthenticate
.
new
(
key
,
parsed_command
.
repo_name
)
Action
::
GitLFSAuthenticate
.
new
(
actor
,
parsed_command
.
repo_name
)
else
else
initial_action
initial_action
end
end
...
...
spec/action/api_2fa_recovery.rb_spec.rb
View file @
2bdf08e7
...
@@ -3,18 +3,18 @@ require_relative '../../lib/action/api_2fa_recovery'
...
@@ -3,18 +3,18 @@ require_relative '../../lib/action/api_2fa_recovery'
describe
Action
::
API2FARecovery
do
describe
Action
::
API2FARecovery
do
let
(
:key_id
)
{
'1'
}
let
(
:key_id
)
{
'1'
}
let
(
:
key
)
{
Actor
::
Key
.
new
(
key_id
)
}
let
(
:
actor
)
{
Actor
::
Key
.
new
(
key_id
)
}
let
(
:username
)
{
'testuser'
}
let
(
:username
)
{
'testuser'
}
let
(
:discover_payload
)
{
{
'username'
=>
username
}
}
let
(
:discover_payload
)
{
{
'username'
=>
username
}
}
let
(
:api
)
{
double
(
GitlabNet
)
}
let
(
:api
)
{
double
(
GitlabNet
)
}
before
do
before
do
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
api
).
to
receive
(
:discover
).
with
(
key_id
).
and_return
(
discover_payload
)
allow
(
api
).
to
receive
(
:discover
).
with
(
actor
).
and_return
(
discover_payload
)
end
end
subject
do
subject
do
described_class
.
new
(
key
)
described_class
.
new
(
actor
)
end
end
describe
'#execute'
do
describe
'#execute'
do
...
@@ -46,7 +46,7 @@ describe Action::API2FARecovery do
...
@@ -46,7 +46,7 @@ describe Action::API2FARecovery do
before
do
before
do
expect
(
subject
).
to
receive
(
:continue?
).
and_return
(
true
)
expect
(
subject
).
to
receive
(
:continue?
).
and_return
(
true
)
expect
(
api
).
to
receive
(
:two_factor_recovery_codes
).
with
(
key_id
).
and_return
(
response
)
expect
(
api
).
to
receive
(
:two_factor_recovery_codes
).
with
(
subject
).
and_return
(
response
)
end
end
context
'with a unsuccessful response'
do
context
'with a unsuccessful response'
do
...
...
spec/action/git_lfs_authenticate_spec.rb
View file @
2bdf08e7
...
@@ -4,24 +4,24 @@ require_relative '../../lib/action/git_lfs_authenticate'
...
@@ -4,24 +4,24 @@ require_relative '../../lib/action/git_lfs_authenticate'
describe
Action
::
GitLFSAuthenticate
do
describe
Action
::
GitLFSAuthenticate
do
let
(
:key_id
)
{
'1'
}
let
(
:key_id
)
{
'1'
}
let
(
:repo_name
)
{
'gitlab-ci.git'
}
let
(
:repo_name
)
{
'gitlab-ci.git'
}
let
(
:
key
)
{
Actor
::
Key
.
new
(
key_id
)
}
let
(
:
actor
)
{
Actor
::
Key
.
new
(
key_id
)
}
let
(
:username
)
{
'testuser'
}
let
(
:username
)
{
'testuser'
}
let
(
:discover_payload
)
{
{
'username'
=>
username
}
}
let
(
:discover_payload
)
{
{
'username'
=>
username
}
}
let
(
:api
)
{
double
(
GitlabNet
)
}
let
(
:api
)
{
double
(
GitlabNet
)
}
before
do
before
do
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
api
).
to
receive
(
:discover
).
with
(
key_id
).
and_return
(
discover_payload
)
allow
(
api
).
to
receive
(
:discover
).
with
(
actor
).
and_return
(
discover_payload
)
end
end
subject
do
subject
do
described_class
.
new
(
key
,
repo_name
)
described_class
.
new
(
actor
,
repo_name
)
end
end
describe
'#execute'
do
describe
'#execute'
do
context
'when response from API is not a success'
do
context
'when response from API is not a success'
do
before
do
before
do
expect
(
api
).
to
receive
(
:lfs_authenticate
).
with
(
key_id
,
repo_name
).
and_return
(
nil
)
expect
(
api
).
to
receive
(
:lfs_authenticate
).
with
(
subject
,
repo_name
).
and_return
(
nil
)
end
end
it
'returns nil'
do
it
'returns nil'
do
...
@@ -36,7 +36,7 @@ describe Action::GitLFSAuthenticate do
...
@@ -36,7 +36,7 @@ describe Action::GitLFSAuthenticate do
let
(
:gitlab_lfs_authentication
)
{
GitlabLfsAuthentication
.
new
(
username
,
lfs_token
,
repository_http_path
)
}
let
(
:gitlab_lfs_authentication
)
{
GitlabLfsAuthentication
.
new
(
username
,
lfs_token
,
repository_http_path
)
}
before
do
before
do
expect
(
api
).
to
receive
(
:lfs_authenticate
).
with
(
key_id
,
repo_name
).
and_return
(
gitlab_lfs_authentication
)
expect
(
api
).
to
receive
(
:lfs_authenticate
).
with
(
subject
,
repo_name
).
and_return
(
gitlab_lfs_authentication
)
end
end
it
'puts payload to stdout'
do
it
'puts payload to stdout'
do
...
...
spec/actor/key_spec.rb
View file @
2bdf08e7
...
@@ -11,7 +11,7 @@ describe Actor::Key do
...
@@ -11,7 +11,7 @@ describe Actor::Key do
before
do
before
do
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
api
).
to
receive
(
:discover
).
with
(
key_id
).
and_return
(
discover_payload
)
allow
(
api
).
to
receive
(
:discover
).
with
(
subject
).
and_return
(
discover_payload
)
end
end
describe
'.from'
do
describe
'.from'
do
...
...
spec/gitlab_keys_spec.rb
View file @
2bdf08e7
...
@@ -8,13 +8,25 @@ describe GitlabKeys do
...
@@ -8,13 +8,25 @@ describe GitlabKeys do
end
end
describe
'.command'
do
describe
'.command'
do
it
'the internal "command" utility function'
do
command
=
"
#{
ROOT_PATH
}
/bin/gitlab-shell does-not-validate"
expect
(
described_class
.
command
(
'does-not-validate'
)).
to
eq
(
command
)
end
it
'does not raise a KeyError on invalid input'
do
command
=
"
#{
ROOT_PATH
}
/bin/gitlab-shell foo
\n
bar
\n
baz
\n
"
expect
(
described_class
.
command
(
"foo
\n
bar
\n
baz
\n
"
)).
to
eq
(
command
)
end
end
describe
'.command_key'
do
it
'returns the "command" part of the key line'
do
it
'returns the "command" part of the key line'
do
command
=
"
#{
ROOT_PATH
}
/bin/gitlab-shell key-123"
command
=
"
#{
ROOT_PATH
}
/bin/gitlab-shell key-123"
expect
(
described_class
.
command
(
'key-123'
)).
to
eq
(
command
)
expect
(
described_class
.
command
_key
(
'key-123'
)).
to
eq
(
command
)
end
end
it
'raises KeyError on invalid input'
do
it
'raises KeyError on invalid input'
do
expect
do
described_class
.
command
(
"
\n
ssh-rsa AAA"
)
end
.
to
raise_error
(
described_class
::
KeyError
)
expect
{
described_class
.
command_key
(
"
\n
ssh-rsa AAA"
)
}
.
to
raise_error
(
described_class
::
KeyError
)
end
end
end
end
...
@@ -30,7 +42,23 @@ describe GitlabKeys do
...
@@ -30,7 +42,23 @@ describe GitlabKeys do
end
end
it
'raises KeyError on invalid input'
do
it
'raises KeyError on invalid input'
do
expect
do
described_class
.
key_line
(
'key-741'
,
"ssh-rsa AAA
\n
ssh-rsa AAA"
)
end
.
to
raise_error
(
described_class
::
KeyError
)
expect
{
described_class
.
key_line
(
'key-741'
,
"ssh-rsa AAA
\n
ssh-rsa AAA"
)
}.
to
raise_error
(
described_class
::
KeyError
)
end
end
describe
'.principal_line'
do
let
(
:line
)
{
%(command="#{ROOT_PATH}/bin/gitlab-shell username-someuser",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty sshUsers)
}
it
'returns the key line'
do
expect
(
described_class
.
principal_line
(
'username-someuser'
,
'sshUsers'
)).
to
eq
(
line
)
end
it
'silently removes a trailing newline'
do
expect
(
described_class
.
principal_line
(
'username-someuser'
,
"sshUsers
\n
"
)).
to
eq
(
line
)
end
it
'raises KeyError on invalid input'
do
expect
{
described_class
.
principal_line
(
'username-someuser'
,
"sshUsers
\n
loginUsers"
)
}.
to
raise_error
(
described_class
::
KeyError
)
end
end
end
end
...
...
spec/gitlab_net_spec.rb
View file @
2bdf08e7
This diff is collapsed.
Click to expand it.
spec/gitlab_shell_spec.rb
View file @
2bdf08e7
...
@@ -10,44 +10,44 @@ describe GitlabShell do
...
@@ -10,44 +10,44 @@ describe GitlabShell do
after
{
FileUtils
.
rm_rf
(
tmp_repos_path
)
}
after
{
FileUtils
.
rm_rf
(
tmp_repos_path
)
}
subject
{
described_class
.
new
(
key_id
)
}
subject
{
described_class
.
new
(
who
)
}
let
(
:key_id
)
{
'1'
}
let
(
:who
)
{
'key-1'
}
let
(
:key
)
{
Actor
::
Key
.
new
(
key_id
)
}
let
(
:audit_usernames
)
{
true
}
let
(
:actor
)
{
Actor
.
new_from
(
who
,
audit_usernames:
audit_usernames
)
}
let
(
:tmp_repos_path
)
{
File
.
join
(
ROOT_PATH
,
'tmp'
,
'repositories'
)
}
let
(
:tmp_repos_path
)
{
File
.
join
(
ROOT_PATH
,
'tmp'
,
'repositories'
)
}
let
(
:repo_name
)
{
'gitlab-ci.git'
}
let
(
:repo_name
)
{
'gitlab-ci.git'
}
let
(
:repo_path
)
{
File
.
join
(
tmp_repos_path
,
repo_name
)
}
let
(
:repo_path
)
{
File
.
join
(
tmp_repos_path
,
repo_name
)
}
let
(
:gl_repository
)
{
'project-1'
}
let
(
:gl_repository
)
{
'project-1'
}
let
(
:gl_username
)
{
'testuser'
}
let
(
:gl_username
)
{
'testuser'
}
let
(
:audit_usernames
)
{
true
}
let
(
:api
)
{
double
(
GitlabNet
)
}
let
(
:api
)
{
double
(
GitlabNet
)
}
let
(
:config
)
{
double
(
GitlabConfig
)
}
let
(
:config
)
{
double
(
GitlabConfig
)
}
let
(
:gitaly_action
)
{
Action
::
Gitaly
.
new
(
let
(
:gitaly_action
)
{
Action
::
Gitaly
.
new
(
key_id
,
actor
,
gl_repository
,
gl_repository
,
gl_username
,
gl_username
,
repo_path
,
repo_path
,
{
'repository'
=>
{
'relative_path'
=>
repo_name
,
'storage_name'
=>
'default'
}
,
'address'
=>
'unix:gitaly.socket'
})
{
'repository'
=>
{
'relative_path'
=>
repo_name
,
'storage_name'
=>
'default'
}
,
'address'
=>
'unix:gitaly.socket'
})
}
}
let
(
:api_2fa_recovery_action
)
{
Action
::
API2FARecovery
.
new
(
key_id
)
}
let
(
:api_2fa_recovery_action
)
{
Action
::
API2FARecovery
.
new
(
actor
)
}
let
(
:git_lfs_authenticate_action
)
{
Action
::
GitLFSAuthenticate
.
new
(
key_id
,
repo_name
)
}
let
(
:git_lfs_authenticate_action
)
{
Action
::
GitLFSAuthenticate
.
new
(
actor
,
repo_name
)
}
before
do
before
do
allow
(
GitlabConfig
).
to
receive
(
:new
).
and_return
(
config
)
allow
(
GitlabConfig
).
to
receive
(
:new
).
and_return
(
config
)
allow
(
config
).
to
receive
(
:audit_usernames
).
and_return
(
audit_usernames
)
allow
(
config
).
to
receive
(
:audit_usernames
).
and_return
(
audit_usernames
)
allow
(
Actor
::
Key
).
to
receive
(
:from
).
with
(
key_id
,
audit_usernames:
audit_usernames
).
and_return
(
key
)
allow
(
Actor
).
to
receive
(
:new_from
).
with
(
who
,
audit_usernames:
audit_usernames
).
and_return
(
actor
)
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
GitlabNet
).
to
receive
(
:new
).
and_return
(
api
)
allow
(
api
).
to
receive
(
:discover
).
with
(
key_id
).
and_return
(
'username'
=>
gl_username
)
allow
(
api
).
to
receive
(
:discover
).
with
(
actor
).
and_return
(
'username'
=>
gl_username
)
end
end
describe
'#exec'
do
describe
'#exec'
do
context
"when we don't have a valid user"
do
context
"when we don't have a valid user"
do
before
do
before
do
allow
(
api
).
to
receive
(
:discover
).
with
(
key_id
).
and_return
(
nil
)
allow
(
api
).
to
receive
(
:discover
).
with
(
actor
).
and_return
(
nil
)
end
end
it
'prints Welcome.. and returns true'
do
it
'prints Welcome.. and returns true'
do
...
@@ -114,7 +114,7 @@ describe GitlabShell do
...
@@ -114,7 +114,7 @@ describe GitlabShell do
let
(
:git_access
)
{
'2fa_recovery_codes'
}
let
(
:git_access
)
{
'2fa_recovery_codes'
}
before
do
before
do
expect
(
Action
::
API2FARecovery
).
to
receive
(
:new
).
with
(
key
).
and_return
(
api_2fa_recovery_action
)
expect
(
Action
::
API2FARecovery
).
to
receive
(
:new
).
with
(
actor
).
and_return
(
api_2fa_recovery_action
)
end
end
it
'returns true'
do
it
'returns true'
do
...
@@ -125,7 +125,7 @@ describe GitlabShell do
...
@@ -125,7 +125,7 @@ describe GitlabShell do
context
'when access to the repo is denied'
do
context
'when access to the repo is denied'
do
before
do
before
do
expect
(
api
).
to
receive
(
:check_access
).
with
(
'git-upload-pack'
,
nil
,
repo_name
,
key
,
'_any'
).
and_raise
(
AccessDeniedError
,
'Sorry, access denied'
)
expect
(
api
).
to
receive
(
:check_access
).
with
(
'git-upload-pack'
,
nil
,
repo_name
,
actor
,
'_any'
).
and_raise
(
AccessDeniedError
,
'Sorry, access denied'
)
end
end
it
'prints a message to stderr and returns false'
do
it
'prints a message to stderr and returns false'
do
...
@@ -136,7 +136,7 @@ describe GitlabShell do
...
@@ -136,7 +136,7 @@ describe GitlabShell do
context
'when the API is unavailable'
do
context
'when the API is unavailable'
do
before
do
before
do
expect
(
api
).
to
receive
(
:check_access
).
with
(
'git-upload-pack'
,
nil
,
repo_name
,
key
,
'_any'
).
and_raise
(
GitlabNet
::
ApiUnreachableError
)
expect
(
api
).
to
receive
(
:check_access
).
with
(
'git-upload-pack'
,
nil
,
repo_name
,
actor
,
'_any'
).
and_raise
(
GitlabNet
::
ApiUnreachableError
)
end
end
it
'prints a message to stderr and returns false'
do
it
'prints a message to stderr and returns false'
do
...
@@ -147,7 +147,7 @@ describe GitlabShell do
...
@@ -147,7 +147,7 @@ describe GitlabShell do
context
'when access has been verified OK'
do
context
'when access has been verified OK'
do
before
do
before
do
expect
(
api
).
to
receive
(
:check_access
).
with
(
git_access
,
nil
,
repo_name
,
key
,
'_any'
).
and_return
(
gitaly_action
)
expect
(
api
).
to
receive
(
:check_access
).
with
(
git_access
,
nil
,
repo_name
,
actor
,
'_any'
).
and_return
(
gitaly_action
)
end
end
context
'when origin_cmd is git-upload-pack'
do
context
'when origin_cmd is git-upload-pack'
do
...
@@ -180,7 +180,7 @@ describe GitlabShell do
...
@@ -180,7 +180,7 @@ describe GitlabShell do
let
(
:lfs_access
)
{
double
(
GitlabLfsAuthentication
,
authentication_payload:
fake_payload
)}
let
(
:lfs_access
)
{
double
(
GitlabLfsAuthentication
,
authentication_payload:
fake_payload
)}
before
do
before
do
expect
(
Action
::
GitLFSAuthenticate
).
to
receive
(
:new
).
with
(
key
,
repo_name
).
and_return
(
git_lfs_authenticate_action
)
expect
(
Action
::
GitLFSAuthenticate
).
to
receive
(
:new
).
with
(
actor
,
repo_name
).
and_return
(
git_lfs_authenticate_action
)
end
end
context
'upload'
do
context
'upload'
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment