read_only_spec.rb 5.3 KB
Newer Older
T
Toon Claes 已提交
1 2 3 4
require 'spec_helper'

describe Gitlab::Middleware::ReadOnly do
  include Rack::Test::Methods
5
  using RSpec::Parameterized::TableSyntax
T
Toon Claes 已提交
6 7 8 9 10 11 12 13 14 15 16

  let(:rack_stack) do
    rack = Rack::Builder.new do
      use ActionDispatch::Session::CacheStore
      use ActionDispatch::Flash
    end

    rack.run(subject)
    rack.to_app
  end

17 18 19 20 21 22 23 24 25 26 27
  let(:observe_env) do
    Module.new do
      attr_reader :env

      def call(env)
        @env = env
        super
      end
    end
  end

28 29
  let(:request) { Rack::MockRequest.new(rack_stack) }

30
  subject do
31 32 33
    described_class.new(fake_app).tap do |app|
      app.extend(observe_env)
    end
34
  end
T
Toon Claes 已提交
35

36
  context 'normal requests to a read-only GitLab instance' do
T
Toon Claes 已提交
37 38 39 40 41 42 43 44 45
    let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['OK']] } }

    before do
      allow(Gitlab::Database).to receive(:read_only?) { true }
    end

    it 'expects PATCH requests to be disallowed' do
      response = request.patch('/test_request')

46
      expect(response).to be_redirect
T
Toon Claes 已提交
47 48 49 50 51 52
      expect(subject).to disallow_request
    end

    it 'expects PUT requests to be disallowed' do
      response = request.put('/test_request')

53
      expect(response).to be_redirect
T
Toon Claes 已提交
54 55 56 57 58 59
      expect(subject).to disallow_request
    end

    it 'expects POST requests to be disallowed' do
      response = request.post('/test_request')

60
      expect(response).to be_redirect
T
Toon Claes 已提交
61 62 63 64 65 66
      expect(subject).to disallow_request
    end

    it 'expects a internal POST request to be allowed after a disallowed request' do
      response = request.post('/test_request')

67
      expect(response).to be_redirect
T
Toon Claes 已提交
68 69 70

      response = request.post("/api/#{API::API.version}/internal")

71
      expect(response).not_to be_redirect
T
Toon Claes 已提交
72 73 74 75 76
    end

    it 'expects DELETE requests to be disallowed' do
      response = request.delete('/test_request')

77
      expect(response).to be_redirect
T
Toon Claes 已提交
78 79 80
      expect(subject).to disallow_request
    end

81
    it 'expects POST of new file that looks like an LFS batch url to be disallowed' do
82
      expect(Rails.application.routes).to receive(:recognize_path).and_call_original
83 84
      response = request.post('/root/gitlab-ce/new/master/app/info/lfs/objects/batch')

85
      expect(response).to be_redirect
86 87 88
      expect(subject).to disallow_request
    end

89 90 91 92 93 94
    it 'returns last_vistited_url for disallowed request' do
      response = request.post('/test_request')

      expect(response.location).to eq 'http://localhost/'
    end

T
Toon Claes 已提交
95 96
    context 'whitelisted requests' do
      it 'expects a POST internal request to be allowed' do
97
        expect(Rails.application.routes).not_to receive(:recognize_path)
T
Toon Claes 已提交
98 99
        response = request.post("/api/#{API::API.version}/internal")

100
        expect(response).not_to be_redirect
T
Toon Claes 已提交
101 102 103
        expect(subject).not_to disallow_request
      end

104 105 106 107 108 109 110 111 112 113 114
      context 'sidekiq admin requests' do
        where(:mounted_at) do
          [
            '',
            '/',
            '/gitlab',
            '/gitlab/',
            '/gitlab/gitlab',
            '/gitlab/gitlab/'
          ]
        end
T
Toon Claes 已提交
115

116 117 118 119
        with_them do
          before do
            stub_config_setting(relative_url_root: mounted_at)
          end
120

121 122 123
          it 'allows requests' do
            path = File.join(mounted_at, 'admin/sidekiq')
            response = request.post(path)
124

125 126 127 128 129 130 131 132 133
            expect(response).not_to be_redirect
            expect(subject).not_to disallow_request

            response = request.get(path)

            expect(response).not_to be_redirect
            expect(subject).not_to disallow_request
          end
        end
134 135
      end

136 137 138 139 140 141 142 143
      where(:description, :path) do
        'LFS request to batch'        | '/root/rouge.git/info/lfs/objects/batch'
        'LFS request to locks verify' | '/root/rouge.git/info/lfs/locks/verify'
        'LFS request to locks create' | '/root/rouge.git/info/lfs/locks'
        'LFS request to locks unlock' | '/root/rouge.git/info/lfs/locks/1/unlock'
        'request to git-upload-pack'  | '/root/rouge.git/git-upload-pack'
        'request to git-receive-pack' | '/root/rouge.git/git-receive-pack'
      end
144

145 146 147 148
      with_them do
        it "expects a POST #{description} URL to be allowed" do
          expect(Rails.application.routes).to receive(:recognize_path).and_call_original
          response = request.post(path)
149

150
          expect(response).not_to be_redirect
151 152
          expect(subject).not_to disallow_request
        end
153
      end
T
Toon Claes 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    end
  end

  context 'json requests to a read-only GitLab instance' do
    let(:fake_app) { lambda { |env| [200, { 'Content-Type' => 'application/json' }, ['OK']] } }
    let(:content_json) { { 'CONTENT_TYPE' => 'application/json' } }

    before do
      allow(Gitlab::Database).to receive(:read_only?) { true }
    end

    it 'expects PATCH requests to be disallowed' do
      response = request.patch('/test_request', content_json)

      expect(response).to disallow_request_in_json
    end

    it 'expects PUT requests to be disallowed' do
      response = request.put('/test_request', content_json)

      expect(response).to disallow_request_in_json
    end

    it 'expects POST requests to be disallowed' do
      response = request.post('/test_request', content_json)

      expect(response).to disallow_request_in_json
    end

    it 'expects DELETE requests to be disallowed' do
      response = request.delete('/test_request', content_json)

      expect(response).to disallow_request_in_json
    end
  end
end