diff options
author | kmcknight <kmcknight@gitlab.com> | 2021-02-25 17:17:25 -0800 |
---|---|---|
committer | Igor Drozdov <idrozdov@gitlab.com> | 2022-07-18 07:28:32 +0200 |
commit | fe5feeea22a639a4835724cf42b337773b54d83c (patch) | |
tree | 9dd8851a2d05460c713c46227e8365244eda3022 /spec | |
parent | 9cacca57e5300c9a23dfc9ae18f48ee48483451b (diff) | |
download | gitlab-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.rb | 71 |
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 |