Skip to content

Commit

Permalink
Merge pull request #2268 from rubygems/colby/gem-push-limit
Browse files Browse the repository at this point in the history
Set new single throttle policy for gem push
  • Loading branch information
colby-swandale authored Mar 17, 2020
2 parents 09a3c65 + e78ff56 commit 9ee71da
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 13 deletions.
12 changes: 4 additions & 8 deletions config/initializers/rack_attack.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
class Rack::Attack
REQUEST_LIMIT = 100
PUSH_LIMIT = 150
REQUEST_LIMIT_PER_EMAIL = 10
LIMIT_PERIOD = 10.minutes
PUSH_LIMIT_PERIOD = 60.minutes

### Prevent Brute-Force Login Attacks ###

Expand Down Expand Up @@ -60,16 +62,10 @@ def self.protected_route?(protected_actions, path, method)
end
end

PUSH_LIMIT = 150
protected_push_action = [{ controller: "api/v1/rubygems", action: "create" }]

# 150 push in 10 min
# 450 push in 1000 min
# 600 push in 10000 min
[1, 3, 4].each do |level|
throttle("api/push/ip/#{level}", limit: PUSH_LIMIT * level, period: (LIMIT_PERIOD**level).seconds) do |req|
req.ip if protected_route?(protected_push_action, req.path, req.request_method)
end
throttle("api/push/ip", limit: PUSH_LIMIT, period: PUSH_LIMIT_PERIOD) do |req|
req.ip if protected_route?(protected_push_action, req.path, req.request_method)
end

# Throttle GET request for api_key by IP address
Expand Down
14 changes: 9 additions & 5 deletions test/integration/rack_attack_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def limit_period
Rack::Attack::LIMIT_PERIOD
end

def push_limit_period
Rack::Attack::PUSH_LIMIT_PERIOD
end

def exceed_limit_for(scope)
update_limit_for("#{scope}:#{@ip_address}", exceeding_limit)
end
Expand All @@ -39,7 +43,7 @@ def exceed_email_limit_for(scope)

def exceed_push_limit_for(scope)
exceeding_push_limit = (Rack::Attack::PUSH_LIMIT * 1.25).to_i
update_limit_for("#{scope}:#{@ip_address}", exceeding_push_limit)
update_limit_for("#{scope}:#{@ip_address}", exceeding_push_limit, push_limit_period)
end

def stay_under_limit_for(scope)
Expand All @@ -55,8 +59,8 @@ def stay_under_push_limit_for(scope)
update_limit_for("#{scope}:#{@user.email}", under_push_limit)
end

def update_limit_for(key, limit)
limit.times { Rack::Attack.cache.count(key, limit_period) }
def update_limit_for(key, limit, period = limit_period)
limit.times { Rack::Attack.cache.count(key, period) }
end

def exceed_exponential_limit_for(scope, level)
Expand Down Expand Up @@ -143,7 +147,7 @@ def encode(username, password)
end

should "allow gem push by ip" do
stay_under_push_limit_for("api/push/ip/1")
stay_under_push_limit_for("api/push/ip")

post "/api/v1/gems",
params: gem_file("test-1.0.0.gem").read,
Expand Down Expand Up @@ -331,7 +335,7 @@ def encode(username, password)
end

should "throttle gem push by ip" do
exceed_push_limit_for("api/push/ip/1")
exceed_push_limit_for("api/push/ip")

post "/api/v1/gems",
params: gem_file("test-1.0.0.gem").read,
Expand Down

0 comments on commit 9ee71da

Please sign in to comment.