1require 'spec_helper'
2
3describe Gitlab::Git::GitalyRemoteRepository do
4  include TestRepo
5  include IntegrationClient
6
7  describe '#new' do
8    let(:gitaly_repository) { double(storage_name: 'storage') }
9    let(:call) do
10      servers = Base64.strict_encode64({
11        default: {
12          address: 'address',
13          token: 'the-secret-token'
14        }
15      }.to_json)
16
17      double(metadata: { 'gitaly-servers' => servers })
18    end
19
20    context 'Labkit::Tracing enabled' do
21      before do
22        expect(Labkit::Tracing).to receive(:enabled?).and_return(true)
23      end
24
25      it 'initializes with an interceptor' do
26        client = described_class.new(gitaly_repository, call)
27        expect(client.instance_variable_get(:@interceptors).size).to eq 1
28      end
29    end
30
31    context 'Labkit::Tracing disabled' do
32      before do
33        expect(Labkit::Tracing).to receive(:enabled?).and_return(false)
34      end
35
36      it 'initializes with no interceptors' do
37        client = described_class.new(gitaly_repository, call)
38        expect(client.instance_variable_get(:@interceptors).size).to eq 0
39      end
40    end
41  end
42
43  let(:repository) { gitlab_git_from_gitaly_with_gitlab_projects(new_mutable_test_repo) }
44  describe 'certs' do
45    let(:client) { get_client("tls://localhost:#{GitalyConfig.dynamic_port('tls')}") }
46
47    context 'when neither SSL_CERT_FILE and SSL_CERT_DIR is set' do
48      it 'Raises an error' do
49        expect { client.certs }.to raise_error 'SSL_CERT_DIR and/or SSL_CERT_FILE environment variable must be set'
50      end
51    end
52
53    context 'when SSL_CERT_FILE is set' do
54      it 'Should return the correct certificate' do
55        cert = File.join(File.dirname(__FILE__), "testdata/certs/gitalycert.pem")
56        allow(ENV).to receive(:[]).with('GITLAB_TRACING').and_call_original
57        allow(ENV).to receive(:[]).with('SSL_CERT_DIR').and_return(nil)
58        allow(ENV).to receive(:[]).with('SSL_CERT_FILE').and_return(cert)
59        certs = client.certs
60        expect(certs).to eq File.read(cert)
61      end
62    end
63
64    context 'when SSL_CERT_DIR is set' do
65      it 'Should return concatenation of gitalycert and gitalycert2 and gitalycert3 omitting gitalycertdup.pem' do
66        cert_pool_dir = File.join(File.dirname(__FILE__), "testdata/certs")
67        allow(ENV).to receive(:[]).with('GITLAB_TRACING').and_call_original
68        allow(ENV).to receive(:[]).with('SSL_CERT_DIR').and_return(cert_pool_dir)
69        allow(ENV).to receive(:[]).with('SSL_CERT_FILE').and_return(nil)
70        certs = client.certs
71
72        # gitalycertdup.pem must exist and must be a duplicate of gitalycert.pem
73        expect(File.exist?(File.join(cert_pool_dir, "gitalycertdup.pem"))).to be true
74        expect(File.read(File.join(cert_pool_dir, "gitalycertdup.pem")))
75          .to eq File.read(File.join(cert_pool_dir, "gitalycert.pem"))
76
77        # No gitalycertdup.pem because duplicates should be removed
78        expected_certs = [File.read(File.join(cert_pool_dir, "gitalycert.pem")),
79                          File.read(File.join(cert_pool_dir, "gitalycert2.pem")),
80                          File.read(File.join(cert_pool_dir, "gitalycert3.pem"))].join "\n"
81
82        expect(certs).to eq expected_certs
83      end
84    end
85
86    context 'when both SSL_CERT_DIR and SSL_CERT_FILE are set' do
87      it 'Should return all certs in SSL_CERT_DIR + SSL_CERT_FILE' do
88        cert_pool_dir = File.join(File.dirname(__FILE__), "testdata/certs")
89        cert1_file = File.join(File.dirname(__FILE__), "testdata/gitalycert.pem")
90        allow(ENV).to receive(:[]).with('GITLAB_TRACING').and_call_original
91        allow(ENV).to receive(:[]).with('SSL_CERT_DIR').and_return(cert_pool_dir)
92        allow(ENV).to receive(:[]).with('SSL_CERT_FILE').and_return(cert1_file)
93        expected_certs_paths = [cert1_file, File.join(cert_pool_dir, "gitalycert2.pem"), File.join(cert_pool_dir, "gitalycert3.pem")]
94
95        expected_certs = expected_certs_paths.map do |cert|
96          File.read cert
97        end.join("\n")
98        certs = client.certs
99        expect(certs).to eq expected_certs
100      end
101    end
102  end
103
104  describe 'Connectivity' do
105    context 'tcp' do
106      let(:client) do
107        get_client("tcp://localhost:#{GitalyConfig.dynamic_port('tcp')}")
108      end
109
110      it 'Should connect over tcp' do
111        expect(client).not_to be_empty
112      end
113    end
114
115    context 'unix' do
116      let(:client) { get_client("unix:#{File.join(TMP_DIR_NAME, SOCKET_PATH)}") }
117
118      it 'Should connect over unix' do
119        expect(client).not_to be_empty
120      end
121    end
122
123    context 'tls' do
124      let(:client) { get_client("tls://localhost:#{GitalyConfig.dynamic_port('tls')}") }
125
126      it 'Should connect over tls' do
127        cert = File.join(File.dirname(__FILE__), "testdata/certs/gitalycert.pem")
128        allow(ENV).to receive(:[]).with('GITLAB_TRACING').and_call_original
129        allow(ENV).to receive(:[]).with('SSL_CERT_DIR').and_return(nil)
130        allow(ENV).to receive(:[]).with('SSL_CERT_FILE').and_return(cert)
131
132        expect(client).not_to be_empty
133      end
134    end
135  end
136end
137