Welcome to mirror list, hosted at ThFree Co, Russian Federation.

rack_attack.rb « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 222f5d57adfe0b891a7140ee167ed445ea3a6b7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# frozen_string_literal: true

# Integration specs for throttling can be found in:
# spec/requests/rack_attack_global_spec.rb
module Gitlab
  module RackAttack
    def self.configure(rack_attack)
      # This adds some methods used by our throttles to the `Rack::Request`
      rack_attack::Request.include(Gitlab::RackAttack::Request)
      # Configure the throttles
      configure_throttles(rack_attack)
    end

    def self.configure_throttles(rack_attack)
      throttle_or_track(rack_attack, 'throttle_unauthenticated', Gitlab::Throttle.unauthenticated_options) do |req|
        if !req.should_be_skipped? &&
           Gitlab::Throttle.settings.throttle_unauthenticated_enabled &&
           req.unauthenticated?
          req.ip
        end
      end

      throttle_or_track(rack_attack, 'throttle_authenticated_api', Gitlab::Throttle.authenticated_api_options) do |req|
        if req.api_request? &&
           Gitlab::Throttle.settings.throttle_authenticated_api_enabled
          req.authenticated_user_id([:api])
        end
      end

      # Product analytics feature is in experimental stage.
      # At this point we want to limit amount of events registered
      # per application (aid stands for application id).
      throttle_or_track(rack_attack, 'throttle_product_analytics_collector', limit: 100, period: 60) do |req|
        if req.product_analytics_collector_request?
          req.params['aid']
        end
      end

      throttle_or_track(rack_attack, 'throttle_authenticated_web', Gitlab::Throttle.authenticated_web_options) do |req|
        if req.web_request? &&
           Gitlab::Throttle.settings.throttle_authenticated_web_enabled
          req.authenticated_user_id([:api, :rss, :ics])
        end
      end

      throttle_or_track(rack_attack, 'throttle_unauthenticated_protected_paths', Gitlab::Throttle.protected_paths_options) do |req|
        if req.post? &&
           !req.should_be_skipped? &&
           req.protected_path? &&
           Gitlab::Throttle.protected_paths_enabled? &&
           req.unauthenticated?
          req.ip
        end
      end

      throttle_or_track(rack_attack, 'throttle_authenticated_protected_paths_api', Gitlab::Throttle.protected_paths_options) do |req|
        if req.post? &&
           req.api_request? &&
           req.protected_path? &&
           Gitlab::Throttle.protected_paths_enabled?
          req.authenticated_user_id([:api])
        end
      end

      throttle_or_track(rack_attack, 'throttle_authenticated_protected_paths_web', Gitlab::Throttle.protected_paths_options) do |req|
        if req.post? &&
           req.web_request? &&
           req.protected_path? &&
           Gitlab::Throttle.protected_paths_enabled?
          req.authenticated_user_id([:api, :rss, :ics])
        end
      end

      rack_attack.safelist('throttle_bypass_header') do |req|
        Gitlab::Throttle.bypass_header.present? &&
          req.get_header(Gitlab::Throttle.bypass_header) == '1'
      end
    end

    def self.throttle_or_track(rack_attack, throttle_name, *args, &block)
      if track?(throttle_name)
        rack_attack.track(throttle_name, *args, &block)
      else
        rack_attack.throttle(throttle_name, *args, &block)
      end
    end

    def self.track?(name)
      dry_run_config = ENV['GITLAB_THROTTLE_DRY_RUN'].to_s.strip

      return false if dry_run_config.empty?
      return true if dry_run_config == '*'

      dry_run_config.split(',').map(&:strip).include?(name)
    end
  end
end
::Gitlab::RackAttack.prepend_if_ee('::EE::Gitlab::RackAttack')