summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorkmcknight <kmcknight@gitlab.com>2021-02-25 17:17:25 -0800
committerIgor Drozdov <idrozdov@gitlab.com>2022-07-18 07:28:32 +0200
commitfe5feeea22a639a4835724cf42b337773b54d83c (patch)
tree9dd8851a2d05460c713c46227e8365244eda3022 /spec
parent9cacca57e5300c9a23dfc9ae18f48ee48483451b (diff)
downloadgitlab-shell-fe5feeea22a639a4835724cf42b337773b54d83c.tar.gz
Implement Push Auth support for 2FA verification
When `2fa_verify` command is executed: - A user is asked to enter OTP - A blocking call for push auth is performed Then: - If the push auth request fails, the user is still able to enter OTP - If OTP is invalid, the `2fa_verify` command ends the execution - If OTP is valid or push auth request succeeded, then the user is successfully authenticated - If 30 seconds passed while no OTP or Push have been provided, then the `2fa_verify` command ends the execution
Diffstat (limited to 'spec')
-rw-r--r--spec/gitlab_shell_two_factor_manual_verify_spec.rb (renamed from spec/gitlab_shell_two_factor_verify_spec.rb)15
-rw-r--r--spec/gitlab_shell_two_factor_push_verify_spec.rb71
2 files changed, 84 insertions, 2 deletions
diff --git a/spec/gitlab_shell_two_factor_verify_spec.rb b/spec/gitlab_shell_two_factor_manual_verify_spec.rb
index 25d8869..f685b22 100644
--- a/spec/gitlab_shell_two_factor_verify_spec.rb
+++ b/spec/gitlab_shell_two_factor_manual_verify_spec.rb
@@ -3,7 +3,7 @@ require_relative 'spec_helper'
require 'open3'
require 'json'
-describe 'bin/gitlab-shell 2fa_verify' do
+describe 'bin/gitlab-shell 2fa_verify manual' do
include_context 'gitlab shell'
let(:env) do
@@ -16,7 +16,7 @@ describe 'bin/gitlab-shell 2fa_verify' do
end
def mock_server(server)
- server.mount_proc('/api/v4/internal/two_factor_otp_check') do |req, res|
+ server.mount_proc('/api/v4/internal/two_factor_manual_otp_check') do |req, res|
res.content_type = 'application/json'
res.status = 200
@@ -30,6 +30,17 @@ describe 'bin/gitlab-shell 2fa_verify' do
end
end
+ server.mount_proc('/api/v4/internal/two_factor_push_otp_check') do |req, res|
+ res.content_type = 'application/json'
+ res.status = 200
+
+ params = JSON.parse(req.body)
+ key_id = params['key_id'] || params['user_id'].to_s
+
+ sleep 5 # simulate Fortinet API timing
+ res.body = { success: false, message: 'boom!' }.to_json
+ end
+
server.mount_proc('/api/v4/internal/discover') do |_, res|
res.status = 200
res.content_type = 'application/json'
diff --git a/spec/gitlab_shell_two_factor_push_verify_spec.rb b/spec/gitlab_shell_two_factor_push_verify_spec.rb
new file mode 100644
index 0000000..e870580
--- /dev/null
+++ b/spec/gitlab_shell_two_factor_push_verify_spec.rb
@@ -0,0 +1,71 @@
+require_relative 'spec_helper'
+
+require 'open3'
+require 'json'
+
+describe 'bin/gitlab-shell 2fa_verify push' do
+ include_context 'gitlab shell'
+
+ let(:env) do
+ { 'SSH_CONNECTION' => 'fake',
+ 'SSH_ORIGINAL_COMMAND' => '2fa_verify' }
+ end
+
+ before(:context) do
+ write_config('gitlab_url' => "http+unix://#{CGI.escape(tmp_socket_path)}")
+ end
+
+ def mock_server(server)
+ server.mount_proc('/api/v4/internal/two_factor_push_otp_check') do |req, res|
+ res.content_type = 'application/json'
+ res.status = 200
+
+ params = JSON.parse(req.body)
+ key_id = params['key_id'] || params['user_id'].to_s
+
+ if key_id == '100'
+ res.body = { success: false }.to_json
+ elsif key_id == '102'
+ res.body = { success: true }.to_json
+ else
+ res.body = { success: false, message: 'boom!' }.to_json
+ end
+ end
+
+ server.mount_proc('/api/v4/internal/discover') do |_, res|
+ res.status = 200
+ res.content_type = 'application/json'
+ res.body = { id: 100, name: 'Some User', username: 'someuser' }.to_json
+ end
+ end
+
+ describe 'command' do
+ context 'when push is provided' do
+ let(:cmd) { "#{gitlab_shell_path} key-102" }
+
+ it 'prints a successful push verification message' do
+ verify_successful_verification_push!(cmd)
+ end
+ end
+
+ context 'when API error occurs' do
+ let(:cmd) { "#{gitlab_shell_path} key-101" }
+
+ it 'prints the error message' do
+ Open3.popen2(env, cmd) do |stdin, stdout|
+ expect(stdout.gets(5)).to eq('OTP: ')
+
+ expect(stdout.flush.read).to eq("\nPush OTP validation failed.\nboom!\n")
+ end
+ end
+ end
+ end
+
+ def verify_successful_verification_push!(cmd)
+ Open3.popen2(env, cmd) do |stdin, stdout|
+ expect(stdout.gets(5)).to eq('OTP: ')
+
+ expect(stdout.flush.read).to eq("\nPush OTP validation successful. Git operations are now allowed.\n")
+ end
+ end
+end