1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
require_relative 'spec_helper'
require 'open3'
describe 'bin/gitlab-shell 2fa_recovery_codes' do
include_context 'gitlab shell'
def mock_server(server)
server.mount_proc('/api/v4/internal/two_factor_recovery_codes') do |req, res|
res.content_type = 'application/json'
res.status = 200
key_id = req.query['key_id'] || req.query['user_id']
unless key_id
body = JSON.parse(req.body)
key_id = body['key_id'] || body['user_id'].to_s
end
if key_id == '100'
res.body = '{"success":true, "recovery_codes": ["1", "2"]}'
else
res.body = '{"success":false, "message": "Forbidden!"}'
end
end
server.mount_proc('/api/v4/internal/discover') do |req, res|
res.status = 200
res.content_type = 'application/json'
res.body = '{"id":100, "name": "Some User", "username": "someuser"}'
end
end
shared_examples 'dialog for regenerating recovery keys' do
context 'when the user agrees to regenerate keys' do
def verify_successful_regeneration!(cmd)
p "+++++++++++++++++++++++++++#{env}---------------#{cmd}"
Open3.popen2(env, cmd) do |stdin, stdout|
expect(stdout.gets).to eq("Are you sure you want to generate new two-factor recovery codes?\n")
expect(stdout.gets).to eq("Any existing recovery codes you saved will be invalidated. (yes/no)\n")
stdin.puts('yes')
expect(stdout.flush.read).to eq(
"\nYour two-factor authentication recovery codes are:\n\n" \
"1\n2\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.\n"
)
end
end
context 'when key is provided' do
let(:cmd) { "#{gitlab_shell_path} key-100" }
it 'the recovery keys are regenerated' do
verify_successful_regeneration!(cmd)
end
end
context 'when username is provided' do
let(:cmd) { "#{gitlab_shell_path} -c/usr/share/webapps/gitlab-shell/bin/gitlab-shell username-someone" }
it 'the recovery keys are regenerated' do
verify_successful_regeneration!(cmd)
end
end
end
context 'when the user disagrees to regenerate keys' do
let(:cmd) { "#{gitlab_shell_path} -c/usr/share/webapps/gitlab-shell/bin/gitlab-shell key-100" }
it 'the recovery keys are not regenerated' do
Open3.popen2(env, cmd) do |stdin, stdout|
expect(stdout.gets).to eq("Are you sure you want to generate new two-factor recovery codes?\n")
expect(stdout.gets).to eq("Any existing recovery codes you saved will be invalidated. (yes/no)\n")
stdin.puts('no')
expect(stdout.flush.read).to eq(
"\nNew recovery codes have *not* been generated. Existing codes will remain valid.\n"
)
end
end
end
context 'when API error occurs' do
let(:cmd) { "#{gitlab_shell_path} -c/usr/share/webapps/gitlab-shell/bin/gitlab-shell key-101" }
context 'when the user agrees to regenerate keys' do
it 'the recovery keys are regenerated' do
Open3.popen2(env, cmd) do |stdin, stdout|
expect(stdout.gets).to eq("Are you sure you want to generate new two-factor recovery codes?\n")
expect(stdout.gets).to eq("Any existing recovery codes you saved will be invalidated. (yes/no)\n")
stdin.puts('yes')
expect(stdout.flush.read).to eq("\nAn error occurred while trying to generate new recovery codes.\nForbidden!\n")
end
end
end
end
end
let(:env) { {'SSH_CONNECTION' => 'fake', 'SSH_ORIGINAL_COMMAND' => '2fa_recovery_codes' } }
describe 'without go features' do
before(:context) do
write_config(
"gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
)
end
it_behaves_like 'dialog for regenerating recovery keys'
end
describe 'with go features' do
before(:context) do
write_config(
"gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
"migration" => { "enabled" => true,
"features" => ["2fa_recovery_codes"] }
)
end
it_behaves_like 'dialog for regenerating recovery keys'
end
end
|