diff --git a/lib/travis/api/app.rb b/lib/travis/api/app.rb index a5b1a37a..7fa44e56 100644 --- a/lib/travis/api/app.rb +++ b/lib/travis/api/app.rb @@ -125,7 +125,7 @@ module Travis::Api use Travis::Api::App::Middleware::Metriks # make sure this is below ScopeCheck so we have the token - use Travis::Api::Attack + use Rack::Attack # if this is a v3 API request, ignore everything after use Travis::API::V3::OptIn diff --git a/lib/travis/api/attack.rb b/lib/travis/api/attack.rb index 47295c9d..bf82058b 100644 --- a/lib/travis/api/attack.rb +++ b/lib/travis/api/attack.rb @@ -1,72 +1,68 @@ require 'rack/attack' -module Travis::Api - class Attack < Rack::Attack - DalliProxy = Rack::Attack::DalliProxy # ? +class Rack::Attack + module RequestMixin + TOKEN = 'travis.access_token'.freeze + Rack::Attack::Request.prepend(self) - module Request - TOKEN = 'travis.access_token'.freeze - Rack::Attack::Request.prepend(self) - - def travis_token - env.fetch(TOKEN) - end - - def authenticated? - env.include? TOKEN - end - - def identifier - authenticated? ? travis_token.to_s : ip - end + def travis_token + env.fetch(TOKEN) end - def self.cache - Rack::Attack.cache + def authenticated? + env.include? TOKEN end - #### - # Ban based on: IP address - # Ban time: indefinite - # Ban after: manually banned - blacklist('block client requesting from redis') do |request| - Travis.redis.sismember(:api_blacklisted_ips, request.ip) - end - - #### - # Ban based on: IP address or access token - # Ban time: 1 hour - # Ban after: 10 POST requests within one minute to /auth/github - blacklist('hammering /auth/github') do |request| - Rack::Attack::Allow2Ban.filter(request.identifier, maxretry: 10, findtime: 1.minute, bantime: 1.hour) do - request.post? and request.path == '/auth/github' - end - end - - ### - # Throttle: unauthenticated requests - 50 per minute - # Scoped by: IP address - throttle('req/ip/1min', limit: 50, period: 1.minute) do |request| - request.ip unless request.authenticated? - end - - ### - # Throttle: authenticated requests - 100 per minute - # Scoped by: access token - throttle('req/token/1min', limit: 100, period: 1.minute) do |request| - request.identifier - end - - if ENV["MEMCACHIER_SERVERS"] - cache.store = Dalli::Client.new( - ENV["MEMCACHIER_SERVERS"].split(","), - username: ENV["MEMCACHIER_USERNAME"], - password: ENV["MEMCACHIER_PASSWORD"], - failover: true, - socket_timeout: 1.5, - socket_failure_delay: 0.2) - else - cache.store = ActiveSupport::Cache::MemoryStore.new + def identifier + authenticated? ? travis_token.to_s : ip end end + + def self.cache + Rack::Attack.cache + end + + #### + # Ban based on: IP address + # Ban time: indefinite + # Ban after: manually banned + blacklist('block client requesting from redis') do |request| + Travis.redis.sismember(:api_blacklisted_ips, request.ip) + end + + #### + # Ban based on: IP address or access token + # Ban time: 1 hour + # Ban after: 10 POST requests within one minute to /auth/github + blacklist('hammering /auth/github') do |request| + Rack::Attack::Allow2Ban.filter(request.identifier, maxretry: 10, findtime: 1.minute, bantime: 1.hour) do + request.post? and request.path == '/auth/github' + end + end + + ### + # Throttle: unauthenticated requests - 50 per minute + # Scoped by: IP address + throttle('req/ip/1min', limit: 50, period: 1.minute) do |request| + request.ip unless request.authenticated? + end + + ### + # Throttle: authenticated requests - 100 per minute + # Scoped by: access token + throttle('req/token/1min', limit: 100, period: 1.minute) do |request| + request.identifier + end + + if ENV["MEMCACHIER_SERVERS"] + cache.store = Dalli::Client.new( + ENV["MEMCACHIER_SERVERS"].split(","), + username: ENV["MEMCACHIER_USERNAME"], + password: ENV["MEMCACHIER_PASSWORD"], + failover: true, + socket_timeout: 1.5, + socket_failure_delay: 0.2) + else + cache.store = ActiveSupport::Cache::MemoryStore.new + end end