Commit c8bf2e7d authored by Nick Thomas's avatar Nick Thomas

Revert "Merge branch 'ash.mckenzie/srp-refactor' into 'master'"

This reverts commit 3aaf4751, reversing
changes made to c6577e0d.
parent 764f6f47
source "http://rubygems.org" source "http://rubygems.org"
group :development, :test do group :development, :test do
gem 'guard-rspec', '~> 4.0' gem 'guard', '~> 1.5.0'
gem 'listen', '~> 3.0.0' gem 'guard-rspec', '~> 2.1.0'
gem 'rspec', '~> 3.0' gem 'listen', '~> 0.5.0'
gem 'rspec', '~> 2.0'
gem 'rspec-its', '~> 1.0.0' gem 'rspec-its', '~> 1.0.0'
gem 'rubocop', '0.49.1', require: false gem 'rubocop', '0.49.1', require: false
gem 'simplecov', '~> 0.9.0', require: false gem 'simplecov', '~> 0.9.0', require: false
gem 'vcr', '~> 4.0' gem 'vcr', '~> 2.4.0'
gem 'webmock', '~> 1.9.0' gem 'webmock', '~> 1.9.0'
end end
...@@ -9,32 +9,18 @@ GEM ...@@ -9,32 +9,18 @@ GEM
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
diff-lcs (1.3) diff-lcs (1.3)
docile (1.1.5) docile (1.1.5)
ffi (1.9.25) guard (1.5.4)
formatador (0.2.5) listen (>= 0.4.2)
guard (2.14.2) lumberjack (>= 1.0.2)
formatador (>= 0.2.4) pry (>= 0.9.10)
listen (>= 2.7, < 4.0) thor (>= 0.14.6)
lumberjack (>= 1.0.12, < 2.0) guard-rspec (2.1.2)
nenv (~> 0.1) guard (>= 1.1)
notiffany (~> 0.0) rspec (~> 2.11)
pry (>= 0.9.12) listen (0.5.3)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-rspec (4.7.3)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
lumberjack (1.0.13) lumberjack (1.0.13)
method_source (0.9.0) method_source (0.9.0)
multi_json (1.13.1) multi_json (1.13.1)
nenv (0.3.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
parallel (1.12.1) parallel (1.12.1)
parser (2.5.1.2) parser (2.5.1.2)
ast (~> 2.4.0) ast (~> 2.4.0)
...@@ -46,25 +32,17 @@ GEM ...@@ -46,25 +32,17 @@ GEM
rainbow (2.2.2) rainbow (2.2.2)
rake rake
rake (12.3.1) rake (12.3.1)
rb-fsevent (0.10.3) rspec (2.99.0)
rb-inotify (0.9.10) rspec-core (~> 2.99.0)
ffi (>= 0.5.0, < 2) rspec-expectations (~> 2.99.0)
rspec (3.7.0) rspec-mocks (~> 2.99.0)
rspec-core (~> 3.7.0) rspec-core (2.99.2)
rspec-expectations (~> 3.7.0) rspec-expectations (2.99.2)
rspec-mocks (~> 3.7.0) diff-lcs (>= 1.1.3, < 2.0)
rspec-core (3.7.1)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-its (1.0.1) rspec-its (1.0.1)
rspec-core (>= 2.99.0.beta1) rspec-core (>= 2.99.0.beta1)
rspec-expectations (>= 2.99.0.beta1) rspec-expectations (>= 2.99.0.beta1)
rspec-mocks (3.7.0) rspec-mocks (2.99.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-support (3.7.1)
rubocop (0.49.1) rubocop (0.49.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0) parser (>= 2.3.3.1, < 3.0)
...@@ -74,7 +52,6 @@ GEM ...@@ -74,7 +52,6 @@ GEM
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0) ruby-progressbar (1.9.0)
safe_yaml (1.0.4) safe_yaml (1.0.4)
shellany (0.0.1)
simplecov (0.9.2) simplecov (0.9.2)
docile (~> 1.1.0) docile (~> 1.1.0)
multi_json (~> 1.0) multi_json (~> 1.0)
...@@ -82,7 +59,7 @@ GEM ...@@ -82,7 +59,7 @@ GEM
simplecov-html (0.9.0) simplecov-html (0.9.0)
thor (0.20.0) thor (0.20.0)
unicode-display_width (1.4.0) unicode-display_width (1.4.0)
vcr (4.0.0) vcr (2.4.0)
webmock (1.9.3) webmock (1.9.3)
addressable (>= 2.2.7) addressable (>= 2.2.7)
crack (>= 0.3.2) crack (>= 0.3.2)
...@@ -91,13 +68,14 @@ PLATFORMS ...@@ -91,13 +68,14 @@ PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
guard-rspec (~> 4.0) guard (~> 1.5.0)
listen (~> 3.0.0) guard-rspec (~> 2.1.0)
rspec (~> 3.0) listen (~> 0.5.0)
rspec (~> 2.0)
rspec-its (~> 1.0.0) rspec-its (~> 1.0.0)
rubocop (= 0.49.1) rubocop (= 0.49.1)
simplecov (~> 0.9.0) simplecov (~> 0.9.0)
vcr (~> 4.0) vcr (~> 2.4.0)
webmock (~> 1.9.0) webmock (~> 1.9.0)
BUNDLED WITH BUNDLED WITH
......
# A sample Guardfile
# More info at https://github.com/guard/guard#readme # More info at https://github.com/guard/guard#readme
guard :rspec, cmd: 'bundle exec rspec' do guard 'rspec' do
watch(%r{^spec/.+_spec\.rb$}) watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { "spec" } watch('spec/spec_helper.rb') { "spec" }
# Rails example
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch('config/routes.rb') { "spec/routing" }
watch('app/controllers/application_controller.rb') { "spec/controllers" }
# Capybara features specs
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
# Turnip features and steps
watch(%r{^spec/acceptance/(.+)\.feature$})
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end end
...@@ -10,16 +10,16 @@ ...@@ -10,16 +10,16 @@
# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQA... # command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQA...
# #
full_key = ARGV[0] key = ARGV[0]
abort "# No key provided" if full_key.nil? || full_key.empty? abort "# No key provided" if key.nil? || key.empty?
require_relative "../lib/gitlab_init" require_relative "../lib/gitlab_init"
require_relative "../lib/gitlab_net" require_relative "../lib/gitlab_net"
require_relative "../lib/gitlab_keys" require_relative "../lib/gitlab_keys"
authorized_key = GitlabNet.new.authorized_key(full_key) authorized_key = GitlabNet.new.authorized_key(key)
if authorized_key.nil? if authorized_key.nil?
puts "# No key was found for #{full_key}" puts "# No key was found for #{key}"
else else
puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key['key']) puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key["key"])
end end
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# command for a given ssh key fingerprint # command for a given ssh key fingerprint
# #
# Ex. # Ex.
# bin/gitlab-shell-authorized-keys-check <expected-username> <actual-username> <public-key> # bin/gitlab-shell-authorized-keys-check <username> <public-key>
# #
# Returns # Returns
# command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA... # command="/bin/gitlab-shell key-#",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAA...
...@@ -27,16 +27,16 @@ abort '# No username provided' if actual_username.nil? || actual_username == '' ...@@ -27,16 +27,16 @@ abort '# No username provided' if actual_username.nil? || actual_username == ''
# Normally, these would both be 'git', but it can be configured by the user # Normally, these would both be 'git', but it can be configured by the user
exit 0 unless expected_username == actual_username exit 0 unless expected_username == actual_username
full_key = ARGV[2] key = ARGV[2]
abort "# No key provided" if full_key.nil? || full_key == '' abort "# No key provided" if key.nil? || key == ''
require_relative '../lib/gitlab_init' require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net' require_relative '../lib/gitlab_net'
require_relative '../lib/gitlab_keys' require_relative '../lib/gitlab_keys'
authorized_key = GitlabNet.new.authorized_key(full_key) authorized_key = GitlabNet.new.authorized_key(key)
if authorized_key.nil? if authorized_key.nil?
puts "# No key was found for #{full_key}" puts "# No key was found for #{key}"
else else
puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key['key']) puts GitlabKeys.key_line("key-#{authorized_key['id']}", authorized_key['key'])
end end
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# the right options. # the right options.
# #
# Ex. # Ex.
# bin/gitlab-shell-authorized-principals-check <key-id> <principal1> [<principal2>...] # bin/gitlab-shell-authorized-keys-check <key-id> <principal1> [<principal2>...]
# #
# Returns one line per principal passed in, e.g.: # 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 {PRINCIPAL}
...@@ -23,9 +23,9 @@ key_id = ARGV[0] ...@@ -23,9 +23,9 @@ key_id = ARGV[0]
abort '# No key_id provided' if key_id.nil? || key_id == '' abort '# No key_id provided' if key_id.nil? || key_id == ''
principals = ARGV[1..-1] principals = ARGV[1..-1]
principals.each do |principal| principals.each { |principal|
abort '# An invalid principal was provided' if principal.nil? || principal == '' abort '# An invalid principal was provided' if principal.nil? || principal == ''
end }
require_relative '../lib/gitlab_init' require_relative '../lib/gitlab_init'
require_relative '../lib/gitlab_net' require_relative '../lib/gitlab_net'
......
...@@ -4,15 +4,15 @@ ...@@ -4,15 +4,15 @@
# will be processed properly. # will be processed properly.
refs = $stdin.read refs = $stdin.read
gl_id = ENV.delete('GL_ID') key_id = ENV.delete('GL_ID')
gl_repository = ENV['GL_REPOSITORY'] gl_repository = ENV['GL_REPOSITORY']
repo_path = Dir.pwd repo_path = Dir.pwd
require_relative '../lib/gitlab_custom_hook' require_relative '../lib/gitlab_custom_hook'
require_relative '../lib/gitlab_post_receive' require_relative '../lib/gitlab_post_receive'
if GitlabPostReceive.new(gl_repository, repo_path, gl_id, refs).exec && if GitlabPostReceive.new(gl_repository, repo_path, key_id, refs).exec &&
GitlabCustomHook.new(repo_path, gl_id).post_receive(refs) GitlabCustomHook.new(repo_path, key_id).post_receive(refs)
exit 0 exit 0
else else
exit 1 exit 1
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# will be processed properly. # will be processed properly.
refs = $stdin.read refs = $stdin.read
gl_id = ENV.delete('GL_ID') key_id = ENV.delete('GL_ID')
protocol = ENV.delete('GL_PROTOCOL') protocol = ENV.delete('GL_PROTOCOL')
repo_path = Dir.pwd repo_path = Dir.pwd
gl_repository = ENV['GL_REPOSITORY'] gl_repository = ENV['GL_REPOSITORY']
...@@ -23,8 +23,8 @@ require_relative '../lib/gitlab_net' ...@@ -23,8 +23,8 @@ require_relative '../lib/gitlab_net'
# last so that it only runs if everything else succeeded. On post-receive on the # last so that it only runs if everything else succeeded. On post-receive on the
# other hand, we run GitlabPostReceive first because the push is already done # other hand, we run GitlabPostReceive first because the push is already done
# and we don't want to skip it if the custom hook fails. # and we don't want to skip it if the custom hook fails.
if GitlabAccess.new(gl_repository, repo_path, gl_id, refs, protocol).exec && if GitlabAccess.new(gl_repository, repo_path, key_id, refs, protocol).exec &&
GitlabCustomHook.new(repo_path, gl_id).pre_receive(refs) && GitlabCustomHook.new(repo_path, key_id).pre_receive(refs) &&
increase_reference_counter(gl_repository, repo_path) increase_reference_counter(gl_repository, repo_path)
exit 0 exit 0
else else
......
...@@ -7,11 +7,11 @@ ref_name = ARGV[0] ...@@ -7,11 +7,11 @@ ref_name = ARGV[0]
old_value = ARGV[1] old_value = ARGV[1]
new_value = ARGV[2] new_value = ARGV[2]
repo_path = Dir.pwd repo_path = Dir.pwd
gl_id = ENV.delete('GL_ID') key_id = ENV.delete('GL_ID')
require_relative '../lib/gitlab_custom_hook' require_relative '../lib/gitlab_custom_hook'
if GitlabCustomHook.new(repo_path, gl_id).update(ref_name, old_value, new_value) if GitlabCustomHook.new(repo_path, key_id).update(ref_name, old_value, new_value)
exit 0 exit 0
else else
exit 1 exit 1
......
require_relative 'action/base'
require_relative 'action/gitaly'
require_relative 'action/git_lfs_authenticate'
require_relative 'action/api_2fa_recovery'
module Action
end
require_relative '../action'
require_relative '../gitlab_logger'
module Action
class API2FARecovery < Base
def initialize(actor)
@actor = actor
end
def execute(_, _)
recover
end
private
attr_reader :actor
def continue?(question)
puts "#{question} (yes/no)"
STDOUT.flush # Make sure the question gets output before we wait for input
response = STDIN.gets.chomp
puts '' # Add a buffer in the output
response == 'yes'
end
def recover
continue = continue?(
"Are you sure you want to generate new two-factor recovery codes?\n" \
"Any existing recovery codes you saved will be invalidated."
)
unless continue
puts 'New recovery codes have *not* been generated. Existing codes will remain valid.'
return
end
resp = api.two_factor_recovery_codes(actor)
if resp['success']
codes = resp['recovery_codes'].join("\n")
$logger.info('API 2FA recovery success', user: actor.log_username)
puts "Your two-factor authentication recovery codes are:\n\n" \
"#{codes}\n\n" \
"During sign in, use one of the codes above when prompted for\n" \
"your two-factor code. Then, visit your Profile Settings and add\n" \
"a new device so you do not lose access to your account again."
true
else
$logger.info('API 2FA recovery error', user: actor.log_username)
puts "An error occurred while trying to generate new recovery codes.\n" \
"#{resp['message']}"
end
end
end
end
require 'json'
require_relative '../gitlab_config'
require_relative '../gitlab_net'
require_relative '../gitlab_metrics'
module Action
class Base
def initialize
raise NotImplementedError
end
def self.create_from_json(_)
raise NotImplementedError
end
private
def config
@config ||= GitlabConfig.new
end
def api
@api ||= GitlabNet.new
end
end
end
require_relative '../action'
require_relative '../gitlab_logger'
module Action
class GitLFSAuthenticate < Base
def initialize(actor, repo_name)
@actor = actor
@repo_name = repo_name
end
def execute(_, _)
GitlabMetrics.measure('lfs-authenticate') do
$logger.info('Processing LFS authentication', user: actor.log_username)
lfs_access = api.lfs_authenticate(actor, repo_name)
return unless lfs_access
puts lfs_access.authentication_payload
end
true
end
private
attr_reader :actor, :repo_name
end
end
require_relative '../action'
require_relative '../gitlab_logger'
require_relative '../gitlab_net'
module Action
class Gitaly < Base
REPOSITORY_PATH_NOT_PROVIDED = "Repository path not provided. Please make sure you're using GitLab v8.10 or later.".freeze
MIGRATED_COMMANDS = {
'git-upload-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-pack'),
'git-upload-archive' => File.join(ROOT_PATH, 'bin', 'gitaly-upload-archive'),
'git-receive-pack' => File.join(ROOT_PATH, 'bin', 'gitaly-receive-pack')
}.freeze
def initialize(actor, gl_repository, gl_username, git_protocol, repository_path, gitaly)
@actor = actor
@gl_repository = gl_repository
@gl_username = gl_username
@git_protocol = git_protocol
@repository_path = repository_path
@gitaly = gitaly
end
def self.create_from_json(actor, json)
new(actor,
json['gl_repository'],
json['gl_username'],
json['git_protocol'],
json['repository_path'],
json['gitaly'])
end
def execute(command, args)
raise ArgumentError, REPOSITORY_PATH_NOT_PROVIDED unless repository_path
raise InvalidRepositoryPathError unless valid_repository?
$logger.info('Performing Gitaly command', user: actor.log_username)
process(command, args)
end
private
attr_reader :actor, :gl_repository, :gl_username, :repository_path, :gitaly
def git_protocol
@git_protocol || ENV['GIT_PROTOCOL'] # TODO: tidy this up
end
def process(command, args)
executable = command
args = [repository_path]
if MIGRATED_COMMANDS.key?(executable) && gitaly
executable = MIGRATED_COMMANDS[executable]
gitaly_address = gitaly['address']
args = [gitaly_address, JSON.dump(gitaly_request)]
end
args_string = [File.basename(executable), *args].join(' ')
$logger.info('executing git command', command: args_string, user: actor.log_username)
exec_cmd(executable, *args)
end
def exec_cmd(*args)
env = exec_env
env['GITALY_TOKEN'] = gitaly['token'] if gitaly && gitaly.include?('token')
if git_trace_available?
env.merge!(
'GIT_TRACE' => config.git_trace_log_file,
'GIT_TRACE_PACKET' => config.git_trace_log_file,
'GIT_TRACE_PERFORMANCE' => config.git_trace_log_file
)
end
# We use 'chdir: ROOT_PATH' to let the next executable know where config.yml is.
Kernel.exec(env, *args, unsetenv_others: true, chdir: ROOT_PATH)
end
def exec_env
{
'HOME' => ENV['HOME'],
'PATH' => ENV['PATH'],
'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
'LANG' => ENV['LANG'],
'GL_ID' => actor.identifier,
'GL_PROTOCOL' => GitlabNet::GL_PROTOCOL,
'GL_REPOSITORY' => gl_repository,
'GL_USERNAME' => gl_username
}
end
def gitaly_request
# The entire gitaly_request hash should be built in gitlab-ce and passed
# on as-is. For now we build a fake one on the spot.
{
'repository' => gitaly['repository'],
'gl_repository' => gl_repository,
'gl_id' => actor.identifier,
'gl_username' => gl_username,
'git_protocol' => git_protocol
}
end
def valid_repository?
File.absolute_path(repository_path) == repository_path
end
def git_trace_available?
return false unless config.git_trace_log_file
if Pathname(config.git_trace_log_file).relative?
$logger.warn('git trace log path must be absolute, ignoring', git_trace_log_file: config.git_trace_log_file)
return false
end
begin
File.open(config.git_trace_log_file, 'a') { nil }
return true
rescue => ex
$logger.warn('Failed to open git trace log file', git_trace_log_file: config.git_trace_log_file, error: ex.to_s)
return false
end
end
end
end
require_relative 'actor/base'
require_relative 'actor/key'
require_relative 'actor/user'
require_relative 'actor/username'
module Actor
class UnsupportedActorError < StandardError; end
def self.new_from(str, audit_usernames: false)
case str
when Key.id_regex
Key.from(str, audit_usernames: audit_usernames)
when User.id_regex
User.from(str, audit_usernames: audit_usernames)
when Username.id_regex
Username.from(str, audit_usernames: audit_usernames)
else
raise UnsupportedActorError
end
end
end
module Actor
class Base
attr_reader :id
def initialize(id, audit_usernames: false)
@id = id
@audit_usernames = audit_usernames
end
def self.from(str, audit_usernames: false)
new(str.gsub(/#{identifier_prefix}-/, ''), audit_usernames: audit_usernames)
end
def self.identifier_key
raise NotImplementedError
end
def self.identifier_prefix
raise NotImplementedError
end
def self.id_regex
raise NotImplementedError
end
def username
raise NotImplementedError
end
def identifier
"#{self.class.identifier_prefix}-#{id}"
end
def identifier_key
self.class.identifier_key
end
def log_username
audit_usernames? ? username : "#{label} with identifier #{identifier}"
end
private
attr_reader :audit_usernames
alias audit_usernames? audit_usernames
def klass_name
self.class.to_s.split('::')[-1]
end
def label
klass_name.downcase
end
end
end
require_relative 'base'
require_relative '../gitlab_net'
module Actor
class Key < Base
ANONYMOUS_USER = 'Anonymous'.freeze
alias key_id id
def self.identifier_prefix
'key'.freeze
end
def self.identifier_key
'key_id'.freeze
end
def self.id_regex
/\Akey\-\d+\Z/
end
def username
@username ||= begin
user = GitlabNet.new.discover(self)
user ? "@#{user['username']}" : ANONYMOUS_USER
end
end
end
end
require_relative 'base'
module Actor
class User < Base
alias username identifier
def self.identifier_prefix
'user'.freeze
end
def self.identifier_key
'user_id'.freeze
end
def self.id_regex
/\Auser\-\d+\Z/
end
end
end
require_relative 'base'
require_relative 'key'
module Actor
class Username < Key
def self.identifier_prefix
'username'.freeze
end
def self.identifier_key
'username'.freeze
end
def self.id_regex
/\Ausername\-[a-z0-9-]+\z/
end
private
# Override Base#label
def label
'user'
end
end
end
class UnknownError < StandardError; end
class AccessDeniedError < StandardError; end
class InvalidRepositoryPathError < StandardError; end
class DisallowedCommandError < StandardError; end
require 'json'
require_relative 'errors'
require_relative 'actor'
require_relative 'gitlab_init' require_relative 'gitlab_init'
require_relative 'gitlab_net' require_relative 'gitlab_net'
require_relative 'gitlab_access_status'
require_relative 'names_helper' require_relative 'names_helper'
require_relative 'gitlab_metrics' require_relative 'gitlab_metrics'
require_relative 'object_dirs_helper' require_relative 'object_dirs_helper'
require 'json'
class GitlabAccess class GitlabAccess
class AccessDeniedError < StandardError; end
include NamesHelper include NamesHelper
def initialize(gl_repository, repo_path, gl_id, changes, protocol) attr_reader :config, :gl_repository, :repo_path, :changes, :protocol
def initialize(gl_repository, repo_path, actor, changes, protocol)
@config = GitlabConfig.new
@gl_repository = gl_repository @gl_repository = gl_repository
@repo_path = repo_path.strip @repo_path = repo_path.strip
@gl_id = gl_id @actor = actor
@changes = changes.lines @changes = changes.lines
@protocol = protocol @protocol = protocol
end end
def exec def exec
GitlabMetrics.measure('check-access:git-receive-pack') do status = GitlabMetrics.measure('check-access:git-receive-pack') do
api.check_access('git-receive-pack', gl_repository, repo_path, actor, changes, protocol, env: ObjectDirsHelper.all_attributes.to_json) api.check_access('git-receive-pack', @gl_repository, @repo_path, @actor, @changes, @protocol, env: ObjectDirsHelper.all_attributes.to_json)
end end
raise AccessDeniedError, status.message unless status.allowed?
true true
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"
...@@ -32,19 +38,9 @@ class GitlabAccess ...@@ -32,19 +38,9 @@ class GitlabAccess
false false
end end
private protected
attr_reader :gl_repository, :repo_path, :gl_id, :changes, :protocol
def api def api
@api ||= GitlabNet.new GitlabNet.new
end
def config
@config ||= GitlabConfig.new
end
def actor
@actor ||= Actor.new_from(gl_id, audit_usernames: config.audit_usernames)
end end
end end
require 'json'
class GitAccessStatus
attr_reader :message, :gl_repository, :gl_id, :gl_username, :repository_path, :gitaly, :git_protocol
def initialize(status, message, gl_repository:, gl_id:, gl_username:, repository_path:, gitaly:, git_protocol:)
@status = status
@message = message
@gl_repository = gl_repository
@gl_id = gl_id
@gl_username = gl_username
@repository_path = repository_path
@gitaly = gitaly
@git_protocol = git_protocol
end
def self.create_from_json(json)
values = JSON.parse(json)
new(values["status"],
values["message"],
gl_repository: values["gl_repository"],
gl_id: values["gl_id"],
gl_username: values["gl_username"],
repository_path: values["repository_path"],
gitaly: values["gitaly"],
git_protocol: values["git_protocol"])
end
def allowed?
@status
end
end
...@@ -5,9 +5,9 @@ require_relative 'gitlab_metrics' ...@@ -5,9 +5,9 @@ require_relative 'gitlab_metrics'
class GitlabCustomHook class GitlabCustomHook
attr_reader :vars, :config attr_reader :vars, :config
def initialize(repo_path, gl_id) def initialize(repo_path, key_id)
@repo_path = repo_path @repo_path = repo_path
@vars = { 'GL_ID' => gl_id } @vars = { 'GL_ID' => key_id }
@config = GitlabConfig.new @config = GitlabConfig.new
end end
......
...@@ -9,7 +9,6 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength ...@@ -9,7 +9,6 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
attr_accessor :auth_file, :key attr_accessor :auth_file, :key
# TODO: whatever is not a great name
def self.command(whatever) def self.command(whatever)
"#{ROOT_PATH}/bin/gitlab-shell #{whatever}" "#{ROOT_PATH}/bin/gitlab-shell #{whatever}"
end end
...@@ -22,7 +21,6 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength ...@@ -22,7 +21,6 @@ class GitlabKeys # rubocop:disable Metrics/ClassLength
command(key_id) command(key_id)
end end
# TODO: whatever is not a great name
def self.whatever_line(command, trailer) def self.whatever_line(command, trailer)
"command=\"#{command}\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #{trailer}" "command=\"#{command}\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty #{trailer}"
end end
......
require 'net/http'
require 'openssl'
require 'json' require 'json'
require_relative 'errors' require_relative 'gitlab_config'
require_relative 'gitlab_logger' require_relative 'gitlab_logger'
require_relative 'gitlab_access' require_relative 'gitlab_access'
require_relative 'gitlab_lfs_authentication' require_relative 'gitlab_lfs_authentication'
require_relative 'httpunix'
require_relative 'http_helper' require_relative 'http_helper'
require_relative 'action'
class GitlabNet class GitlabNet # rubocop:disable Metrics/ClassLength
include HTTPHelper include HTTPHelper
class ApiUnreachableError < StandardError; end
class NotFound < StandardError; end
CHECK_TIMEOUT = 5 CHECK_TIMEOUT = 5
GL_PROTOCOL = 'ssh'.freeze
API_INACCESSIBLE_ERROR = 'API is not accessible'.freeze
def check_access(cmd, gl_repository, repo, actor, changes, protocol = GL_PROTOCOL, env: {}) def check_access(cmd, gl_repository, repo, who, changes, protocol, env: {})
changes = changes.join("\n") unless changes.is_a?(String) changes = changes.join("\n") unless changes.is_a?(String)
params = { params = {
...@@ -26,27 +29,56 @@ class GitlabNet ...@@ -26,27 +29,56 @@ class GitlabNet
env: env env: env
} }
params[actor.identifier_key.to_sym] = actor.id who_sym, _, who_v = self.class.parse_who(who)
params[who_sym] = who_v
resp = post("#{internal_api_endpoint}/allowed", params) url = "#{internal_api_endpoint}/allowed"
resp = post(url, params)
determine_action(actor, resp) if resp.code == '200'
GitAccessStatus.create_from_json(resp.body)
else
GitAccessStatus.new(false,
'API is not accessible',
gl_repository: nil,
gl_id: nil,
gl_username: nil,
repository_path: nil,
gitaly: nil,
git_protocol: nil)
end
end end
def discover(actor) def discover(who)
resp = get("#{internal_api_endpoint}/discover?#{actor.identifier_key}=#{actor.id}") _, who_k, who_v = self.class.parse_who(who)
JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
rescue JSON::ParserError, ApiUnreachableError resp = get("#{internal_api_endpoint}/discover?#{who_k}=#{who_v}")
nil
JSON.parse(resp.body) rescue nil
end end
def lfs_authenticate(actor, repo) def lfs_authenticate(gl_id, repo)
params = { project: sanitize_path(repo) } id_sym, _, id = self.class.parse_who(gl_id)
params[actor.identifier_key.to_sym] = actor.id
if id_sym == :key_id
params = {
project: sanitize_path(repo),
key_id: id
}
elsif id_sym == :user_id
params = {
project: sanitize_path(repo),
user_id: id
}
else
raise ArgumentError, "lfs_authenticate() got unsupported GL_ID='#{gl_id}'!"
end
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 if resp.code == '200'
GitlabLfsAuthentication.build_from_json(resp.body)
end
end end
def broadcast_message def broadcast_message
...@@ -61,7 +93,11 @@ class GitlabNet ...@@ -61,7 +93,11 @@ class GitlabNet
url += "&gl_repository=#{URI.escape(gl_repository)}" if gl_repository url += "&gl_repository=#{URI.escape(gl_repository)}" if gl_repository
resp = get(url) resp = get(url)
resp.code == HTTP_SUCCESS ? JSON.parse(resp.body) : [] if resp.code == '200'
JSON.parse(resp.body)
else
[]
end
rescue rescue
[] []
end end
...@@ -70,17 +106,19 @@ class GitlabNet ...@@ -70,17 +106,19 @@ class GitlabNet
get("#{internal_api_endpoint}/check", options: { read_timeout: CHECK_TIMEOUT }) get("#{internal_api_endpoint}/check", options: { read_timeout: CHECK_TIMEOUT })
end end
def authorized_key(full_key) def authorized_key(key)
resp = get("#{internal_api_endpoint}/authorized_keys?key=#{URI.escape(full_key, '+/=')}") resp = get("#{internal_api_endpoint}/authorized_keys?key=#{URI.escape(key, '+/=')}")
JSON.parse(resp.body) if resp.code == HTTP_SUCCESS JSON.parse(resp.body) if resp.code == "200"
rescue rescue
nil nil
end end
def two_factor_recovery_codes(actor) def two_factor_recovery_codes(gl_id)
params = { actor.identifier_key.to_sym => actor.id } id_sym, _, id = self.class.parse_who(gl_id)
resp = post("#{internal_api_endpoint}/two_factor_recovery_codes", params)
JSON.parse(resp.body) if resp.code == HTTP_SUCCESS resp = post("#{internal_api_endpoint}/two_factor_recovery_codes", id_sym => id)
JSON.parse(resp.body) if resp.code == '200'
rescue rescue
{} {}
end end
...@@ -89,50 +127,51 @@ class GitlabNet ...@@ -89,50 +127,51 @@ class GitlabNet
params = { gl_repository: gl_repository, project: repo_path } params = { gl_repository: gl_repository, project: repo_path }
resp = post("#{internal_api_endpoint}/notify_post_receive", params) resp = post("#{internal_api_endpoint}/notify_post_receive", params)
resp.code == HTTP_SUCCESS resp.code == '200'
rescue rescue
false false
end end
def post_receive(gl_repository, actor, changes) def post_receive(gl_repository, identifier, changes)
params = { gl_repository: gl_repository, identifier: actor.identifier, changes: changes } params = {
gl_repository: gl_repository,
identifier: identifier,
changes: changes
}
resp = post("#{internal_api_endpoint}/post_receive", params) resp = post("#{internal_api_endpoint}/post_receive", params)
raise NotFoundError if resp.code == HTTP_NOT_FOUND
JSON.parse(resp.body) if resp.code == HTTP_SUCCESS raise NotFound if resp.code == '404'
JSON.parse(resp.body) if resp.code == '200'
end end
def pre_receive(gl_repository) def pre_receive(gl_repository)
resp = post("#{internal_api_endpoint}/pre_receive", gl_repository: gl_repository) resp = post("#{internal_api_endpoint}/pre_receive", gl_repository: gl_repository)
raise NotFoundError if resp.code == HTTP_NOT_FOUND
JSON.parse(resp.body) if resp.code == HTTP_SUCCESS
end
private raise NotFound if resp.code == '404'
def sanitize_path(repo) JSON.parse(resp.body) if resp.code == '200'
repo.delete("'")
end end
def determine_action(actor, resp) def self.parse_who(who)
json = JSON.parse(resp.body) if who.start_with?("key-")
message = json['message'] value = who.gsub("key-", "")
raise ArgumentError, "who='#{who}' is invalid!" unless value =~ /\A[0-9]+\z/
case resp.code [:key_id, 'key_id', value]
when HTTP_SUCCESS elsif who.start_with?("user-")
# TODO: This raise can be removed once internal API can respond with correct value = who.gsub("user-", "")
# HTTP status codes, instead of relying upon parsing the body and raise ArgumentError, "who='#{who}' is invalid!" unless value =~ /\A[0-9]+\z/
# accessing the 'status' key. [:user_id, 'user_id', value]
raise AccessDeniedError, message unless json['status'] elsif who.start_with?("username-")
[:username, 'username', who.gsub("username-", "")]
Action::Gitaly.create_from_json(actor, json)
when HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
raise AccessDeniedError, message
else else
raise UnknownError, "#{API_INACCESSIBLE_ERROR}: #{message}" raise ArgumentError, "who='#{who}' is invalid!"
end
end end
rescue JSON::ParserError
raise UnknownError, API_INACCESSIBLE_ERROR protected
def sanitize_path(repo)
repo.delete("'")
end end
end end
...@@ -8,18 +8,20 @@ require 'securerandom' ...@@ -8,18 +8,20 @@ require 'securerandom'
class GitlabPostReceive class GitlabPostReceive
include NamesHelper include NamesHelper
def initialize(gl_repository, repo_path, gl_id, changes) attr_reader :config, :gl_repository, :repo_path, :changes, :jid
def initialize(gl_repository, repo_path, actor, changes)
@config = GitlabConfig.new @config = GitlabConfig.new
@gl_repository = gl_repository @gl_repository = gl_repository
@repo_path = repo_path.strip @repo_path = repo_path.strip
@gl_id = gl_id @actor = actor
@changes = changes @changes = changes
@jid = SecureRandom.hex(12) @jid = SecureRandom.hex(12)
end end
def exec def exec
response = GitlabMetrics.measure("post-receive") do response = GitlabMetrics.measure("post-receive") do
api.post_receive(gl_repository, actor, changes) api.post_receive(gl_repository, @actor, changes)
end end
return false unless response return false unless response
...@@ -33,18 +35,12 @@ class GitlabPostReceive ...@@ -33,18 +35,12 @@ class GitlabPostReceive
false false
end end
private protected
attr_reader :config, :gl_repository, :repo_path, :gl_id, :changes, :jid
def api def api
@api ||= GitlabNet.new @api ||= GitlabNet.new
end end
def actor
@actor ||= Actor.new_from(gl_id, audit_usernames: config.audit_usernames)
end
def print_merge_request_links(merge_request_urls) def print_merge_request_links(merge_request_urls)
return if merge_request_urls.empty? return if merge_request_urls.empty?
puts puts
...@@ -104,6 +100,8 @@ class GitlabPostReceive ...@@ -104,6 +100,8 @@ class GitlabPostReceive
puts "=" * total_width puts "=" * total_width
end end
private
def parse_broadcast_msg(msg, text_length) def parse_broadcast_msg(msg, text_length)
msg ||= "" msg ||= ""
# just return msg if shorter than or equal to text length # just return msg if shorter than or equal to text length
......
This diff is collapsed.
require 'net/http'
require 'openssl'
require_relative 'gitlab_config'
require_relative 'httpunix'
module HTTPHelper module HTTPHelper
READ_TIMEOUT = 300 READ_TIMEOUT = 300
HTTP_SUCCESS = '200'.freeze
HTTP_MULTIPLE_CHOICES = '300'.freeze
HTTP_UNAUTHORIZED = '401'.freeze
HTTP_NOT_FOUND = '404'.freeze
HTTP_SUCCESS_LIKE = [HTTP_SUCCESS, HTTP_MULTIPLE_CHOICES].freeze
class ApiUnreachableError < StandardError; end
class NotFoundError < StandardError; end
protected protected
...@@ -91,7 +76,7 @@ module HTTPHelper ...@@ -91,7 +76,7 @@ module HTTPHelper
$logger.info('finished HTTP request', method: method.to_s.upcase, url: url, duration: Time.new - start_time) $logger.info('finished HTTP request', method: method.to_s.upcase, url: url, duration: Time.new - start_time)
end end
if HTTP_SUCCESS_LIKE.include?(response.code) if response.code == "200"
$logger.debug('Received response', code: response.code, body: response.body) $logger.debug('Received response', code: response.code, body: response.body)
else else
$logger.error('Call failed', method: method.to_s.upcase, url: url, code: response.code, body: response.body) $logger.error('Call failed', method: method.to_s.upcase, url: url, code: response.code, body: response.body)
...@@ -124,7 +109,7 @@ module HTTPHelper ...@@ -124,7 +109,7 @@ module HTTPHelper
end end
def secret_token def secret_token
@secret_token ||= File.read(config.secret_file) @secret_token ||= File.read config.secret_file
end end
def read_timeout def read_timeout
......
require_relative '../spec_helper'
require_relative '../../lib/action/api_2fa_recovery'
describe Action::API2FARecovery do
let(:key_id) { '1' }
let(:actor) { Actor::Key.new(key_id) }
let(:username) { 'testuser' }
let(:discover_payload) { { 'username' => username } }
let(:api) { double(GitlabNet) }
before do
allow(GitlabNet).to receive(:new).and_return(api)
allow(api).to receive(:discover).with(actor).and_return(discover_payload)
end
subject do
described_class.new(actor)
end
describe '#execute' do
context 'with an invalid repsonse' do
it 'returns nil' do
expect($stdin).to receive(:gets).and_return("meh\n")
expect do
expect(subject.execute(nil, nil)).to be_nil
end.to output(/New recovery codes have \*not\* been generated/).to_stdout
end
end
context 'with a negative response' do
before do
expect(subject).to receive(:continue?).and_return(false)
end
it 'returns nil' do
expect do
expect(subject.execute(nil, nil)).to be_nil
end.to output(/New recovery codes have \*not\* been generated/).to_stdout
end
end
context 'with an affirmative response' do
let(:recovery_codes) { %w{ 8dfe0f433208f40b289904c6072e4a72 c33cee7fd0a73edb56e61b785e49af03 } }
before do
expect(subject).to receive(:continue?).and_return(true)
expect(api).to receive(:two_factor_recovery_codes).with(actor).and_return(response)
end
context 'with a unsuccessful response' do
let(:response) { { 'success' => false } }
it 'puts error message to stdout' do
expect do
expect(subject.execute(nil, nil)).to be_falsey
end.to output(/An error occurred while trying to generate new recovery codes/).to_stdout
end
end
context 'with a successful response' do
let(:response) { { 'success' => true, 'recovery_codes' => recovery_codes } }
it 'puts information message including recovery codes to stdout' do
expect do
expect(subject.execute(nil, nil)).to be_truthy
end.to output(Regexp.new(recovery_codes.join("\n"))).to_stdout
end
end
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/action/base'
describe Action::Base do
describe '.create_from_json' do
it 'raises a NotImplementedError exeption' do
expect do
described_class.create_from_json('nomatter')
end.to raise_error(NotImplementedError)
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/action/git_lfs_authenticate'
describe Action::GitLFSAuthenticate do
let(:key_id) { '1' }
let(:repo_name) { 'gitlab-ci.git' }
let(:actor) { Actor::Key.new(key_id) }
let(:username) { 'testuser' }
let(:discover_payload) { { 'username' => username } }
let(:api) { double(GitlabNet) }
before do
allow(GitlabNet).to receive(:new).and_return(api)
allow(api).to receive(:discover).with(actor).and_return(discover_payload)
end
subject do
described_class.new(actor, repo_name)
end
describe '#execute' do
context 'when response from API is not a success' do
before do
expect(api).to receive(:lfs_authenticate).with(actor, repo_name).and_return(nil)
end
it 'returns nil' do
expect(subject.execute(nil, nil)).to be_nil
end
end
context 'when response from API is a success' do
let(:username) { 'testuser' }
let(:lfs_token) { '1234' }
let(:repository_http_path) { "/tmp/#{repo_name}" }
let(:gitlab_lfs_authentication) { GitlabLfsAuthentication.new(username, lfs_token, repository_http_path) }
before do
expect(api).to receive(:lfs_authenticate).with(actor, repo_name).and_return(gitlab_lfs_authentication)
end
it 'puts payload to stdout' do
expect($stdout).to receive(:puts).with('{"header":{"Authorization":"Basic dGVzdHVzZXI6MTIzNA=="},"href":"/tmp/gitlab-ci.git/info/lfs/"}')
expect(subject.execute(nil, nil)).to be_truthy
end
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/action/gitaly'
describe Action::Gitaly do
let(:git_trace_log_file_valid) { '/tmp/git_trace_performance.log' }
let(:git_trace_log_file_invalid) { "/bleep-bop#{git_trace_log_file_valid}" }
let(:git_trace_log_file_relative) { "..#{git_trace_log_file_valid}" }
let(:key_id) { '1' }
let(:key_str) { 'key-1' }
let(:key) { Actor::Key.new(key_id) }
let(:gl_repository) { 'project-1' }
let(:gl_username) { 'testuser' }
let(:git_protocol) { 'version=2' }
let(:tmp_repos_path) { File.join(ROOT_PATH, 'tmp', 'repositories') }
let(:repo_name) { 'gitlab-ci.git' }
let(:repository_path) { File.join(tmp_repos_path, repo_name) }
let(:gitaly_address) { 'unix:gitaly.socket' }
let(:gitaly_token) { '123456' }
let(:gitaly) do
{
'repository' => { 'relative_path' => repo_name, 'storage_name' => 'default' },
'address' => gitaly_address,
'token' => gitaly_token
}
end
describe '.create_from_json' do
it 'returns an instance of Action::Gitaly' do
json = {
"gl_repository" => gl_repository,
"gl_username" => gl_username,
"repository_path" => repository_path,
"gitaly" => gitaly
}
expect(described_class.create_from_json(key_id, json)).to be_instance_of(Action::Gitaly)
end
end
subject do
described_class.new(key, gl_repository, gl_username, git_protocol, repository_path, gitaly)
end
describe '#execute' do
let(:args) { [ repository_path ] }
let(:base_exec_env) do
{
'HOME' => ENV['HOME'],
'PATH' => ENV['PATH'],
'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
'LANG' => ENV['LANG'],
'GL_ID' => key_str,
'GL_PROTOCOL' => GitlabNet::GL_PROTOCOL,
'GL_REPOSITORY' => gl_repository,
'GL_USERNAME' => gl_username,
'GITALY_TOKEN' => gitaly_token,
}
end
let(:with_trace_exec_env) do
base_exec_env.merge({
'GIT_TRACE' => git_trace_log_file,
'GIT_TRACE_PACKET' => git_trace_log_file,
'GIT_TRACE_PERFORMANCE' => git_trace_log_file
})
end
let(:gitaly_request) do
{
'repository' => gitaly['repository'],
'gl_repository' => gl_repository,
'gl_id' => key_str,
'gl_username' => gl_username,
'git_protocol' => git_protocol
}
end
context 'for migrated commands' do
context 'such as git-upload-pack' do
let(:git_trace_log_file) { nil }
let(:command) { 'git-upload-pack' }
before do
allow_any_instance_of(GitlabConfig).to receive(:git_trace_log_file).and_return(git_trace_log_file)
end
context 'with an invalid config.git_trace_log_file' do
let(:git_trace_log_file) { git_trace_log_file_invalid }
it 'returns true' do
expect(Kernel).to receive(:exec).with(
base_exec_env,
described_class::MIGRATED_COMMANDS[command],
gitaly_address,
JSON.dump(gitaly_request),
unsetenv_others: true,
chdir: ROOT_PATH
).and_return(true)
expect(subject.execute(command, args)).to be_truthy
end
end
context 'with n relative config.git_trace_log_file' do
let(:git_trace_log_file) { git_trace_log_file_relative }
it 'returns true' do
expect(Kernel).to receive(:exec).with(
base_exec_env,
described_class::MIGRATED_COMMANDS[command],
gitaly_address,
JSON.dump(gitaly_request),
unsetenv_others: true,
chdir: ROOT_PATH
).and_return(true)
expect(subject.execute(command, args)).to be_truthy
end
end
context 'with a valid config.git_trace_log_file' do
let(:git_trace_log_file) { git_trace_log_file_valid }
it 'returns true' do
expect(Kernel).to receive(:exec).with(
with_trace_exec_env,
described_class::MIGRATED_COMMANDS[command],
gitaly_address,
JSON.dump(gitaly_request),
unsetenv_others: true,
chdir: ROOT_PATH
).and_return(true)
expect(subject.execute(command, args)).to be_truthy
end
end
end
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/actor/base'
describe Actor::Base do
describe '.identifier_key' do
it 'raises a NotImplementedError exception' do
expect do
described_class.identifier_key
end.to raise_error(NotImplementedError)
end
end
describe '.identifier_prefix' do
it 'raises a NotImplementedError exception' do
expect do
described_class.identifier_prefix
end.to raise_error(NotImplementedError)
end
end
describe '.id_regex' do
it 'raises a NotImplementedError exception' do
expect do
described_class.id_regex
end.to raise_error(NotImplementedError)
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/actor/key'
describe Actor::Key do
let(:key_id) { '1' }
let(:username) { 'testuser' }
let(:api) { double(GitlabNet) }
let(:discover_payload) { { 'username' => username } }
let(:audit_usernames) { nil }
before do
allow(GitlabNet).to receive(:new).and_return(api)
allow(api).to receive(:discover).with(subject).and_return(discover_payload)
end
describe '.from' do
it 'returns an instance of Actor::Key' do
expect(described_class.from('key-1')).to be_a(Actor::Key)
end
it 'has a key_id == 1' do
expect(described_class.from('key-1').key_id).to eq '1'
end
end
describe '.identifier_prefix' do
it "returns 'key'" do
expect(described_class.identifier_prefix).to eql 'key'
end
end
describe '.identifier_key' do
it "returns 'key_id'" do
expect(described_class.identifier_key).to eql 'key_id'
end
end
subject { described_class.new(key_id, audit_usernames: audit_usernames) }
describe '#username' do
context 'with a valid user' do
it "returns '@testuser'" do
expect(subject.username).to eql '@testuser'
end
end
context 'without a valid user' do
let(:discover_payload) { nil }
it "returns 'Anonymous'" do
expect(subject.username).to eql 'Anonymous'
end
end
end
describe '#identifier' do
it "returns 'key-1'" do
expect(subject.identifier).to eql 'key-1'
end
end
describe '#log_username' do
context 'when audit_usernames is true' do
let(:audit_usernames) { true }
it "returns 'testuser'" do
expect(subject.log_username).to eql '@testuser'
end
end
context 'when audit_usernames is false' do
let(:audit_usernames) { false }
it "returns 'key with identifier key-1'" do
expect(subject.log_username).to eql 'key with identifier key-1'
end
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/actor/user'
describe Actor::User do
let(:user_id) { '1' }
let(:username) { 'testuser' }
let(:audit_usernames) { nil }
describe '.from' do
it 'returns an instance of Actor::User' do
expect(described_class.from('user-1')).to be_a(Actor::User)
end
it 'has an id == 1' do
expect(described_class.from('user-1').id).to eq '1'
end
end
describe '.identifier_prefix' do
it "returns 'user'" do
expect(described_class.identifier_prefix).to eql 'user'
end
end
describe '.identifier_key' do
it "returns 'user_id'" do
expect(described_class.identifier_key).to eql 'user_id'
end
end
subject { described_class.new(user_id, audit_usernames: audit_usernames) }
describe '#username' do
it "returns 'user-1'" do
expect(subject.username).to eql 'user-1'
end
end
describe '#identifier' do
it "returns 'user-1'" do
expect(subject.identifier).to eql 'user-1'
end
end
describe '#log_username' do
context 'when audit_usernames is true' do
let(:audit_usernames) { true }
it "returns 'user-1'" do
expect(subject.log_username).to eql 'user-1'
end
end
context 'when audit_usernames is false' do
let(:audit_usernames) { false }
it "returns 'user with identifier user-1'" do
expect(subject.log_username).to eql 'user with identifier user-1'
end
end
end
end
require_relative '../spec_helper'
require_relative '../../lib/actor/username'
describe Actor::Username do
let(:username) { 'testuser' }
let(:api) { double(GitlabNet) }
let(:discover_payload) { { 'username' => username } }
let(:audit_usernames) { nil }
before do
allow(GitlabNet).to receive(:new).and_return(api)
allow(api).to receive(:discover).with(subject).and_return(discover_payload)
end
describe '.from' do
it 'returns an instance of Actor::Username' do
expect(described_class.from("username-#{username}")).to be_a(Actor::Username)
end
it 'has an id == 1' do
expect(described_class.from('username-1').id).to eq '1'
end
end
describe '.identifier_prefix' do
it "returns 'user'" do
expect(described_class.identifier_prefix).to eql 'username'
end
end
describe '.identifier_key' do
it "returns 'username'" do
expect(described_class.identifier_key).to eql 'username'
end
end
subject { described_class.new(username, audit_usernames: audit_usernames) }
describe '#username' do
context 'without a valid user' do
it "returns '@testuser'" do
expect(subject.username).to eql "@#{username}"
end
end
context 'without a valid user' do
let(:discover_payload) { nil }
it "returns 'Anonymous'" do
expect(subject.username).to eql 'Anonymous'
end
end
end
describe '#identifier' do
it "returns 'username-testuser'" do
expect(subject.identifier).to eql 'username-testuser'
end
end
describe '#log_username' do
context 'when audit_usernames is true' do
let(:audit_usernames) { true }
it "returns '@testuser'" do
expect(subject.log_username).to eql "@#{username}"
end
end
context 'when audit_usernames is false' do
let(:audit_usernames) { false }
it "returns 'user with identifier username-testuser'" do
expect(subject.log_username).to eql "user with identifier username-#{username}"
end
end
end
end
require_relative 'spec_helper'
require_relative '../lib/actor'
describe Actor do
describe '.new_from' do
context 'for an unsupported Actor type' do
it 'raises a NotImplementedError exception' do
expect do
described_class.new_from('unsupported-1')
end.to raise_error(Actor::UnsupportedActorError)
end
end
context 'for a supported Actor type' do
context 'of Key' do
it 'returns an instance of Key' do
expect(described_class.new_from('key-1')).to be_a(Actor::Key)
end
end
context 'of User' do
it 'returns an instance of User' do
expect(described_class.new_from('user-1')).to be_a(Actor::User)
end
end
context 'of Username' do
it 'returns an instance of Username' do
expect(described_class.new_from('username-john1')).to be_a(Actor::Username)
end
end
end
end
end
...@@ -7,27 +7,31 @@ describe GitlabAccess do ...@@ -7,27 +7,31 @@ describe GitlabAccess do
let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
let(:api) do let(:api) do
double(GitlabNet).tap do |api| double(GitlabNet).tap do |api|
allow(api).to receive(:check_access).and_return( api.stub(check_access: GitAccessStatus.new(true,
Action::Gitaly.new( 'ok',
'key-1', gl_repository: 'project-1',
'project-1', gl_id: 'user-123',
'testuser', gl_username: 'testuser',
'version=2', repository_path: '/home/git/repositories',
'/home/git/repositories', gitaly: nil,
nil git_protocol: 'version=2'))
)
)
end end
end end
subject do subject do
GitlabAccess.new(nil, repo_path, 'key-123', 'wow', 'ssh').tap do |access| GitlabAccess.new(nil, repo_path, 'key-123', 'wow', 'ssh').tap do |access|
allow(access).to receive(:exec_cmd).and_return(:exec_called) access.stub(exec_cmd: :exec_called)
allow(access).to receive(:api).and_return(api) access.stub(api: api)
end end
end end
before do before do
allow_any_instance_of(GitlabConfig).to receive(:repos_path).and_return(repository_path) GitlabConfig.any_instance.stub(repos_path: repository_path)
end
describe :initialize do
it { subject.repo_path.should == repo_path }
it { subject.changes.should == ['wow'] }
it { subject.protocol.should == 'ssh' }
end end
describe "#exec" do describe "#exec" do
...@@ -39,7 +43,16 @@ describe GitlabAccess do ...@@ -39,7 +43,16 @@ describe GitlabAccess do
context "access is denied" do context "access is denied" do
before do before do
allow(api).to receive(:check_access).and_raise(AccessDeniedError) api.stub(check_access: GitAccessStatus.new(
false,
'denied',
gl_repository: nil,
gl_id: nil,
gl_username: nil,
repository_path: nil,
gitaly: nil,
git_protocol: nil
))
end end
it "returns false" do it "returns false" do
...@@ -49,7 +62,7 @@ describe GitlabAccess do ...@@ -49,7 +62,7 @@ describe GitlabAccess do
context "API connection fails" do context "API connection fails" do
before do before do
allow(api).to receive(:check_access).and_raise(GitlabNet::ApiUnreachableError) api.stub(:check_access).and_raise(GitlabNet::ApiUnreachableError)
end end
it "returns false" do it "returns false" do
......
...@@ -3,55 +3,29 @@ require_relative '../lib/gitlab_config' ...@@ -3,55 +3,29 @@ require_relative '../lib/gitlab_config'
describe GitlabConfig do describe GitlabConfig do
let(:config) { GitlabConfig.new } let(:config) { GitlabConfig.new }
let(:config_data) do
{
# 'user' => 'git',
# 'http_settings' => {
# 'self_signed_cert' => false
# },
# 'log_level' => 'ERROR',
# 'audit_usernames' => true,
# 'log_format' => 'json', # Not sure on other values?
# 'git_trace_log_file' => nil
}
end
before do
expect(YAML).to receive(:load_file).and_return(config_data)
end
describe '#gitlab_url' do describe :gitlab_url do
let(:url) { 'http://test.com' } let(:url) { 'http://test.com' }
subject { config.gitlab_url } subject { config.gitlab_url }
before { config.send(:config)['gitlab_url'] = url }
before { config_data['gitlab_url'] = url }
it { should_not be_empty } it { should_not be_empty }
it { should eq(url) } it { should eq(url) }
context 'remove trailing slashes' do context 'remove trailing slashes' do
before { config_data['gitlab_url'] = url + '//' } before { config.send(:config)['gitlab_url'] = url + '//' }
it { should eq(url) } it { should eq(url) }
end end
end end
describe '#audit_usernames' do describe :audit_usernames do
subject { config.audit_usernames } subject { config.audit_usernames }
it("returns false by default") { should eq(false) } it("returns false by default") { should eq(false) }
end end
describe '#log_level' do describe :log_format do
subject { config.log_level }
it 'returns "INFO" by default' do
should eq('INFO')
end
end
describe '#log_format' do
subject { config.log_format } subject { config.log_format }
it 'returns "text" by default' do it 'returns "text" by default' do
......
...@@ -65,9 +65,9 @@ describe GitlabKeys do ...@@ -65,9 +65,9 @@ describe GitlabKeys do
describe :initialize do describe :initialize do
let(:gitlab_keys) { build_gitlab_keys('add-key', 'key-741', 'ssh-rsa AAAAB3NzaDAxx2E') } let(:gitlab_keys) { build_gitlab_keys('add-key', 'key-741', 'ssh-rsa AAAAB3NzaDAxx2E') }
it { expect(gitlab_keys.key).to eql 'ssh-rsa AAAAB3NzaDAxx2E' } it { gitlab_keys.key.should == 'ssh-rsa AAAAB3NzaDAxx2E' }
it { expect(gitlab_keys.instance_variable_get(:@command)).to eql 'add-key' } it { gitlab_keys.instance_variable_get(:@command).should == 'add-key' }
it { expect(gitlab_keys.instance_variable_get(:@key_id)).to eql 'key-741' } it { gitlab_keys.instance_variable_get(:@key_id).should == 'key-741' }
end end
describe :add_key do describe :add_key do
...@@ -77,7 +77,7 @@ describe GitlabKeys do ...@@ -77,7 +77,7 @@ describe GitlabKeys do
create_authorized_keys_fixture create_authorized_keys_fixture
gitlab_keys.send :add_key gitlab_keys.send :add_key
auth_line = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-741\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaDAxx2E" auth_line = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-741\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaDAxx2E"
expect(File.read(tmp_authorized_keys_path)).to eql "existing content\n#{auth_line}\n" File.read(tmp_authorized_keys_path).should == "existing content\n#{auth_line}\n"
end end
context "without file writing" do context "without file writing" do
...@@ -85,12 +85,12 @@ describe GitlabKeys do ...@@ -85,12 +85,12 @@ describe GitlabKeys do
before { create_authorized_keys_fixture } before { create_authorized_keys_fixture }
it "should log an add-key event" do it "should log an add-key event" do
expect($logger).to receive(:info).with("Adding key", {:key_id=>"key-741", :public_key=>"ssh-rsa AAAAB3NzaDAxx2E"}) $logger.should_receive(:info).with("Adding key", {:key_id=>"key-741", :public_key=>"ssh-rsa AAAAB3NzaDAxx2E"})
gitlab_keys.send :add_key gitlab_keys.send :add_key
end end
it "should return true" do it "should return true" do
expect(gitlab_keys.send(:add_key)).to be_truthy gitlab_keys.send(:add_key).should be_truthy
end end
end end
end end
...@@ -104,7 +104,7 @@ describe GitlabKeys do ...@@ -104,7 +104,7 @@ describe GitlabKeys do
create_authorized_keys_fixture create_authorized_keys_fixture
gitlab_keys.send :add_key gitlab_keys.send :add_key
auth_line1 = 'key-741 AAAAB3NzaDAxx2E' auth_line1 = 'key-741 AAAAB3NzaDAxx2E'
expect(gitlab_keys.send(:list_keys)).to eql "#{auth_line1}\n" gitlab_keys.send(:list_keys).should == "#{auth_line1}\n"
end end
end end
...@@ -118,9 +118,10 @@ describe GitlabKeys do ...@@ -118,9 +118,10 @@ describe GitlabKeys do
end end
it 'outputs the key IDs, separated by newlines' do it 'outputs the key IDs, separated by newlines' do
expect do output = capture_stdout do
gitlab_keys.send(:list_key_ids) gitlab_keys.send(:list_key_ids)
end.to output("1\n2\n3\n9000\n").to_stdout end
output.should match "1\n2\n3\n9000"
end end
end end
...@@ -129,38 +130,38 @@ describe GitlabKeys do ...@@ -129,38 +130,38 @@ describe GitlabKeys do
let(:fake_stdin) { StringIO.new("key-12\tssh-dsa ASDFASGADG\nkey-123\tssh-rsa GFDGDFSGSDFG\n", 'r') } let(:fake_stdin) { StringIO.new("key-12\tssh-dsa ASDFASGADG\nkey-123\tssh-rsa GFDGDFSGSDFG\n", 'r') }
before do before do
create_authorized_keys_fixture create_authorized_keys_fixture
allow(gitlab_keys).to receive(:stdin).and_return(fake_stdin) gitlab_keys.stub(stdin: fake_stdin)
end end
it "adds lines at the end of the file" do it "adds lines at the end of the file" do
gitlab_keys.send :batch_add_keys gitlab_keys.send :batch_add_keys
auth_line1 = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-12\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dsa ASDFASGADG" auth_line1 = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-12\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-dsa ASDFASGADG"
auth_line2 = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-123\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa GFDGDFSGSDFG" auth_line2 = "command=\"#{ROOT_PATH}/bin/gitlab-shell key-123\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa GFDGDFSGSDFG"
expect(File.read(tmp_authorized_keys_path)).to eql "existing content\n#{auth_line1}\n#{auth_line2}\n" File.read(tmp_authorized_keys_path).should == "existing content\n#{auth_line1}\n#{auth_line2}\n"
end end
context "with invalid input" do context "with invalid input" do
let(:fake_stdin) { StringIO.new("key-12\tssh-dsa ASDFASGADG\nkey-123\tssh-rsa GFDGDFSGSDFG\nfoo\tbar\tbaz\n", 'r') } let(:fake_stdin) { StringIO.new("key-12\tssh-dsa ASDFASGADG\nkey-123\tssh-rsa GFDGDFSGSDFG\nfoo\tbar\tbaz\n", 'r') }
it "aborts" do it "aborts" do
expect(gitlab_keys).to receive(:abort) gitlab_keys.should_receive(:abort)
gitlab_keys.send :batch_add_keys gitlab_keys.send :batch_add_keys
end end
end end
context "without file writing" do context "without file writing" do
before do before do
expect(gitlab_keys).to receive(:open).and_yield(double(:file, puts: nil, chmod: nil)) gitlab_keys.should_receive(:open).and_yield(double(:file, puts: nil, chmod: nil))
end end
it "should log an add-key event" do it "should log an add-key event" do
expect($logger).to receive(:info).with("Adding key", key_id: 'key-12', public_key: "ssh-dsa ASDFASGADG") $logger.should_receive(:info).with("Adding key", key_id: 'key-12', public_key: "ssh-dsa ASDFASGADG")
expect($logger).to receive(:info).with("Adding key", key_id: 'key-123', public_key: "ssh-rsa GFDGDFSGSDFG") $logger.should_receive(:info).with("Adding key", key_id: 'key-123', public_key: "ssh-rsa GFDGDFSGSDFG")
gitlab_keys.send :batch_add_keys gitlab_keys.send :batch_add_keys
end end
it "should return true" do it "should return true" do
expect(gitlab_keys.send(:batch_add_keys)).to be_truthy gitlab_keys.send(:batch_add_keys).should be_truthy
end end
end end
end end
...@@ -186,22 +187,22 @@ describe GitlabKeys do ...@@ -186,22 +187,22 @@ describe GitlabKeys do
end end
gitlab_keys.send :rm_key gitlab_keys.send :rm_key
erased_line = delete_line.gsub(/./, '#') erased_line = delete_line.gsub(/./, '#')
expect(File.read(tmp_authorized_keys_path)).to eql "existing content\n#{erased_line}\n#{other_line}\n" File.read(tmp_authorized_keys_path).should == "existing content\n#{erased_line}\n#{other_line}\n"
end end
context "without file writing" do context "without file writing" do
before do before do
allow(gitlab_keys).to receive(:open) gitlab_keys.stub(:open)
allow(gitlab_keys).to receive(:lock).and_yield gitlab_keys.stub(:lock).and_yield
end end
it "should log an rm-key event" do it "should log an rm-key event" do
expect($logger).to receive(:info).with("Removing key", key_id: "key-741") $logger.should_receive(:info).with("Removing key", key_id: "key-741")
gitlab_keys.send :rm_key gitlab_keys.send :rm_key
end end
it "should return true" do it "should return true" do
expect(gitlab_keys.send(:rm_key)).to be_truthy gitlab_keys.send(:rm_key).should be_truthy
end end
end end
...@@ -218,7 +219,7 @@ describe GitlabKeys do ...@@ -218,7 +219,7 @@ describe GitlabKeys do
end end
gitlab_keys.send :rm_key gitlab_keys.send :rm_key
erased_line = delete_line.gsub(/./, '#') erased_line = delete_line.gsub(/./, '#')
expect(File.read(tmp_authorized_keys_path)).to eql "existing content\n#{erased_line}\n#{other_line}\n" File.read(tmp_authorized_keys_path).should == "existing content\n#{erased_line}\n#{other_line}\n"
end end
end end
end end
...@@ -227,8 +228,8 @@ describe GitlabKeys do ...@@ -227,8 +228,8 @@ describe GitlabKeys do
let(:gitlab_keys) { build_gitlab_keys('clear') } let(:gitlab_keys) { build_gitlab_keys('clear') }
it "should return true" do it "should return true" do
allow(gitlab_keys).to receive(:open) gitlab_keys.stub(:open)
expect(gitlab_keys.send(:clear)).to be_truthy gitlab_keys.send(:clear).should be_truthy
end end
end end
...@@ -241,7 +242,7 @@ describe GitlabKeys do ...@@ -241,7 +242,7 @@ describe GitlabKeys do
end end
it 'returns false if opening raises an exception' do it 'returns false if opening raises an exception' do
expect(gitlab_keys).to receive(:open_auth_file).and_raise("imaginary error") gitlab_keys.should_receive(:open_auth_file).and_raise("imaginary error")
expect(gitlab_keys.exec).to eq(false) expect(gitlab_keys.exec).to eq(false)
end end
...@@ -256,51 +257,51 @@ describe GitlabKeys do ...@@ -256,51 +257,51 @@ describe GitlabKeys do
describe :exec do describe :exec do
it 'add-key arg should execute add_key method' do it 'add-key arg should execute add_key method' do
gitlab_keys = build_gitlab_keys('add-key') gitlab_keys = build_gitlab_keys('add-key')
expect(gitlab_keys).to receive(:add_key) gitlab_keys.should_receive(:add_key)
gitlab_keys.exec gitlab_keys.exec
end end
it 'batch-add-keys arg should execute batch_add_keys method' do it 'batch-add-keys arg should execute batch_add_keys method' do
gitlab_keys = build_gitlab_keys('batch-add-keys') gitlab_keys = build_gitlab_keys('batch-add-keys')
expect(gitlab_keys).to receive(:batch_add_keys) gitlab_keys.should_receive(:batch_add_keys)
gitlab_keys.exec gitlab_keys.exec
end end
it 'rm-key arg should execute rm_key method' do it 'rm-key arg should execute rm_key method' do
gitlab_keys = build_gitlab_keys('rm-key') gitlab_keys = build_gitlab_keys('rm-key')
expect(gitlab_keys).to receive(:rm_key) gitlab_keys.should_receive(:rm_key)
gitlab_keys.exec gitlab_keys.exec
end end
it 'clear arg should execute clear method' do it 'clear arg should execute clear method' do
gitlab_keys = build_gitlab_keys('clear') gitlab_keys = build_gitlab_keys('clear')
expect(gitlab_keys).to receive(:clear) gitlab_keys.should_receive(:clear)
gitlab_keys.exec gitlab_keys.exec
end end
it 'check-permissions arg should execute check_permissions method' do it 'check-permissions arg should execute check_permissions method' do
gitlab_keys = build_gitlab_keys('check-permissions') gitlab_keys = build_gitlab_keys('check-permissions')
expect(gitlab_keys).to receive(:check_permissions) gitlab_keys.should_receive(:check_permissions)
gitlab_keys.exec gitlab_keys.exec
end end
it 'should puts message if unknown command arg' do it 'should puts message if unknown command arg' do
gitlab_keys = build_gitlab_keys('change-key') gitlab_keys = build_gitlab_keys('change-key')
expect(gitlab_keys).to receive(:puts).with('not allowed') gitlab_keys.should_receive(:puts).with('not allowed')
gitlab_keys.exec gitlab_keys.exec
end end
it 'should log a warning on unknown commands' do it 'should log a warning on unknown commands' do
gitlab_keys = build_gitlab_keys('nooope') gitlab_keys = build_gitlab_keys('nooope')
allow(gitlab_keys).to receive(:puts).and_return(nil) gitlab_keys.stub(puts: nil)
expect($logger).to receive(:warn).with("Attempt to execute invalid gitlab-keys command", command: '"nooope"') $logger.should_receive(:warn).with("Attempt to execute invalid gitlab-keys command", command: '"nooope"')
gitlab_keys.exec gitlab_keys.exec
end end
end end
describe :lock do describe :lock do
before do before do
allow_any_instance_of(GitlabKeys).to receive(:lock_file).and_return(tmp_lock_file_path) GitlabKeys.any_instance.stub(lock_file: tmp_lock_file_path)
end end
it "should raise exception if operation lasts more then timeout" do it "should raise exception if operation lasts more then timeout" do
...@@ -309,7 +310,7 @@ describe GitlabKeys do ...@@ -309,7 +310,7 @@ describe GitlabKeys do
key.send :lock, 1 do key.send :lock, 1 do
sleep 2 sleep 2
end end
end.to raise_error(Timeout::Error) end.to raise_error
end end
it "should actually lock file" do it "should actually lock file" do
...@@ -334,7 +335,7 @@ describe GitlabKeys do ...@@ -334,7 +335,7 @@ describe GitlabKeys do
end end
thr1.join thr1.join
expect($global).to eql "foobar" $global.should == "foobar"
end end
end end
...@@ -352,7 +353,7 @@ describe GitlabKeys do ...@@ -352,7 +353,7 @@ describe GitlabKeys do
def create_authorized_keys_fixture(existing_content: 'existing content') def create_authorized_keys_fixture(existing_content: 'existing content')
FileUtils.mkdir_p(File.dirname(tmp_authorized_keys_path)) FileUtils.mkdir_p(File.dirname(tmp_authorized_keys_path))
open(tmp_authorized_keys_path, 'w') { |file| file.puts(existing_content) } open(tmp_authorized_keys_path, 'w') { |file| file.puts(existing_content) }
allow(gitlab_keys).to receive(:auth_file).and_return(tmp_authorized_keys_path) gitlab_keys.stub(auth_file: tmp_authorized_keys_path)
end end
def tmp_authorized_keys_path def tmp_authorized_keys_path
......
...@@ -16,22 +16,22 @@ describe GitlabLfsAuthentication do ...@@ -16,22 +16,22 @@ describe GitlabLfsAuthentication do
end end
describe '#build_from_json' do describe '#build_from_json' do
it { expect(subject.username).to eql 'dzaporozhets' } it { subject.username.should == 'dzaporozhets' }
it { expect(subject.lfs_token).to eql 'wsnys8Zm8Jn7zyhHTAAK' } it { subject.lfs_token.should == 'wsnys8Zm8Jn7zyhHTAAK' }
it { expect(subject.repository_http_path).to eql 'http://gitlab.dev/repo' } it { subject.repository_http_path.should == 'http://gitlab.dev/repo' }
end end
describe '#authentication_payload' do describe '#authentication_payload' do
result = "{\"header\":{\"Authorization\":\"Basic ZHphcG9yb3poZXRzOndzbnlzOFptOEpuN3p5aEhUQUFL\"},\"href\":\"http://gitlab.dev/repo/info/lfs/\"}" result = "{\"header\":{\"Authorization\":\"Basic ZHphcG9yb3poZXRzOndzbnlzOFptOEpuN3p5aEhUQUFL\"},\"href\":\"http://gitlab.dev/repo/info/lfs/\"}"
it { expect(subject.authentication_payload).to eq(result) } it { subject.authentication_payload.should eq(result) }
it 'should be a proper JSON' do it 'should be a proper JSON' do
payload = subject.authentication_payload payload = subject.authentication_payload
json_payload = JSON.parse(payload) json_payload = JSON.parse(payload)
expect(json_payload['header']['Authorization']).to eq('Basic ZHphcG9yb3poZXRzOndzbnlzOFptOEpuN3p5aEhUQUFL') json_payload['header']['Authorization'].should eq('Basic ZHphcG9yb3poZXRzOndzbnlzOFptOEpuN3p5aEhUQUFL')
expect(json_payload['href']).to eq('http://gitlab.dev/repo/info/lfs/') json_payload['href'].should eq('http://gitlab.dev/repo/info/lfs/')
end end
end end
end end
...@@ -6,7 +6,7 @@ describe :convert_log_level do ...@@ -6,7 +6,7 @@ describe :convert_log_level do
subject { convert_log_level :extreme } subject { convert_log_level :extreme }
it "converts invalid log level to Logger::INFO" do it "converts invalid log level to Logger::INFO" do
expect($stderr).to receive(:puts).at_least(:once) $stderr.should_receive(:puts).at_least(:once)
should eq(Logger::INFO) should eq(Logger::INFO)
end end
end end
......
This diff is collapsed.
...@@ -5,13 +5,13 @@ require 'gitlab_post_receive' ...@@ -5,13 +5,13 @@ require 'gitlab_post_receive'
describe GitlabPostReceive do describe GitlabPostReceive do
let(:repository_path) { "/home/git/repositories" } let(:repository_path) { "/home/git/repositories" }
let(:repo_name) { 'dzaporozhets/gitlab-ci' } let(:repo_name) { 'dzaporozhets/gitlab-ci' }
let(:gl_id) { 'key-123' } let(:actor) { 'key-123' }
let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" }
let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") } let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") }
let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) } let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
let(:repo_path) { File.join(repository_path, repo_name) + ".git" } let(:repo_path) { File.join(repository_path, repo_name) + ".git" }
let(:gl_repository) { "project-1" } let(:gl_repository) { "project-1" }
let(:gitlab_post_receive) { GitlabPostReceive.new(gl_repository, repo_path, gl_id, wrongly_encoded_changes) } let(:gitlab_post_receive) { GitlabPostReceive.new(gl_repository, repo_path, actor, wrongly_encoded_changes) }
let(:broadcast_message) { "test " * 10 + "message " * 10 } let(:broadcast_message) { "test " * 10 + "message " * 10 }
let(:enqueued_at) { Time.new(2016, 6, 23, 6, 59) } let(:enqueued_at) { Time.new(2016, 6, 23, 6, 59) }
let(:new_merge_request_urls) do let(:new_merge_request_urls) do
...@@ -31,7 +31,7 @@ describe GitlabPostReceive do ...@@ -31,7 +31,7 @@ describe GitlabPostReceive do
before do before do
$logger = double('logger').as_null_object # Global vars are bad $logger = double('logger').as_null_object # Global vars are bad
allow_any_instance_of(GitlabConfig).to receive(:repos_path).and_return(repository_path) GitlabConfig.any_instance.stub(repos_path: repository_path)
end end
describe "#exec" do describe "#exec" do
......
This diff is collapsed.
...@@ -5,8 +5,8 @@ describe NamesHelper do ...@@ -5,8 +5,8 @@ describe NamesHelper do
include NamesHelper include NamesHelper
describe :extract_ref_name do describe :extract_ref_name do
it { expect(extract_ref_name('refs/heads/awesome-feature')).to eql 'awesome-feature' } it { extract_ref_name('refs/heads/awesome-feature').should == 'awesome-feature' }
it { expect(extract_ref_name('refs/tags/v2.2.1')).to eql 'v2.2.1' } it { extract_ref_name('refs/tags/v2.2.1').should == 'v2.2.1' }
it { expect(extract_ref_name('refs/tags/releases/v2.2.1')).to eql 'releases/v2.2.1' } it { extract_ref_name('refs/tags/releases/v2.2.1').should == 'releases/v2.2.1' }
end end
end end
...@@ -5,7 +5,7 @@ http_interactions: ...@@ -5,7 +5,7 @@ http_interactions:
uri: http://localhost:3000/api/v4/internal/allowed uri: http://localhost:3000/api/v4/internal/allowed
body: body:
encoding: US-ASCII encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers: headers:
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
......
...@@ -5,7 +5,7 @@ http_interactions: ...@@ -5,7 +5,7 @@ http_interactions:
uri: http://localhost:3000/api/v4/internal/allowed uri: http://localhost:3000/api/v4/internal/allowed
body: body:
encoding: US-ASCII encoding: US-ASCII
string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers: headers:
Accept-Encoding: Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
......
---
http_interactions:
- request:
method: get
uri: http://localhost:3000/api/v4/internal/discover?key_id=1
body:
encoding: US-ASCII
string: secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 404
message: Not Found
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '42'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 10:44:49 GMT
Etag:
- W/"63b4ab301951bea83c4fc398eba8e307"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- dc11b8d4-1972-417b-8305-2c35c849405c
X-Runtime:
- '0.230170'
body:
encoding: UTF-8
string: '{"message":"404 Not found"}'
http_version:
recorded_at: Wed, 21 Jun 2017 10:44:49 GMT
recorded_with: VCR 2.4.0
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 500
message: Internal Server Error
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '155'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 10:44:52 GMT
Etag:
- W/"45654cae433b5a9c5fbba1d45d382e52"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 67ab4954-19e6-42ce-aae6-55c8ae5a365e
X-Runtime:
- '0.230871'
body:
encoding: UTF-8
string: '""'
http_version:
recorded_at: Wed, 21 Jun 2017 10:44:52 GMT
recorded_with: VCR 2.4.0
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 500
message: Internal Server Error
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '155'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 10:44:52 GMT
Etag:
- W/"45654cae433b5a9c5fbba1d45d382e52"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 67ab4954-19e6-42ce-aae6-55c8ae5a365e
X-Runtime:
- '0.230871'
body:
encoding: UTF-8
string: '{"status":false,"message":"An internal server error occurred"}'
http_version:
recorded_at: Wed, 21 Jun 2017 10:44:52 GMT
recorded_with: VCR 2.4.0
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=http&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '62'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 10:32:01 GMT
Etag:
- W/"71e09fcf8a60a03cd1acc22806386ead"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 70bdecc9-0078-4a4b-aa6b-cac1b2578886
X-Runtime:
- '0.324202'
body:
encoding: UTF-8
string: '{"status":false,"message":"Pulling over HTTP is not allowed."}'
http_version:
recorded_at: Wed, 21 Jun 2017 10:32:01 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=http&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '62'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 10:32:01 GMT
Etag:
- W/"7f14e23ac07cc8b0a53c567fcf9432fd"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 573f3584-87c6-41cb-a5bf-5e7ee76d4250
X-Runtime:
- '0.266135'
body:
encoding: UTF-8
string: '{"status":false,"message":"Pushing over HTTP is not allowed."}'
http_version:
recorded_at: Wed, 21 Jun 2017 10:32:01 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '63'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 12:23:57 GMT
Etag:
- W/"76a32010244f80700d5e1ba8a55d094c"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 096ae253-c6fe-4360-b4d4-48f4b5435ca6
X-Runtime:
- '6.377187'
body:
encoding: UTF-8
string: '{"status":false,"message":"Git access over SSH is not allowed"}'
http_version:
recorded_at: Wed, 21 Jun 2017 12:23:57 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=2&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '63'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 12:24:04 GMT
Etag:
- W/"76a32010244f80700d5e1ba8a55d094c"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- c843a5a3-fc08-46eb-aa45-caceae515638
X-Runtime:
- '7.359835'
body:
encoding: UTF-8
string: '{"status":false,"message":"Git access over SSH is not allowed"}'
http_version:
recorded_at: Wed, 21 Jun 2017 12:24:04 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=1&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '63'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 12:23:57 GMT
Etag:
- W/"76a32010244f80700d5e1ba8a55d094c"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 93620e06-fda9-4be5-855e-300f5d62fa3c
X-Runtime:
- '0.207159'
body:
encoding: UTF-8
string: '{"status":false,"message":"Git access over SSH is not allowed"}'
http_version:
recorded_at: Wed, 21 Jun 2017 12:23:57 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&key_id=2&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '63'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 12:24:04 GMT
Etag:
- W/"76a32010244f80700d5e1ba8a55d094c"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 8ce54f29-9ed0-46e5-aedb-37edaa3d52da
X-Runtime:
- '0.228256'
body:
encoding: UTF-8
string: '{"status":false,"message":"Git access over SSH is not allowed"}'
http_version:
recorded_at: Wed, 21 Jun 2017 12:24:04 GMT
recorded_with: VCR 2.4.0
---
http_interactions:
- request:
method: post
uri: http://localhost:3000/api/v4/internal/allowed
body:
encoding: US-ASCII
string: action=git-upload-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&gl_repository&project=gitlab-org%2Fgitlab-test.git&protocol=ssh&env=%7B%7D&user_id=2&secret_token=0a3938d9d95d807e94d937af3a4fbbea%0A
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Ruby
Content-Type:
- application/x-www-form-urlencoded
response:
status:
code: 200
message: OK
headers:
Cache-Control:
- max-age=0, private, must-revalidate
Content-Length:
- '63'
Content-Type:
- application/json
Date:
- Wed, 21 Jun 2017 12:24:05 GMT
Etag:
- W/"76a32010244f80700d5e1ba8a55d094c"
Vary:
- Origin
X-Frame-Options:
- SAMEORIGIN
X-Request-Id:
- 3b242d73-d860-48ac-8fef-80e2d0d3daca
X-Runtime:
- '0.342469'
body:
encoding: UTF-8
string: '{"status":false,"message":"Git access over SSH is not allowed"}'
http_version:
recorded_at: Wed, 21 Jun 2017 12:24:05 GMT
recorded_with: VCR 2.4.0
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
...@@ -17,8 +17,8 @@ http_interactions: ...@@ -17,8 +17,8 @@ http_interactions:
- application/x-www-form-urlencoded - application/x-www-form-urlencoded
response: response:
status: status:
code: 401 code: 200
message: Unauthorized message: OK
headers: headers:
Cache-Control: Cache-Control:
- max-age=0, private, must-revalidate - max-age=0, private, must-revalidate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment