Add Rack::Attack Gem to Throttle Requests, Only Search to start (#6841) [deploy]
* throttle requests made to search endpoints * stub elasticsearch requests in rack attack specs and disable for running specs unless tagged * use original client IP from fastly to throttle requests to search endpoints
This commit is contained in:
parent
4baa9d3165
commit
55fe5a40a8
5 changed files with 45 additions and 0 deletions
1
Gemfile
1
Gemfile
|
|
@ -72,6 +72,7 @@ gem "puma", "~> 4.3" # Puma is a simple, fast, threaded, and highly concurrent H
|
|||
gem "pundit", "~> 2.1" # Object oriented authorization for Rails applications
|
||||
gem "pusher", "~> 1.3" # Ruby library for Pusher Channels HTTP API
|
||||
gem "pusher-push-notifications", "~> 1.1" # Pusher Push Notifications Ruby server SDK
|
||||
gem "rack-attack", "~> 6.2.2" # Used to throttle requests to prevent brute force attacks
|
||||
gem "rack-cors", "~> 1.1" # Middleware that will make Rack-based apps CORS compatible
|
||||
gem "rack-timeout", "~> 0.6" # Rack middleware which aborts requests that have been running for longer than a specified timeout
|
||||
gem "rails", "~> 5.2" # Ruby on Rails
|
||||
|
|
|
|||
|
|
@ -568,6 +568,8 @@ GEM
|
|||
rest-client (~> 2.0, >= 2.0.2)
|
||||
pusher-signature (0.1.8)
|
||||
rack (2.2.2)
|
||||
rack-attack (6.2.2)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-host-redirect (1.3.0)
|
||||
|
|
@ -958,6 +960,7 @@ DEPENDENCIES
|
|||
pundit-matchers (~> 1.6)
|
||||
pusher (~> 1.3)
|
||||
pusher-push-notifications (~> 1.1)
|
||||
rack-attack (~> 6.2.2)
|
||||
rack-cors (~> 1.1)
|
||||
rack-host-redirect (~> 1.3)
|
||||
rack-timeout (~> 0.6)
|
||||
|
|
|
|||
7
config/initializers/rack/attack.rb
Normal file
7
config/initializers/rack/attack.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
class Rack::Attack
|
||||
throttle("search_throttle", limit: 5, period: 1) do |request|
|
||||
if request.path.starts_with?("/search/") && request.env["HTTP_FASTLY_CLIENT_IP"].present?
|
||||
request.env["HTTP_FASTLY_CLIENT_IP"].to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
26
spec/initializers/rack/attack_spec.rb
Normal file
26
spec/initializers/rack/attack_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
require "rails_helper"
|
||||
|
||||
describe Rack::Attack, type: :request, throttle: true do
|
||||
describe "search_throttle" do
|
||||
before do
|
||||
redis_url = "redis://localhost:6379"
|
||||
cache_db = ActiveSupport::Cache::RedisStore.new(redis_url)
|
||||
allow(Rails).to receive(:cache) { cache_db }
|
||||
end
|
||||
|
||||
it "throttles /search endpoints based on IP" do
|
||||
Timecop.freeze do
|
||||
allow(Search::User).to receive(:search_documents).and_return({})
|
||||
valid_responses = Array.new(5).map do
|
||||
get "/search/users", headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
||||
end
|
||||
throttled_response = get "/search/users", headers: { "HTTP_FASTLY_CLIENT_IP" => "5.6.7.8" }
|
||||
new_ip_response = get "/search/users", headers: { "HTTP_FASTLY_CLIENT_IP" => "1.1.1.1" }
|
||||
|
||||
valid_responses.each { |r| expect(r).not_to eq(429) }
|
||||
expect(throttled_response).to eq(429)
|
||||
expect(new_ip_response).not_to eq(429)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -53,6 +53,8 @@ WebMock.disable_net_connect!(allow_localhost: true, allow: allowed_sites)
|
|||
|
||||
RSpec::Matchers.define_negated_matcher :not_change, :change
|
||||
|
||||
Rack::Attack.enabled = false
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.use_transactional_fixtures = true
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
|
|
@ -77,6 +79,12 @@ RSpec.configure do |config|
|
|||
example.run
|
||||
end
|
||||
|
||||
config.around(:each, throttle: true) do |example|
|
||||
Rack::Attack.enabled = true
|
||||
example.run
|
||||
Rack::Attack.enabled = false
|
||||
end
|
||||
|
||||
config.after do
|
||||
SiteConfig.clear_cache
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue