1# frozen_string_literal: true 2 3module Gitlab 4 module RackAttack 5 module Request 6 FILES_PATH_REGEX = %r{^/api/v\d+/projects/[^/]+/repository/files/.+}.freeze 7 GROUP_PATH_REGEX = %r{^/api/v\d+/groups/[^/]+/?$}.freeze 8 9 def unauthenticated? 10 !(authenticated_user_id([:api, :rss, :ics]) || authenticated_runner_id) 11 end 12 13 def throttled_user_id(request_formats) 14 user_id = authenticated_user_id(request_formats) 15 16 if Gitlab::RackAttack.user_allowlist.include?(user_id) 17 Gitlab::Instrumentation::Throttle.safelist = 'throttle_user_allowlist' 18 return 19 end 20 21 user_id 22 end 23 24 def authenticated_runner_id 25 request_authenticator.runner&.id 26 end 27 28 def api_request? 29 path.start_with?('/api') 30 end 31 32 def api_internal_request? 33 path =~ %r{^/api/v\d+/internal/} 34 end 35 36 def health_check_request? 37 path =~ %r{^/-/(health|liveness|readiness|metrics)} 38 end 39 40 def container_registry_event? 41 path =~ %r{^/api/v\d+/container_registry_event/} 42 end 43 44 def product_analytics_collector_request? 45 path.start_with?('/-/collector/i') 46 end 47 48 def should_be_skipped? 49 api_internal_request? || health_check_request? || container_registry_event? 50 end 51 52 def web_request? 53 !api_request? && !health_check_request? 54 end 55 56 def protected_path? 57 !protected_path_regex.nil? 58 end 59 60 def protected_path_regex 61 path =~ protected_paths_regex 62 end 63 64 def throttle?(throttle, authenticated:) 65 fragment = Gitlab::Throttle.throttle_fragment!(throttle, authenticated: authenticated) 66 67 __send__("#{fragment}?") # rubocop:disable GitlabSecurity/PublicSend 68 end 69 70 def throttle_unauthenticated_api? 71 api_request? && 72 !should_be_skipped? && 73 !throttle_unauthenticated_packages_api? && 74 !throttle_unauthenticated_files_api? && 75 !throttle_unauthenticated_deprecated_api? && 76 Gitlab::Throttle.settings.throttle_unauthenticated_api_enabled && 77 unauthenticated? 78 end 79 80 def throttle_unauthenticated_web? 81 web_request? && 82 !should_be_skipped? && 83 # TODO: Column will be renamed in https://gitlab.com/gitlab-org/gitlab/-/issues/340031 84 Gitlab::Throttle.settings.throttle_unauthenticated_enabled && 85 unauthenticated? 86 end 87 88 def throttle_authenticated_api? 89 api_request? && 90 !throttle_authenticated_packages_api? && 91 !throttle_authenticated_files_api? && 92 !throttle_authenticated_deprecated_api? && 93 Gitlab::Throttle.settings.throttle_authenticated_api_enabled 94 end 95 96 def throttle_authenticated_web? 97 web_request? && 98 !throttle_authenticated_git_lfs? && 99 Gitlab::Throttle.settings.throttle_authenticated_web_enabled 100 end 101 102 def throttle_unauthenticated_protected_paths? 103 post? && 104 !should_be_skipped? && 105 protected_path? && 106 Gitlab::Throttle.protected_paths_enabled? && 107 unauthenticated? 108 end 109 110 def throttle_authenticated_protected_paths_api? 111 post? && 112 api_request? && 113 protected_path? && 114 Gitlab::Throttle.protected_paths_enabled? 115 end 116 117 def throttle_authenticated_protected_paths_web? 118 post? && 119 web_request? && 120 protected_path? && 121 Gitlab::Throttle.protected_paths_enabled? 122 end 123 124 def throttle_unauthenticated_packages_api? 125 packages_api_path? && 126 Gitlab::Throttle.settings.throttle_unauthenticated_packages_api_enabled && 127 unauthenticated? 128 end 129 130 def throttle_authenticated_packages_api? 131 packages_api_path? && 132 Gitlab::Throttle.settings.throttle_authenticated_packages_api_enabled 133 end 134 135 def throttle_authenticated_git_lfs? 136 git_lfs_path? && 137 Gitlab::Throttle.settings.throttle_authenticated_git_lfs_enabled 138 end 139 140 def throttle_unauthenticated_files_api? 141 files_api_path? && 142 Gitlab::Throttle.settings.throttle_unauthenticated_files_api_enabled && 143 unauthenticated? 144 end 145 146 def throttle_authenticated_files_api? 147 files_api_path? && 148 Gitlab::Throttle.settings.throttle_authenticated_files_api_enabled 149 end 150 151 def throttle_unauthenticated_deprecated_api? 152 deprecated_api_request? && 153 Gitlab::Throttle.settings.throttle_unauthenticated_deprecated_api_enabled && 154 unauthenticated? 155 end 156 157 def throttle_authenticated_deprecated_api? 158 deprecated_api_request? && 159 Gitlab::Throttle.settings.throttle_authenticated_deprecated_api_enabled 160 end 161 162 private 163 164 def authenticated_user_id(request_formats) 165 request_authenticator.user(request_formats)&.id 166 end 167 168 def request_authenticator 169 @request_authenticator ||= Gitlab::Auth::RequestAuthenticator.new(self) 170 end 171 172 def protected_paths 173 Gitlab::CurrentSettings.current_application_settings.protected_paths 174 end 175 176 def protected_paths_regex 177 Regexp.union(protected_paths.map { |path| /\A#{Regexp.escape(path)}/ }) 178 end 179 180 def packages_api_path? 181 path =~ ::Gitlab::Regex::Packages::API_PATH_REGEX 182 end 183 184 def git_lfs_path? 185 path =~ Gitlab::PathRegex.repository_git_lfs_route_regex 186 end 187 188 def files_api_path? 189 path =~ FILES_PATH_REGEX 190 end 191 192 def deprecated_api_request? 193 # The projects member of the groups endpoint is deprecated. If left 194 # unspecified, with_projects defaults to true 195 with_projects = params['with_projects'] 196 with_projects = true if with_projects.blank? 197 198 path =~ GROUP_PATH_REGEX && Gitlab::Utils.to_boolean(with_projects) 199 end 200 end 201 end 202end 203::Gitlab::RackAttack::Request.prepend_mod_with('Gitlab::RackAttack::Request') 204