mirror of
https://github.com/samsonjs/rack-attack.git
synced 2026-03-25 09:25:49 +00:00
Merge pull request #431 from fatkodima/use-middleware
Auto plug middleware for simpler installation
This commit is contained in:
commit
95347e35f1
12 changed files with 111 additions and 26 deletions
14
Appraisals
14
Appraisals
|
|
@ -17,24 +17,20 @@ appraise "rack_1_6" do
|
|||
gem "rack-test", ">= 0.6"
|
||||
end
|
||||
|
||||
appraise 'rails_6_0' do
|
||||
gem 'actionpack', '~> 6.0.0'
|
||||
gem 'activesupport', '~> 6.0.0'
|
||||
appraise 'rails_6-0' do
|
||||
gem 'railties', '~> 6.0.0'
|
||||
end
|
||||
|
||||
appraise 'rails_5-2' do
|
||||
gem 'actionpack', '~> 5.2.0'
|
||||
gem 'activesupport', '~> 5.2.0'
|
||||
gem 'railties', '~> 5.2.0'
|
||||
end
|
||||
|
||||
appraise 'rails_5-1' do
|
||||
gem 'actionpack', '~> 5.1.0'
|
||||
gem 'activesupport', '~> 5.1.0'
|
||||
gem 'railties', '~> 5.1.0'
|
||||
end
|
||||
|
||||
appraise 'rails_4-2' do
|
||||
gem 'actionpack', '~> 4.2.0'
|
||||
gem 'activesupport', '~> 4.2.0'
|
||||
gem 'railties', '~> 4.2.0'
|
||||
|
||||
# Override rack-test version constraint by making it more loose
|
||||
# so it's compatible with actionpack 4.2.x
|
||||
|
|
|
|||
|
|
@ -68,14 +68,19 @@ Or install it yourself as:
|
|||
|
||||
Then tell your ruby web application to use rack-attack as a middleware.
|
||||
|
||||
a) For __rails__ applications:
|
||||
|
||||
a) For __rails__ applications with versions >= 5 it is used by default. For older rails versions you should enable it explicitly:
|
||||
```ruby
|
||||
# In config/application.rb
|
||||
|
||||
config.middleware.use Rack::Attack
|
||||
```
|
||||
|
||||
You can disable it permanently (like for specific environment) or temporarily (can be useful for specific test cases) by writing:
|
||||
|
||||
```ruby
|
||||
Rack::Attack.enabled = false
|
||||
```
|
||||
|
||||
b) For __rack__ applications:
|
||||
|
||||
```ruby
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 4.2.0"
|
||||
gem "activesupport", "~> 4.2.0"
|
||||
gem "railties", "~> 4.2.0"
|
||||
gem "rack-test", ">= 0.6"
|
||||
|
||||
gemspec path: "../"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 5.1.0"
|
||||
gem "activesupport", "~> 5.1.0"
|
||||
gem "railties", "~> 5.1.0"
|
||||
|
||||
gemspec path: "../"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 5.2.0"
|
||||
gem "activesupport", "~> 5.2.0"
|
||||
gem "railties", "~> 5.2.0"
|
||||
|
||||
gemspec path: "../"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 6.0.0"
|
||||
gem "activesupport", "~> 6.0.0"
|
||||
gem "railties", "~> 6.0.0"
|
||||
|
||||
gemspec path: "../"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ require 'rack/attack/path_normalizer'
|
|||
require 'rack/attack/request'
|
||||
require "ipaddr"
|
||||
|
||||
require 'rack/attack/railtie' if defined?(::Rails)
|
||||
|
||||
module Rack
|
||||
class Attack
|
||||
class MisconfiguredStoreError < StandardError; end
|
||||
|
|
@ -28,7 +30,8 @@ module Rack
|
|||
autoload :Allow2Ban, 'rack/attack/allow2ban'
|
||||
|
||||
class << self
|
||||
attr_accessor :notifier, :blocklisted_response, :throttled_response, :anonymous_blocklists, :anonymous_safelists
|
||||
attr_accessor :enabled, :notifier, :blocklisted_response, :throttled_response,
|
||||
:anonymous_blocklists, :anonymous_safelists
|
||||
|
||||
def safelist(name = nil, &block)
|
||||
safelist = Safelist.new(name, &block)
|
||||
|
|
@ -134,6 +137,7 @@ module Rack
|
|||
end
|
||||
|
||||
# Set defaults
|
||||
@enabled = true
|
||||
@anonymous_blocklists = []
|
||||
@anonymous_safelists = []
|
||||
@notifier = ActiveSupport::Notifications if defined?(ActiveSupport::Notifications)
|
||||
|
|
@ -148,6 +152,8 @@ module Rack
|
|||
end
|
||||
|
||||
def call(env)
|
||||
return @app.call(env) unless self.class.enabled
|
||||
|
||||
env['PATH_INFO'] = PathNormalizer.normalize_path(env['PATH_INFO'])
|
||||
request = Rack::Attack::Request.new(env)
|
||||
|
||||
|
|
|
|||
21
lib/rack/attack/railtie.rb
Normal file
21
lib/rack/attack/railtie.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Rack
|
||||
class Attack
|
||||
class Railtie < ::Rails::Railtie
|
||||
initializer 'rack.attack.middleware', after: :load_config_initializers, before: :build_middleware_stack do |app|
|
||||
if Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new("5")
|
||||
middlewares = app.config.middleware
|
||||
operations = middlewares.send(:operations) + middlewares.send(:delete_operations)
|
||||
|
||||
use_middleware = operations.none? do |operation|
|
||||
middleware = operation[1]
|
||||
middleware.include?(Rack::Attack)
|
||||
end
|
||||
|
||||
middlewares.use(Rack::Attack) if use_middleware
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -46,8 +46,5 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency 'byebug', '~> 11.0'
|
||||
end
|
||||
|
||||
# The following are potential runtime dependencies users may have,
|
||||
# which rack-attack uses only for testing compatibility in test suite.
|
||||
s.add_development_dependency 'actionpack', '~> 5.2'
|
||||
s.add_development_dependency 'activesupport', '~> 5.2'
|
||||
s.add_development_dependency 'railties', '>= 4.2'
|
||||
end
|
||||
|
|
|
|||
41
spec/acceptance/rails_middleware_spec.rb
Normal file
41
spec/acceptance/rails_middleware_spec.rb
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../spec_helper"
|
||||
|
||||
if defined?(Rails)
|
||||
describe "Middleware for Rails" do
|
||||
before do
|
||||
@app = Class.new(Rails::Application) do
|
||||
config.eager_load = false
|
||||
config.logger = Logger.new(nil) # avoid creating the log/ directory automatically
|
||||
config.cache_store = :null_store # avoid creating tmp/ directory for cache
|
||||
end
|
||||
end
|
||||
|
||||
if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new("5")
|
||||
it "is used by default" do
|
||||
@app.initialize!
|
||||
assert_equal 1, @app.middleware.count(Rack::Attack)
|
||||
end
|
||||
|
||||
it "is not added when it was added explicitly" do
|
||||
@app.config.middleware.use(Rack::Attack)
|
||||
@app.initialize!
|
||||
assert_equal 1, @app.middleware.count(Rack::Attack)
|
||||
end
|
||||
|
||||
it "is not added when it was explicitly deleted" do
|
||||
@app.config.middleware.delete(Rack::Attack)
|
||||
@app.initialize!
|
||||
refute @app.middleware.include?(Rack::Attack)
|
||||
end
|
||||
end
|
||||
|
||||
if Gem::Version.new(Rails::VERSION::STRING) < Gem::Version.new("5")
|
||||
it "is not used by default" do
|
||||
@app.initialize!
|
||||
assert_equal 0, @app.middleware.count(Rack::Attack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -76,4 +76,27 @@ describe 'Rack::Attack' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'enabled' do
|
||||
it 'should be enabled by default' do
|
||||
_(Rack::Attack.enabled).must_equal true
|
||||
end
|
||||
|
||||
it 'should directly pass request when disabled' do
|
||||
bad_ip = '1.2.3.4'
|
||||
Rack::Attack.blocklist("ip #{bad_ip}") { |req| req.ip == bad_ip }
|
||||
|
||||
get '/', {}, 'REMOTE_ADDR' => bad_ip
|
||||
_(last_response.status).must_equal 403
|
||||
|
||||
prev_enabled = Rack::Attack.enabled
|
||||
begin
|
||||
Rack::Attack.enabled = false
|
||||
get '/', {}, 'REMOTE_ADDR' => bad_ip
|
||||
_(last_response.status).must_equal 200
|
||||
ensure
|
||||
Rack::Attack.enabled = prev_enabled
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ require "bundler/setup"
|
|||
require "minitest/autorun"
|
||||
require "minitest/pride"
|
||||
require "rack/test"
|
||||
require 'active_support'
|
||||
require 'action_dispatch'
|
||||
require "rails"
|
||||
|
||||
require "rack/attack"
|
||||
|
||||
|
|
@ -30,6 +29,7 @@ class MiniTest::Spec
|
|||
include Rack::Test::Methods
|
||||
|
||||
before do
|
||||
Rails.cache = nil
|
||||
@_original_throttled_response = Rack::Attack.throttled_response
|
||||
@_original_blocklisted_response = Rack::Attack.blocklisted_response
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue