summaryrefslogtreecommitdiff
path: root/config/initializers/rack_attack_new.rb
blob: b0f7febe4273f376ad57ace4b85f08b84cc6c2ba (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
module Gitlab::Throttle
  def self.settings
    Gitlab::CurrentSettings.current_application_settings
  end

  def self.protected_paths_enabled?
    !self.omnibus_protected_paths_present? &&
      self.settings.throttle_protected_paths_enabled?
  end

  def self.omnibus_protected_paths_present?
    Rack::Attack.throttles.key?('protected paths')
  end

  def self.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.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.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
end

class Rack::Attack
  throttle('throttle_unauthenticated', Gitlab::Throttle.unauthenticated_options) do |req|
    Gitlab::Throttle.settings.throttle_unauthenticated_enabled &&
      req.unauthenticated? &&
      !req.should_be_skipped? &&
      req.ip
  end

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

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

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

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

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

  class Request
    def unauthenticated?
      !authenticated_user_id([:api, :rss, :ics])
    end

    def authenticated_user_id(request_formats)
      Gitlab::Auth::RequestAuthenticator.new(self).user(request_formats)&.id
    end

    def api_request?
      path.start_with?('/api')
    end

    def api_internal_request?
      path =~ %r{^/api/v\d+/internal/}
    end

    def should_be_skipped?
      api_internal_request?
    end

    def web_request?
      !api_request?
    end

    def protected_path?
      !protected_path_regex.nil?
    end

    def protected_path_regex
      path =~ protected_paths_regex
    end

    private

    def protected_paths
      Gitlab::CurrentSettings.current_application_settings.protected_paths
    end

    def protected_paths_regex
      Regexp.union(protected_paths.map { |path| /\A#{Regexp.escape(path)}/ })
    end
  end
end

::Rack::Attack.extend_if_ee('::EE::Gitlab::Rack::Attack') # rubocop: disable Cop/InjectEnterpriseEditionModule
::Rack::Attack::Request.prepend_if_ee('::EE::Gitlab::Rack::Attack::Request')