diff options
author | Pawel Chojnacki <pawel@chojnacki.ws> | 2017-02-20 15:09:05 +0100 |
---|---|---|
committer | Pawel Chojnacki <pawel@chojnacki.ws> | 2017-03-06 15:41:25 +0100 |
commit | 0ef8a643489ad1a3da4431155326f0a6e206d870 (patch) | |
tree | beb7bceb362f627e4864075e76d05e81f9b743da | |
parent | 9cc0ff8f468c54e23172492d97f6d9b428d3ad2e (diff) | |
download | gitlab-ce-0ef8a643489ad1a3da4431155326f0a6e206d870.tar.gz |
Remove unecessary calls to limit_user!, UniqueIps Middleware, and address MR review
- cleanup formating in haml
- clarify time window is in seconds
- cleanup straneous chunks in db/schema
- rename count_uniqe_ips to update_and_return_ips_count
- other
-rw-r--r-- | app/controllers/application_controller.rb | 4 | ||||
-rw-r--r-- | app/controllers/sessions_controller.rb | 10 | ||||
-rw-r--r-- | app/views/admin/application_settings/_form.html.haml | 5 | ||||
-rw-r--r-- | config/application.rb | 4 | ||||
-rw-r--r-- | config/initializers/doorkeeper.rb | 6 | ||||
-rw-r--r-- | db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb | 12 | ||||
-rw-r--r-- | db/schema.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/auth.rb | 3 | ||||
-rw-r--r-- | lib/gitlab/auth/too_many_ips.rb | 17 | ||||
-rw-r--r-- | lib/gitlab/auth/unique_ips_limiter.rb | 34 | ||||
-rw-r--r-- | lib/gitlab/request_context.rb | 1 | ||||
-rw-r--r-- | spec/controllers/sessions_controller_spec.rb | 1 | ||||
-rw-r--r-- | spec/lib/gitlab/auth/unique_ips_limiter_spec.rb | 35 | ||||
-rw-r--r-- | spec/lib/gitlab/auth_spec.rb | 2 | ||||
-rw-r--r-- | spec/lib/gitlab/request_context_spec.rb | 10 |
15 files changed, 60 insertions, 86 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index cc7b7f247e8..0d3ee4f4c1f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -40,6 +40,10 @@ class ApplicationController < ActionController::Base render_403 end + rescue_from Gitlab::Auth::TooManyIps do |e| + head :forbidden, retry_after: UniqueIpsLimiter.config.unique_ips_limit_time_window + end + def redirect_back_or_default(default: root_path, options: {}) redirect_to request.referer.present? ? :back : default, options end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 3f5b92d9a99..7d81c96262f 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -67,12 +67,10 @@ class SessionsController < Devise::SessionsController end def find_user - Gitlab::Auth::UniqueIpsLimiter.limit_user! do - if session[:otp_user_id] - User.find(session[:otp_user_id]) - elsif user_params[:login] - User.by_login(user_params[:login]) - end + if session[:otp_user_id] + User.find(session[:otp_user_id]) + elsif user_params[:login] + User.by_login(user_params[:login]) end end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 7f25f76d0cb..00366b0a8c9 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -366,7 +366,8 @@ = f.label :unique_ips_limit_enabled do = f.check_box :unique_ips_limit_enabled Limit sign in from multiple ips - %span.help-block#recaptcha_help_block Helps prevent malicious users hide their activity + %span.help-block#unique_ip_help_block + Helps prevent malicious users hide their activity .form-group = f.label :unique_ips_limit_per_user, 'IPs per user', class: 'control-label col-sm-2' @@ -380,7 +381,7 @@ .col-sm-10 = f.number_field :unique_ips_limit_time_window, class: 'form-control' .help-block - How long an IP will be counted towards the limit + How many seconds an IP will be counted towards the limit %fieldset %legend Abuse reports diff --git a/config/application.rb b/config/application.rb index c4dea9e92b0..8003c055b27 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,8 +8,6 @@ module Gitlab class Application < Rails::Application require_dependency Rails.root.join('lib/gitlab/redis') require_dependency Rails.root.join('lib/gitlab/request_context') - require_dependency Rails.root.join('lib/gitlab/auth') - require_dependency Rails.root.join('lib/gitlab/auth/unique_ips_limiter') # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers @@ -114,8 +112,6 @@ module Gitlab config.middleware.insert_before Warden::Manager, Rack::Attack - config.middleware.insert_before Warden::Manager, Gitlab::Auth::UniqueIpsLimiter - # Allow access to GitLab API from other domains config.middleware.insert_before Warden::Manager, Rack::Cors do allow do diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb index 44b658e5872..88cd0f5f652 100644 --- a/config/initializers/doorkeeper.rb +++ b/config/initializers/doorkeeper.rb @@ -12,10 +12,8 @@ Doorkeeper.configure do end resource_owner_from_credentials do |routes| - Gitlab::Auth::UniqueIpsLimiter.limit_user! do - user = Gitlab::Auth.find_with_user_password(params[:username], params[:password]) - user unless user.try(:two_factor_enabled?) - end + user = Gitlab::Auth.find_with_user_password(params[:username], params[:password]) + user unless user.try(:two_factor_enabled?) end # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below. diff --git a/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb b/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb index 2aa305f6b58..cbcf9a30b3c 100644 --- a/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb +++ b/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb @@ -4,14 +4,14 @@ class AddUniqueIpsLimitToApplicationSettings < ActiveRecord::Migration disable_ddl_transaction! def up - add_column_with_default(:application_settings, :unique_ips_limit_per_user, :integer, default: 10) - add_column_with_default(:application_settings, :unique_ips_limit_time_window, :integer, default: 3600) - add_column_with_default(:application_settings, :unique_ips_limit_enabled, :boolean, default: false) + add_column_with_default :application_settings, :unique_ips_limit_per_user, :integer, default: 10 + add_column_with_default :application_settings, :unique_ips_limit_time_window, :integer, default: 3600 + add_column_with_default :application_settings, :unique_ips_limit_enabled, :boolean, default: false end def down - remove_column(:application_settings, :unique_ips_limit_per_user) - remove_column(:application_settings, :unique_ips_limit_time_window) - remove_column(:application_settings, :unique_ips_limit_enabled) + remove_column :application_settings, :unique_ips_limit_per_user + remove_column :application_settings, :unique_ips_limit_time_window + remove_column :application_settings, :unique_ips_limit_enabled end end diff --git a/db/schema.rb b/db/schema.rb index 8aed4e13b28..be54b177fa6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -586,9 +586,9 @@ ActiveRecord::Schema.define(version: 20170305203726) do end add_index "labels", ["group_id", "project_id", "title"], name: "index_labels_on_group_id_and_project_id_and_title", unique: true, using: :btree + add_index "labels", ["type", "project_id"], name: "index_labels_on_type_and_project_id", using: :btree add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree add_index "labels", ["title"], name: "index_labels_on_title", using: :btree - add_index "labels", ["type", "project_id"], name: "index_labels_on_type_and_project_id", using: :btree create_table "lfs_objects", force: :cascade do |t| t.string "oid", null: false diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 8e2aee2d7a0..0a0bd0e781c 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -22,9 +22,8 @@ module Gitlab user_with_password_for_git(login, password) || Gitlab::Auth::Result.new - Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) - rate_limit!(ip, success: result.success?, login: login) + Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) result end diff --git a/lib/gitlab/auth/too_many_ips.rb b/lib/gitlab/auth/too_many_ips.rb new file mode 100644 index 00000000000..ed862791551 --- /dev/null +++ b/lib/gitlab/auth/too_many_ips.rb @@ -0,0 +1,17 @@ +module Gitlab + module Auth + class TooManyIps < StandardError + attr_reader :user_id, :ip, :unique_ips_count + + def initialize(user_id, ip, unique_ips_count) + @user_id = user_id + @ip = ip + @unique_ips_count = unique_ips_count + end + + def message + "User #{user_id} from IP: #{ip} tried logging from too many ips: #{unique_ips_count}" + end + end + end +end diff --git a/lib/gitlab/auth/unique_ips_limiter.rb b/lib/gitlab/auth/unique_ips_limiter.rb index 4b2b758be8a..7b1aa736769 100644 --- a/lib/gitlab/auth/unique_ips_limiter.rb +++ b/lib/gitlab/auth/unique_ips_limiter.rb @@ -1,19 +1,5 @@ module Gitlab module Auth - class TooManyIps < StandardError - attr_reader :user_id, :ip, :unique_ips_count - - def initialize(user_id, ip, unique_ips_count) - @user_id = user_id - @ip = ip - @unique_ips_count = unique_ips_count - end - - def message - "User #{user_id} from IP: #{ip} tried logging from too many ips: #{unique_ips_count}" - end - end - class UniqueIpsLimiter USER_UNIQUE_IPS_PREFIX = 'user_unique_ips' @@ -21,7 +7,7 @@ module Gitlab def limit_user_id!(user_id) if config.unique_ips_limit_enabled ip = RequestContext.client_ip - unique_ips = count_unique_ips(user_id, ip) + unique_ips = update_and_return_ips_count(user_id, ip) raise TooManyIps.new(user_id, ip, unique_ips) if unique_ips > config.unique_ips_limit_per_user end end @@ -36,8 +22,8 @@ module Gitlab Gitlab::CurrentSettings.current_application_settings end - def count_unique_ips(user_id, ip) - time = Time.now.to_i + def update_and_return_ips_count(user_id, ip) + time = Time.now.utc.to_i key = "#{USER_UNIQUE_IPS_PREFIX}:#{user_id}" Gitlab::Redis.with do |redis| @@ -51,20 +37,6 @@ module Gitlab end end end - - def initialize(app) - @app = app - end - - def call(env) - begin - @app.call(env) - rescue TooManyIps => ex - - Rails.logger.info ex.message - [403, { 'Content-Type' => 'text/plain', 'Retry-After' => UniqueIpsLimiter.config.unique_ips_limit_time_window }, ["Too many logins from different IPs\n"]] - end - end end end end diff --git a/lib/gitlab/request_context.rb b/lib/gitlab/request_context.rb index 36a5d94d98a..548adf4775a 100644 --- a/lib/gitlab/request_context.rb +++ b/lib/gitlab/request_context.rb @@ -14,7 +14,6 @@ module Gitlab end def call(env) - raise RequestStoreNotActive.new unless RequestStore.active? req = Rack::Request.new(env) RequestStore[:client_ip] = req.ip diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 56ed11737ad..fe11bdf4a78 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -33,6 +33,7 @@ describe SessionsController do include_examples 'user login operation with unique ip limit' do def operation post(:create, user: { login: user.username, password: user.password }) + expect(subject.current_user).to eq user end end diff --git a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb index 2b21a76c59d..3214786d172 100644 --- a/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb +++ b/spec/lib/gitlab/auth/unique_ips_limiter_spec.rb @@ -7,36 +7,35 @@ describe Gitlab::Auth::UniqueIpsLimiter, :redis, lib: true do describe '#count_unique_ips' do context 'non unique IPs' do it 'properly counts them' do - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip1')).to eq(1) - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip1')).to eq(1) + expect(described_class.update_and_return_ips_count(user.id, 'ip1')).to eq(1) + expect(described_class.update_and_return_ips_count(user.id, 'ip1')).to eq(1) end end context 'unique IPs' do it 'properly counts them' do - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip2')).to eq(1) - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip3')).to eq(2) + expect(described_class.update_and_return_ips_count(user.id, 'ip2')).to eq(1) + expect(described_class.update_and_return_ips_count(user.id, 'ip3')).to eq(2) end end it 'resets count after specified time window' do - cur_time = Time.now - allow(Time).to receive(:now).and_return(cur_time) - - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip2')).to eq(1) - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip3')).to eq(2) - - allow(Time).to receive(:now).and_return(cur_time + Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window) - - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip4')).to eq(1) - expect(Gitlab::Auth::UniqueIpsLimiter.count_unique_ips(user.id, 'ip5')).to eq(2) + Timecop.freeze do + expect(described_class.update_and_return_ips_count(user.id, 'ip2')).to eq(1) + expect(described_class.update_and_return_ips_count(user.id, 'ip3')).to eq(2) + + Timecop.travel(Time.now.utc + described_class.config.unique_ips_limit_time_window) do + expect(described_class.update_and_return_ips_count(user.id, 'ip4')).to eq(1) + expect(described_class.update_and_return_ips_count(user.id, 'ip5')).to eq(2) + end + end end end describe '#limit_user!' do include_examples 'user login operation with unique ip limit' do def operation - Gitlab::Auth::UniqueIpsLimiter.limit_user! { user } + described_class.limit_user! { user } end end @@ -45,13 +44,13 @@ describe Gitlab::Auth::UniqueIpsLimiter, :redis, lib: true do it 'blocks user trying to login from third ip' do change_ip('ip1') - expect(Gitlab::Auth::UniqueIpsLimiter.limit_user! { user }).to eq(user) + expect(described_class.limit_user! { user }).to eq(user) change_ip('ip2') - expect(Gitlab::Auth::UniqueIpsLimiter.limit_user! { user }).to eq(user) + expect(described_class.limit_user! { user }).to eq(user) change_ip('ip3') - expect { Gitlab::Auth::UniqueIpsLimiter.limit_user! { user } }.to raise_error(Gitlab::Auth::TooManyIps) + expect { described_class.limit_user! { user } }.to raise_error(Gitlab::Auth::TooManyIps) end end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 860189dcf3c..daf8f5c1d6c 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -206,7 +206,7 @@ describe Gitlab::Auth, lib: true do include_examples 'user login operation with unique ip limit' do def operation - expect(gl_auth.find_with_user_password(username, password)).to eql user + expect(gl_auth.find_with_user_password(username, password)).to eq(user) end end diff --git a/spec/lib/gitlab/request_context_spec.rb b/spec/lib/gitlab/request_context_spec.rb index 69c5549c39c..b2828f7e5e0 100644 --- a/spec/lib/gitlab/request_context_spec.rb +++ b/spec/lib/gitlab/request_context_spec.rb @@ -26,15 +26,5 @@ describe Gitlab::RequestContext, lib: true do it { is_expected.to be_nil } end end - - context 'RequestStore is not active' do - it { is_expected.to be_nil } - - context 'when RequestContext mw is run' do - subject { -> { Gitlab::RequestContext.new(app).call(env) } } - - it { is_expected.to raise_error(Gitlab::RequestStoreNotActive) } - end - end end end |