Skip to content
Snippets Groups Projects
Commit dc9266fb authored by Michael Kozono's avatar Michael Kozono Committed by Francisco Javier López
Browse files

Add request throttles

parent 732b1226
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -11,8 +11,7 @@ class ApplicationController < ActionController::Base
include EnforcesTwoFactorAuthentication
include WithPerformanceBar
 
before_action :authenticate_user_from_personal_access_token!
before_action :authenticate_user_from_rss_token!
before_action :authenticate_sessionless_user!
before_action :authenticate_user!
before_action :validate_user_service_ticket!
before_action :check_password_expiration
Loading
Loading
@@ -100,6 +99,7 @@ class ApplicationController < ActionController::Base
return try(:authenticated_user)
end
 
<<<<<<< HEAD
def authenticate_user_from_personal_access_token!
token = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence
 
Loading
Loading
@@ -121,6 +121,14 @@ class ApplicationController < ActionController::Base
user = User.find_by_rss_token(token)
 
sessionless_sign_in(user)
=======
# This filter handles private tokens, personal access tokens, and atom
# requests with rss tokens
def authenticate_sessionless_user!
user = Gitlab::Auth.find_sessionless_user(request)
sessionless_sign_in(user) if user
>>>>>>> Add request throttles
end
 
def log_exception(exception)
Loading
Loading
Loading
Loading
@@ -231,6 +231,15 @@ module ApplicationSettingsHelper
:sign_in_text,
:signup_enabled,
:terminal_max_session_time,
:throttle_unauthenticated_enabled,
:throttle_unauthenticated_requests_per_period,
:throttle_unauthenticated_period_in_seconds,
:throttle_authenticated_web_enabled,
:throttle_authenticated_web_requests_per_period,
:throttle_authenticated_web_period_in_seconds,
:throttle_authenticated_api_enabled,
:throttle_authenticated_api_requests_per_period,
:throttle_authenticated_api_period_in_seconds,
:two_factor_grace_period,
:unique_ips_limit_enabled,
:unique_ips_limit_per_user,
Loading
Loading
Loading
Loading
@@ -743,5 +743,56 @@
installations. Set to 0 to completely disable polling.
= link_to icon('question-circle'), help_page_path('administration/polling')
 
%fieldset
%legend User and IP Rate Limits
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :throttle_unauthenticated_enabled do
= f.check_box :throttle_unauthenticated_enabled
Enable unauthenticated request rate limit
%span.help-block
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_unauthenticated_requests_per_period, 'Max requests per period per IP', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_unauthenticated_requests_per_period, class: 'form-control'
.form-group
= f.label :throttle_unauthenticated_period_in_seconds, 'Rate limit period in seconds', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_unauthenticated_period_in_seconds, class: 'form-control'
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :throttle_authenticated_api_enabled do
= f.check_box :throttle_authenticated_api_enabled
Enable authenticated API request rate limit
%span.help-block
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_authenticated_api_requests_per_period, 'Max requests per period per user', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_authenticated_api_requests_per_period, class: 'form-control'
.form-group
= f.label :throttle_authenticated_api_period_in_seconds, 'Rate limit period in seconds', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_authenticated_api_period_in_seconds, class: 'form-control'
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :throttle_authenticated_web_enabled do
= f.check_box :throttle_authenticated_web_enabled
Enable authenticated web request rate limit
%span.help-block
Helps reduce request volume (e.g. from crawlers or abusive bots)
.form-group
= f.label :throttle_authenticated_web_requests_per_period, 'Max requests per period per user', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_authenticated_web_requests_per_period, class: 'form-control'
.form-group
= f.label :throttle_authenticated_web_period_in_seconds, 'Rate limit period in seconds', class: 'control-label col-sm-2'
.col-sm-10
= f.number_field :throttle_authenticated_web_period_in_seconds, class: 'form-control'
.form-actions
= f.submit 'Save', class: 'btn btn-save'
---
title: Add anonymous rate limit per IP, and authenticated (web or API) rate limits
per user
merge_request: 14708
author:
type: added
Loading
Loading
@@ -113,7 +113,7 @@ module Gitlab
 
config.action_view.sanitized_allowed_protocols = %w(smb)
 
config.middleware.insert_before Warden::Manager, Rack::Attack
config.middleware.insert_after Warden::Manager, Rack::Attack
 
# Allow access to GitLab API from other domains
config.middleware.insert_before Warden::Manager, Rack::Cors do
Loading
Loading
class Rack::Attack
def self.settings
Gitlab::CurrentSettings.current_application_settings
end
def self.throttle_unauthenticated_options
limit_proc = proc { |req| settings.throttle_unauthenticated_requests_per_period }
period_proc = proc { |req| settings.throttle_unauthenticated_period_in_seconds.seconds }
{ limit: limit_proc, period: period_proc }
end
def self.throttle_authenticated_api_options
limit_proc = proc { |req| settings.throttle_authenticated_api_requests_per_period }
period_proc = proc { |req| settings.throttle_authenticated_api_period_in_seconds.seconds }
{ limit: limit_proc, period: period_proc }
end
def self.throttle_authenticated_web_options
limit_proc = proc { |req| settings.throttle_authenticated_web_requests_per_period }
period_proc = proc { |req| settings.throttle_authenticated_web_period_in_seconds.seconds }
{ limit: limit_proc, period: period_proc }
end
def self.define_throttles
throttle('throttle_unauthenticated', throttle_unauthenticated_options) do |req|
settings.throttle_unauthenticated_enabled &&
req.unauthenticated? &&
req.ip
end
throttle('throttle_authenticated_api', throttle_authenticated_api_options) do |req|
settings.throttle_authenticated_api_enabled &&
req.api_request? &&
req.authenticated_user_id
end
throttle('throttle_authenticated_web', throttle_authenticated_web_options) do |req|
settings.throttle_authenticated_web_enabled &&
req.web_request? &&
req.authenticated_user_id
end
end
define_throttles unless Rails.env.test?
class Request
def unauthenticated?
!authenticated_user_id
end
def authenticated_user_id
session_user_id || sessionless_user_id
end
def api_request?
path.start_with?('/api')
end
def web_request?
!api_request?
end
private
def session_user_id
Gitlab::Auth.find_session_user(self)&.id
end
def sessionless_user_id
Gitlab::Auth.find_sessionless_user(self)&.id
end
end
end
Loading
Loading
@@ -82,6 +82,36 @@ module Gitlab
end
end
 
# request may be Rack::Attack::Request which is just a Rack::Request, so
# we cannot use ActionDispatch::Request methods.
def find_user_by_private_token(request)
token = request.params['private_token'].presence || request.env['HTTP_PRIVATE_TOKEN'].presence
return unless token.present?
User.find_by_authentication_token(token) || User.find_by_personal_access_token(token)
end
# request may be Rack::Attack::Request which is just a Rack::Request, so
# we cannot use ActionDispatch::Request methods.
def find_user_by_rss_token(request)
return unless request.params['format'] == 'atom'
token = request.params['rss_token'].presence
return unless token.present?
User.find_by_rss_token(token)
end
def find_session_user(request)
request.env['warden']&.authenticate
end
def find_sessionless_user(request)
find_user_by_private_token(request) || find_user_by_rss_token(request)
end
private
 
def service_request_check(login, password, project)
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment