diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-04 00:06:23 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-12-04 00:06:23 +0300 |
commit | 4529c19950e412f0461910585414f8633d3b1b18 (patch) | |
tree | 00b75c579ef52b41fea09c516cd5286dee5df703 /spec | |
parent | ab7cf450ba19cf80b9534f25dc707b33845e3014 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/application_controller_spec.rb | 26 | ||||
-rw-r--r-- | spec/lib/gitlab/auth/ip_rate_limiter_spec.rb | 32 | ||||
-rw-r--r-- | spec/lib/gitlab/auth_spec.rb | 104 | ||||
-rw-r--r-- | spec/requests/git_http_spec.rb | 2 |
4 files changed, 121 insertions, 43 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 04bbffc587f..9c6ea13f948 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -867,5 +867,31 @@ describe ApplicationController do it { is_expected.not_to redirect_to users_sign_up_welcome_path } end + + describe 'rescue_from Gitlab::Auth::IpBlacklisted' do + controller(described_class) do + skip_before_action :authenticate_user! + + def index + raise Gitlab::Auth::IpBlacklisted + end + end + + it 'returns a 403 and logs the request' do + expect(Gitlab::AuthLogger).to receive(:error).with({ + message: 'Rack_Attack', + env: :blocklist, + remote_ip: '1.2.3.4', + request_method: 'GET', + path: '/anonymous' + }) + + request.remote_addr = '1.2.3.4' + + get :index + + expect(response).to have_gitlab_http_status(:forbidden) + end + end end end diff --git a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb index 8d6bf45ab30..aea1b2921b6 100644 --- a/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb +++ b/spec/lib/gitlab/auth/ip_rate_limiter_spec.rb @@ -62,4 +62,36 @@ describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_caching do it_behaves_like 'whitelisted IPs' end end + + shared_examples 'skips the rate limiter' do + it 'does not call Rack::Attack::Allow2Ban.reset!' do + expect(Rack::Attack::Allow2Ban).not_to receive(:reset!) + + subject.reset! + end + + it 'does not call Rack::Attack::Allow2Ban.banned?' do + expect(Rack::Attack::Allow2Ban).not_to receive(:banned?) + + subject.banned? + end + + it 'does not call Rack::Attack::Allow2Ban.filter' do + expect(Rack::Attack::Allow2Ban).not_to receive(:filter) + + subject.register_fail! + end + end + + context 'when IP is whitlisted' do + let(:ip) { '127.0.0.1' } + + it_behaves_like 'skips the rate limiter' + end + + context 'when rate limiter is disabled' do + let(:options) { { enabled: false } } + + it_behaves_like 'skips the rate limiter' + end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index dc4b0b5b1b6..d3f3b67aa90 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -79,6 +79,66 @@ describe Gitlab::Auth do end describe 'find_for_git_client' do + describe 'rate limiting' do + before do + stub_rack_attack_setting(enabled: true, ip_whitelist: []) + end + + context 'when IP is already banned' do + subject { gl_auth.find_for_git_client('username', 'password', project: nil, ip: 'ip') } + + before do + expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| + expect(rate_limiter).to receive(:banned?).and_return(true) + end + end + + it 'raises an IpBlacklisted exception' do + expect { subject }.to raise_error(Gitlab::Auth::IpBlacklisted) + end + end + + context 'for CI registry user' do + let_it_be(:build) { create(:ci_build, :running) } + + it 'skips rate limiting for successful auth' do + expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| + expect(rate_limiter).not_to receive(:reset!) + end + + gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: build.project, ip: 'ip') + end + + it 'skips rate limiting for failed auth' do + expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| + expect(rate_limiter).not_to receive(:register_fail!) + end + + gl_auth.find_for_git_client('gitlab-ci-token', 'wrong_token', project: build.project, ip: 'ip') + end + end + + context 'for other users' do + let_it_be(:user) { create(:user) } + + it 'resets rate limit for successful auth' do + expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| + expect(rate_limiter).to receive(:reset!) + end + + gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip') + end + + it 'registers failure for failed auth' do + expect_next_instance_of(Gitlab::Auth::IpRateLimiter) do |rate_limiter| + expect(rate_limiter).to receive(:register_fail!) + end + + gl_auth.find_for_git_client(user.username, 'wrong_password', project: nil, ip: 'ip') + end + end + end + context 'build token' do subject { gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: project, ip: 'ip') } @@ -86,10 +146,6 @@ describe Gitlab::Auth do let!(:build) { create(:ci_build, :running) } let(:project) { build.project } - before do - expect(gl_auth).not_to receive(:rate_limit!).with('ip', success: true, login: 'gitlab-ci-token') - end - it 'recognises user-less build' do expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, described_class.build_authentication_abilities)) end @@ -106,10 +162,6 @@ describe Gitlab::Auth do let!(:build) { create(:ci_build, status: build_status) } let(:project) { build.project } - before do - expect(gl_auth).not_to receive(:rate_limit!).with('ip', success: false, login: 'gitlab-ci-token') - end - it 'denies authentication' do expect(subject).to eq(Gitlab::Auth::Result.new) end @@ -121,14 +173,12 @@ describe Gitlab::Auth do project.create_drone_ci_service(active: true) project.drone_ci_service.update(token: 'token') - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'drone-ci-token') expect(gl_auth.find_for_git_client('drone-ci-token', 'token', project: project, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, project, :ci, described_class.build_authentication_abilities)) end it 'recognizes master passwords' do user = create(:user, password: 'password') - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: user.username) expect(gl_auth.find_for_git_client(user.username, 'password', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, described_class.full_authentication_abilities)) end @@ -145,7 +195,6 @@ describe Gitlab::Auth do user = create(:user) token = Gitlab::LfsToken.new(user).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: user.username) expect(gl_auth.find_for_git_client(user.username, token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :lfs_token, described_class.read_write_project_authentication_abilities)) end @@ -153,7 +202,6 @@ describe Gitlab::Auth do key = create(:deploy_key) token = Gitlab::LfsToken.new(key).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") expect(gl_auth.find_for_git_client("lfs+deploy-key-#{key.id}", token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(key, nil, :lfs_deploy_token, described_class.read_only_authentication_abilities)) end @@ -171,7 +219,6 @@ describe Gitlab::Auth do create(:deploy_keys_project, :write_access, deploy_key: key, project: project) token = Gitlab::LfsToken.new(key).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") expect(gl_auth.find_for_git_client("lfs+deploy-key-#{key.id}", token, project: project, ip: 'ip')).to eq(Gitlab::Auth::Result.new(key, nil, :lfs_deploy_token, described_class.read_write_authentication_abilities)) end @@ -179,7 +226,6 @@ describe Gitlab::Auth do key = create(:deploy_key) token = Gitlab::LfsToken.new(key).token - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: "lfs+deploy-key-#{key.id}") expect(gl_auth.find_for_git_client("lfs+deploy-key-#{key.id}", token, project: project, ip: 'ip')).to eq(Gitlab::Auth::Result.new(key, nil, :lfs_deploy_token, described_class.read_only_authentication_abilities)) end end @@ -190,14 +236,12 @@ describe Gitlab::Auth do let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) } it 'succeeds for OAuth tokens with the `api` scope' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'oauth2') expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(user, nil, :oauth, described_class.full_authentication_abilities)) end it 'fails for OAuth tokens with other scopes' do token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'read_user') - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'oauth2') expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, nil)) end @@ -257,7 +301,7 @@ describe Gitlab::Auth do end context 'while using regular user and password' do - it 'falls through lfs authentication' do + it 'goes through lfs authentication' do user = create( :user, username: 'normal_user', @@ -268,7 +312,7 @@ describe Gitlab::Auth do .to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, described_class.full_authentication_abilities)) end - it 'fails through oauth authentication when the username is oauth2' do + it 'goes through oauth authentication when the username is oauth2' do user = create( :user, username: 'oauth2', @@ -283,7 +327,6 @@ describe Gitlab::Auth do it 'returns double nil for invalid credentials' do login = 'foo' - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new) end @@ -301,10 +344,6 @@ describe Gitlab::Auth do let(:user) { create(:user, username: username, password: 'my-secret') } let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) } - before do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: username) - end - it 'succeeds for the token' do auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code]) @@ -328,13 +367,11 @@ describe Gitlab::Auth do it 'succeeds for the right token' do auth_success = Gitlab::Auth::Result.new(read_repository, project, :deploy_token, [:download_code]) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'deployer') expect(gl_auth.find_for_git_client('deployer', read_repository.token, project: project, ip: 'ip')) .to eq(auth_success) end it 'fails for the wrong token' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'deployer') expect(gl_auth.find_for_git_client('deployer', read_registry.token, project: project, ip: 'ip')) .to eq(auth_failure) end @@ -347,13 +384,11 @@ describe Gitlab::Auth do it 'succeeds for the right token' do auth_success = Gitlab::Auth::Result.new(read_repository, project, :deploy_token, [:download_code]) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'deployer') expect(gl_auth.find_for_git_client('deployer', read_repository.token, project: project, ip: 'ip')) .to eq(auth_success) end it 'fails for the wrong token' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'deployer') expect(gl_auth.find_for_git_client('deployer', read_registry.token, project: project, ip: 'ip')) .to eq(auth_failure) end @@ -367,7 +402,6 @@ describe Gitlab::Auth do it 'succeeds when login and token are valid' do auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code]) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: login) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: project, ip: 'ip')) .to eq(auth_success) end @@ -376,32 +410,27 @@ describe Gitlab::Auth do deploy_token = create(:deploy_token, username: 'deployer', read_registry: false, projects: [project]) auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code]) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: 'deployer') expect(gl_auth.find_for_git_client('deployer', deploy_token.token, project: project, ip: 'ip')) .to eq(auth_success) end it 'fails when login is not valid' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'random_login') expect(gl_auth.find_for_git_client('random_login', deploy_token.token, project: project, ip: 'ip')) .to eq(auth_failure) end it 'fails when token is not valid' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, '123123', project: project, ip: 'ip')) .to eq(auth_failure) end it 'fails if token is nil' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, nil, project: project, ip: 'ip')) .to eq(auth_failure) end it 'fails if token is not related to project' do another_deploy_token = create(:deploy_token) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, another_deploy_token.token, project: project, ip: 'ip')) .to eq(auth_failure) end @@ -410,7 +439,6 @@ describe Gitlab::Auth do deploy_token.revoke! expect(deploy_token.revoked?).to be_truthy - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'deploy-token') expect(gl_auth.find_for_git_client('deploy-token', deploy_token.token, project: project, ip: 'ip')) .to eq(auth_failure) end @@ -428,31 +456,26 @@ describe Gitlab::Auth do it 'succeeds when login and token are valid' do auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:read_container_image]) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: login) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: nil, ip: 'ip')) .to eq(auth_success) end it 'fails when login is not valid' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'random_login') expect(gl_auth.find_for_git_client('random_login', deploy_token.token, project: project, ip: 'ip')) .to eq(auth_failure) end it 'fails when token is not valid' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, '123123', project: project, ip: 'ip')) .to eq(auth_failure) end it 'fails if token is nil' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, nil, project: nil, ip: 'ip')) .to eq(auth_failure) end it 'fails if token is not related to project' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, 'abcdef', project: nil, ip: 'ip')) .to eq(auth_failure) end @@ -461,7 +484,6 @@ describe Gitlab::Auth do deploy_token.revoke! expect(deploy_token.revoked?).to be_truthy - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: 'deploy-token') expect(gl_auth.find_for_git_client('deploy-token', deploy_token.token, project: nil, ip: 'ip')) .to eq(auth_failure) end @@ -473,7 +495,6 @@ describe Gitlab::Auth do end it 'fails when login and token are valid' do - expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: login) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: nil, ip: 'ip')) .to eq(auth_failure) end @@ -586,7 +607,6 @@ describe Gitlab::Auth do private def expect_results_with_abilities(personal_access_token, abilities, success = true) - expect(gl_auth).to receive(:rate_limit!).with('ip', success: success, login: '') expect(gl_auth.find_for_git_client('', personal_access_token&.token, project: nil, ip: 'ip')) .to eq(Gitlab::Auth::Result.new(personal_access_token&.user, nil, personal_access_token.nil? ? nil : :personal_access_token, abilities)) end diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb index 1b17d492b0c..42b4bd71b88 100644 --- a/spec/requests/git_http_spec.rb +++ b/spec/requests/git_http_spec.rb @@ -456,7 +456,7 @@ describe 'Git HTTP requests' do end it "responds with status 403" do - expect(Rack::Attack::Allow2Ban).to receive(:filter).and_return(true) + expect(Rack::Attack::Allow2Ban).to receive(:banned?).and_return(true) expect(Gitlab::AuthLogger).to receive(:error).with({ message: 'Rack_Attack', env: :blocklist, |