1require_relative 'spec_helper'
2
3describe 'bin/gitlab-shell-authorized-keys-check' do
4  include_context 'gitlab shell'
5
6  def tmp_socket_path
7    # This has to be a relative path shorter than 100 bytes due to
8    # limitations in how Unix sockets work.
9    'tmp/gitlab-shell-authorized-keys-check-socket'
10  end
11
12  def mock_server(server)
13    server.mount_proc('/api/v4/internal/authorized_keys') do |req, res|
14      if req.query['key'] == 'known-rsa-key'
15        res.status = 200
16        res.content_type = 'application/json'
17        res.body = '{"key":"known-rsa-key", "id": 1}'
18      else
19        res.status = 404
20      end
21    end
22  end
23
24  let(:authorized_keys_check_path) { File.join(tmp_root_path, 'bin', 'gitlab-shell-authorized-keys-check') }
25
26  shared_examples 'authorized keys check' do
27    it 'succeeds when a valid key is given' do
28      output, status = run!
29
30      expect(output).to eq("command=\"#{gitlab_shell_path} key-1\",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty known-rsa-key\n")
31      expect(status).to be_success
32    end
33
34    it 'returns nothing when an unknown key is given' do
35      output, status = run!(key: 'unknown-key')
36
37      expect(output).to eq("# No key was found for unknown-key\n")
38      expect(status).to be_success
39    end
40
41    it' fails when not enough arguments are given' do
42      output, status = run!(key: nil)
43
44      expect(output).to eq('')
45      expect(status).not_to be_success
46    end
47
48    it' fails when too many arguments are given' do
49      output, status = run!(key: ['a', 'b'])
50
51      expect(output).to eq('')
52      expect(status).not_to be_success
53    end
54
55    it 'skips when run as the wrong user' do
56      output, status = run!(expected_user: 'unknown-user')
57
58      expect(output).to eq('')
59      expect(status).to be_success
60    end
61
62    it 'skips when the wrong users connects' do
63      output, status = run!(actual_user: 'unknown-user')
64
65      expect(output).to eq('')
66      expect(status).to be_success
67    end
68  end
69
70  describe 'without go features' do
71    before(:all) do
72      write_config(
73        "gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
74      )
75    end
76
77    it_behaves_like 'authorized keys check'
78  end
79
80  describe 'without go features (via go)', :go do
81    before(:all) do
82      write_config(
83        "gitlab_url" => "http+unix://#{CGI.escape(tmp_socket_path)}",
84      )
85    end
86
87    it_behaves_like 'authorized keys check'
88  end
89
90  describe 'with the go authorized-keys-check feature', :go do
91    before(:all) do
92      write_config(
93        'gitlab_url' => "http+unix://#{CGI.escape(tmp_socket_path)}",
94        'migration' => {
95          'enabled' => true,
96          'features' => ['authorized-keys-check']
97        }
98      )
99    end
100
101    it_behaves_like 'authorized keys check'
102  end
103
104  def run!(expected_user: 'git', actual_user: 'git', key: 'known-rsa-key')
105    cmd = [
106      authorized_keys_check_path,
107      expected_user,
108      actual_user,
109      key
110    ].flatten.compact
111
112    output = IO.popen(cmd, &:read)
113
114    [output, $?]
115  end
116end
117