86 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| module Gitlab
 | |
|   class Throttle
 | |
|     DEFAULT_RATE_LIMITING_RESPONSE_TEXT = 'Retry later'
 | |
| 
 | |
|     # Each of these settings follows the same pattern of specifying separate
 | |
|     # authenticated and unauthenticated rates via settings. New throttles should
 | |
|     # ideally be regular as well.
 | |
|     REGULAR_THROTTLES = [:api, :packages_api, :files_api, :deprecated_api].freeze
 | |
| 
 | |
|     def self.settings
 | |
|       Gitlab::CurrentSettings.current_application_settings
 | |
|     end
 | |
| 
 | |
|     # Returns true if we should use the Admin Area protected paths throttle
 | |
|     def self.protected_paths_enabled?
 | |
|       self.settings.throttle_protected_paths_enabled?
 | |
|     end
 | |
| 
 | |
|     def self.omnibus_protected_paths_present?
 | |
|       Rack::Attack.throttles.key?('protected paths')
 | |
|     end
 | |
| 
 | |
|     def self.bypass_header
 | |
|       env_value = ENV['GITLAB_THROTTLE_BYPASS_HEADER']
 | |
|       return unless env_value.present?
 | |
| 
 | |
|       "HTTP_#{env_value.upcase.tr('-', '_')}"
 | |
|     end
 | |
| 
 | |
|     class << self
 | |
|       def options(throttle, authenticated:)
 | |
|         fragment = throttle_fragment!(throttle, authenticated: authenticated)
 | |
| 
 | |
|         # rubocop:disable GitlabSecurity/PublicSend
 | |
|         limit_proc = proc { |req| settings.public_send("#{fragment}_requests_per_period") }
 | |
|         period_proc = proc { |req| settings.public_send("#{fragment}_period_in_seconds").seconds }
 | |
|         # rubocop:enable GitlabSecurity/PublicSend
 | |
| 
 | |
|         { limit: limit_proc, period: period_proc }
 | |
|       end
 | |
| 
 | |
|       def throttle_fragment!(throttle, authenticated:)
 | |
|         raise("Unknown throttle: #{throttle}") unless REGULAR_THROTTLES.include?(throttle)
 | |
| 
 | |
|         "throttle_#{'un' unless authenticated}authenticated_#{throttle}"
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     def self.unauthenticated_web_options
 | |
|       # TODO: Columns will be renamed in https://gitlab.com/gitlab-org/gitlab/-/issues/340031
 | |
|       # Once this is done, web can be made into a regular throttle
 | |
|       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.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.protected_paths_options
 | |
|       limit_proc = proc { |req| settings.throttle_protected_paths_requests_per_period }
 | |
|       period_proc = proc { |req| settings.throttle_protected_paths_period_in_seconds.seconds }
 | |
| 
 | |
|       { limit: limit_proc, period: period_proc }
 | |
|     end
 | |
| 
 | |
|     def self.throttle_authenticated_git_lfs_options
 | |
|       limit_proc = proc { |req| settings.throttle_authenticated_git_lfs_requests_per_period }
 | |
|       period_proc = proc { |req| settings.throttle_authenticated_git_lfs_period_in_seconds.seconds }
 | |
| 
 | |
|       { limit: limit_proc, period: period_proc }
 | |
|     end
 | |
| 
 | |
|     def self.rate_limiting_response_text
 | |
|       (settings.rate_limiting_response_text.presence || DEFAULT_RATE_LIMITING_RESPONSE_TEXT) + "\n"
 | |
|     end
 | |
|   end
 | |
| end
 |