FEATURE: Add global admin api key rate limiter (#12527)

This commit is contained in:
David Taylor 2021-06-03 10:52:43 +01:00 committed by GitHub
parent 58b30fb510
commit 4134173bbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 11 deletions

View File

@ -225,7 +225,7 @@ s3_install_cors_rule =
max_user_api_reqs_per_minute = 20
max_user_api_reqs_per_day = 2880
max_admin_api_reqs_per_key_per_minute = 60
max_admin_api_reqs_per_minute = 60
max_reqs_per_ip_per_minute = 200
max_reqs_per_ip_per_10_seconds = 50

View File

@ -131,7 +131,7 @@ class Auth::DefaultCurrentUserProvider
raise Discourse::InvalidAccess.new(I18n.t('invalid_api_credentials'), nil, custom_message: "invalid_api_credentials") unless current_user
raise Discourse::InvalidAccess if current_user.suspended? || !current_user.active
@env[API_KEY_ENV] = true
rate_limit_admin_api_requests(api_key)
rate_limit_admin_api_requests!
end
# user api key handling
@ -377,15 +377,23 @@ class Auth::DefaultCurrentUserProvider
!!@env[HEADER_API_KEY]
end
def rate_limit_admin_api_requests(api_key)
def rate_limit_admin_api_requests!
return if Rails.env == "profile"
RateLimiter.new(
limit = GlobalSetting.max_admin_api_reqs_per_minute.to_i
if GlobalSetting.respond_to?(:max_admin_api_reqs_per_key_per_minute)
Discourse.deprecate("DISCOURSE_MAX_ADMIN_API_REQS_PER_KEY_PER_MINUTE is deprecated. Please use DISCOURSE_MAX_ADMIN_API_REQS_PER_MINUTE")
limit = [ GlobalSetting.max_admin_api_reqs_per_key_per_minute.to_i, limit].max
end
global_limit = RateLimiter.new(
nil,
"admin_api_min_#{ApiKey.hash_key(api_key)}",
GlobalSetting.max_admin_api_reqs_per_key_per_minute,
"admin_api_min",
limit,
60
).performed!
)
global_limit.performed!
end
def can_write?

View File

@ -195,10 +195,11 @@ describe Auth::DefaultCurrentUserProvider do
RateLimiter.enable
end
it "rate limits api requests per api key" do
global_setting :max_admin_api_reqs_per_key_per_minute, 3
it "rate limits admin api requests" do
global_setting :max_admin_api_reqs_per_minute, 3
freeze_time
RateLimiter.new(nil, "admin_api_min", 3, 60).clear!
api_key = ApiKey.create!(created_by_id: -1)
params = { "HTTP_API_KEY" => api_key.key, "HTTP_API_USERNAME" => user.username.downcase }

View File

@ -49,12 +49,13 @@ describe 'rate limiter integration' do
it 'can cleanly limit requests and sets a Retry-After header' do
freeze_time
#request.set_header("action_dispatch.show_exceptions", true)
RateLimiter.clear_all!
admin = Fabricate(:admin)
api_key = Fabricate(:api_key, user: admin)
global_setting :max_admin_api_reqs_per_key_per_minute, 1
global_setting :max_admin_api_reqs_per_minute, 1
get '/admin/api/keys.json', headers: {
HTTP_API_KEY: api_key.key,