summaryrefslogtreecommitdiff
path: root/spec/requests/rack_attack_global_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/requests/rack_attack_global_spec.rb')
-rw-r--r--spec/requests/rack_attack_global_spec.rb183
1 files changed, 155 insertions, 28 deletions
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index cf459ba99c1..ca8720cd414 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe 'Rack Attack global throttles' do
+ include RackAttackSpecHelpers
+
let(:settings) { Gitlab::CurrentSettings.current_application_settings }
# Start with really high limits and override them with low limits to ensure
@@ -12,7 +14,9 @@ describe 'Rack Attack global throttles' do
throttle_authenticated_api_requests_per_period: 100,
throttle_authenticated_api_period_in_seconds: 1,
throttle_authenticated_web_requests_per_period: 100,
- throttle_authenticated_web_period_in_seconds: 1
+ throttle_authenticated_web_period_in_seconds: 1,
+ throttle_authenticated_protected_paths_request_per_period: 100,
+ throttle_authenticated_protected_paths_in_seconds: 1
}
end
@@ -20,21 +24,17 @@ describe 'Rack Attack global throttles' do
let(:period_in_seconds) { 10000 }
let(:period) { period_in_seconds.seconds }
- around do |example|
- # Instead of test environment's :null_store so the throttles can increment
- Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
-
- # Make time-dependent tests deterministic
- Timecop.freeze { example.run }
-
- Rack::Attack.cache.store = Rails.cache
- end
+ include_context 'rack attack cache store'
describe 'unauthenticated requests' do
let(:url_that_does_not_require_authentication) { '/users/sign_in' }
let(:url_api_internal) { '/api/v4/internal/check' }
before do
+ # Disabling protected paths throttle, otherwise requests to
+ # '/users/sign_in' are caught by this throttle.
+ settings_to_set[:throttle_protected_paths_enabled] = false
+
# Set low limits
settings_to_set[:throttle_unauthenticated_requests_per_period] = requests_per_period
settings_to_set[:throttle_unauthenticated_period_in_seconds] = period_in_seconds
@@ -203,29 +203,156 @@ describe 'Rack Attack global throttles' do
it_behaves_like 'rate-limited web authenticated requests'
end
- def api_get_args_with_token_headers(partial_url, token_headers)
- ["/api/#{API::API.version}#{partial_url}", params: nil, headers: token_headers]
- end
+ describe 'protected paths' do
+ context 'unauthenticated requests' do
+ let(:protected_path_that_does_not_require_authentication) do
+ '/users/confirmation'
+ end
- def rss_url(user)
- "/dashboard/projects.atom?feed_token=#{user.feed_token}"
- end
+ before do
+ settings_to_set[:throttle_protected_paths_requests_per_period] = requests_per_period # 1
+ settings_to_set[:throttle_protected_paths_period_in_seconds] = period_in_seconds # 10_000
+ end
- def private_token_headers(user)
- { 'HTTP_PRIVATE_TOKEN' => user.private_token }
- end
+ context 'when protected paths throttle is disabled' do
+ before do
+ settings_to_set[:throttle_protected_paths_enabled] = false
+ stub_application_setting(settings_to_set)
+ end
- def personal_access_token_headers(personal_access_token)
- { 'HTTP_PRIVATE_TOKEN' => personal_access_token.token }
- end
+ it 'allows requests over the rate limit' do
+ (1 + requests_per_period).times do
+ get protected_path_that_does_not_require_authentication
+ expect(response).to have_http_status 200
+ end
+ end
+ end
- def oauth_token_headers(oauth_access_token)
- { 'AUTHORIZATION' => "Bearer #{oauth_access_token.token}" }
- end
+ context 'when protected paths throttle is enabled' do
+ before do
+ settings_to_set[:throttle_protected_paths_enabled] = true
+ stub_application_setting(settings_to_set)
+ end
+
+ it 'rejects requests over the rate limit' do
+ requests_per_period.times do
+ get protected_path_that_does_not_require_authentication
+ expect(response).to have_http_status 200
+ end
+
+ expect_rejection { get protected_path_that_does_not_require_authentication }
+ end
+
+ context 'when Omnibus throttle is present' do
+ before do
+ allow(Gitlab::Throttle)
+ .to receive(:omnibus_protected_paths_present?).and_return(true)
+ end
+
+ it 'allows requests over the rate limit' do
+ (1 + requests_per_period).times do
+ get protected_path_that_does_not_require_authentication
+ expect(response).to have_http_status 200
+ end
+ end
+ end
+ end
+ end
+
+ context 'API requests authenticated with personal access token', :api do
+ let(:user) { create(:user) }
+ let(:token) { create(:personal_access_token, user: user) }
+ let(:other_user) { create(:user) }
+ let(:other_user_token) { create(:personal_access_token, user: other_user) }
+ let(:throttle_setting_prefix) { 'throttle_protected_paths' }
+ let(:api_partial_url) { '/users' }
+
+ let(:protected_paths) do
+ [
+ '/api/v4/users'
+ ]
+ end
+
+ before do
+ settings_to_set[:protected_paths] = protected_paths
+ stub_application_setting(settings_to_set)
+ end
+
+ context 'with the token in the query string' do
+ let(:get_args) { [api(api_partial_url, personal_access_token: token)] }
+ let(:other_user_get_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+
+ context 'with the token in the headers' do
+ let(:get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(token)) }
+ let(:other_user_get_args) { api_get_args_with_token_headers(api_partial_url, personal_access_token_headers(other_user_token)) }
+
+ it_behaves_like 'rate-limited token-authenticated requests'
+ end
+
+ context 'when Omnibus throttle is present' do
+ let(:get_args) { [api(api_partial_url, personal_access_token: token)] }
+ let(:other_user_get_args) { [api(api_partial_url, personal_access_token: other_user_token)] }
+
+ before do
+ settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
+ settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds
+ settings_to_set[:"#{throttle_setting_prefix}_enabled"] = true
+ stub_application_setting(settings_to_set)
+
+ allow(Gitlab::Throttle)
+ .to receive(:omnibus_protected_paths_present?).and_return(true)
+ end
+
+ it 'allows requests over the rate limit' do
+ (1 + requests_per_period).times do
+ get(*get_args)
+ expect(response).to have_http_status 200
+ end
+ end
+ end
+ end
+
+ describe 'web requests authenticated with regular login' do
+ let(:throttle_setting_prefix) { 'throttle_protected_paths' }
+ let(:user) { create(:user) }
+ let(:url_that_requires_authentication) { '/dashboard/snippets' }
+
+ let(:protected_paths) do
+ [
+ url_that_requires_authentication
+ ]
+ end
+
+ before do
+ settings_to_set[:protected_paths] = protected_paths
+ stub_application_setting(settings_to_set)
+ end
+
+ it_behaves_like 'rate-limited web authenticated requests'
+
+ context 'when Omnibus throttle is present' do
+ before do
+ settings_to_set[:"#{throttle_setting_prefix}_requests_per_period"] = requests_per_period
+ settings_to_set[:"#{throttle_setting_prefix}_period_in_seconds"] = period_in_seconds
+ settings_to_set[:"#{throttle_setting_prefix}_enabled"] = true
+ stub_application_setting(settings_to_set)
- def expect_rejection(&block)
- yield
+ allow(Gitlab::Throttle)
+ .to receive(:omnibus_protected_paths_present?).and_return(true)
- expect(response).to have_http_status(429)
+ login_as(user)
+ end
+
+ it 'allows requests over the rate limit' do
+ (1 + requests_per_period).times do
+ get url_that_requires_authentication
+ expect(response).to have_http_status 200
+ end
+ end
+ end
+ end
end
end