Commit 34635146 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Only check for blacklisted IPs on Git requests

We block IP addresses when failed Git auths reach a certain
threshold.

This block applied to all requests so for every request, we
had to check Redis to see if the IP is blocked. This caused
unnecessary Redis load.

This MR changes the block to only apply to Git requests as
it is described in the documentation
parent 240f55f9
...@@ -74,6 +74,18 @@ class ApplicationController < ActionController::Base ...@@ -74,6 +74,18 @@ class ApplicationController < ActionController::Base
render_403 render_403
end end
rescue_from Gitlab::Auth::IpBlacklisted do
Gitlab::AuthLogger.error(
message: 'Rack_Attack',
env: :blocklist,
remote_ip: request.ip,
request_method: request.request_method,
path: request.fullpath
)
head :forbidden
end
rescue_from Gitlab::Auth::TooManyIps do |e| rescue_from Gitlab::Auth::TooManyIps do |e|
head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window
end end
......
---
title: Only blacklist IPs from Git requests
merge_request: 20828
author:
type: changed
# Tell the Rack::Attack Rack middleware to maintain an IP blacklist.
# We update the blacklist in Gitlab::Auth::IpRateLimiter.
Rack::Attack.blocklist('Git HTTP Basic Auth') do |req|
rate_limiter = Gitlab::Auth::IpRateLimiter.new(req.ip)
next false if !rate_limiter.enabled? || rate_limiter.trusted_ip?
Rack::Attack::Allow2Ban.filter(req.ip, Gitlab.config.rack_attack.git_basic_auth) do
# This block only gets run if the IP was not already banned.
# Return false, meaning that we do not see anything wrong with the
# request at this time
false
end
end
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
module Gitlab module Gitlab
module Auth module Auth
MissingPersonalAccessTokenError = Class.new(StandardError) MissingPersonalAccessTokenError = Class.new(StandardError)
IpBlacklisted = Class.new(StandardError)
# Scopes used for GitLab API access # Scopes used for GitLab API access
API_SCOPES = [:api, :read_user].freeze API_SCOPES = [:api, :read_user].freeze
...@@ -35,6 +36,10 @@ module Gitlab ...@@ -35,6 +36,10 @@ module Gitlab
def find_for_git_client(login, password, project:, ip:) def find_for_git_client(login, password, project:, ip:)
raise "Must provide an IP for rate limiting" if ip.nil? raise "Must provide an IP for rate limiting" if ip.nil?
rate_limiter = Gitlab::Auth::IpRateLimiter.new(ip)
raise IpBlacklisted if !skip_rate_limit?(login: login) && rate_limiter.banned?
# `user_with_password_for_git` should be the last check # `user_with_password_for_git` should be the last check
# because it's the most expensive, especially when LDAP # because it's the most expensive, especially when LDAP
# is enabled. # is enabled.
...@@ -48,7 +53,7 @@ module Gitlab ...@@ -48,7 +53,7 @@ module Gitlab
user_with_password_for_git(login, password) || user_with_password_for_git(login, password) ||
Gitlab::Auth::Result.new Gitlab::Auth::Result.new
rate_limit!(ip, success: result.success?, login: login) unless skip_rate_limit?(login: login) rate_limit!(rate_limiter, success: result.success?, login: login)
Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor) Gitlab::Auth::UniqueIpsLimiter.limit_user!(result.actor)
return result if result.success? || authenticate_using_internal_or_ldap_password? return result if result.success? || authenticate_using_internal_or_ldap_password?
...@@ -96,10 +101,11 @@ module Gitlab ...@@ -96,10 +101,11 @@ module Gitlab
end end
end end
private
# rubocop:disable Gitlab/RailsLogger # rubocop:disable Gitlab/RailsLogger
def rate_limit!(ip, success:, login:) def rate_limit!(rate_limiter, success:, login:)
rate_limiter = Gitlab::Auth::IpRateLimiter.new(ip) return if skip_rate_limit?(login: login)
return unless rate_limiter.enabled?
if success if success
# Repeated login 'failures' are normal behavior for some Git clients so # Repeated login 'failures' are normal behavior for some Git clients so
...@@ -109,18 +115,16 @@ module Gitlab ...@@ -109,18 +115,16 @@ module Gitlab
else else
# Register a login failure so that Rack::Attack can block the next # Register a login failure so that Rack::Attack can block the next
# request from this IP if needed. # request from this IP if needed.
rate_limiter.register_fail! # This returns true when the failures are over the threshold and the IP
# is banned.
if rate_limiter.banned? if rate_limiter.register_fail!
Rails.logger.info "IP #{ip} failed to login " \ Rails.logger.info "IP #{rate_limiter.ip} failed to login " \
"as #{login} but has been temporarily banned from Git auth" "as #{login} but has been temporarily banned from Git auth"
end end
end end
end end
# rubocop:enable Gitlab/RailsLogger # rubocop:enable Gitlab/RailsLogger
private
def skip_rate_limit?(login:) def skip_rate_limit?(login:)
::Ci::Build::CI_REGISTRY_USER == login ::Ci::Build::CI_REGISTRY_USER == login
end end
......
...@@ -9,41 +9,48 @@ module Gitlab ...@@ -9,41 +9,48 @@ module Gitlab
def initialize(ip) def initialize(ip)
@ip = ip @ip = ip
@banned = false
end
def enabled?
config.enabled
end end
def reset! def reset!
return if skip_rate_limit?
Rack::Attack::Allow2Ban.reset(ip, config) Rack::Attack::Allow2Ban.reset(ip, config)
end end
def register_fail! def register_fail!
return false if trusted_ip? return false if skip_rate_limit?
# Allow2Ban.filter will return false if this IP has not failed too often yet # Allow2Ban.filter will return false if this IP has not failed too often yet
@banned = Rack::Attack::Allow2Ban.filter(ip, config) do Rack::Attack::Allow2Ban.filter(ip, config) do
# We return true to increment the count for this IP # We return true to increment the count for this IP
true true
end end
end end
def banned? def banned?
@banned return false if skip_rate_limit?
end
def trusted_ip? Rack::Attack::Allow2Ban.banned?(ip)
trusted_ips.any? { |netmask| netmask.include?(ip) }
end end
private private
def skip_rate_limit?
!enabled? || trusted_ip?
end
def enabled?
config.enabled
end
def config def config
Gitlab.config.rack_attack.git_basic_auth Gitlab.config.rack_attack.git_basic_auth
end end
def trusted_ip?
trusted_ips.any? { |netmask| netmask.include?(ip) }
end
def trusted_ips def trusted_ips
strong_memoize(:trusted_ips) do strong_memoize(:trusted_ips) do
config.ip_whitelist.map do |proxy| config.ip_whitelist.map do |proxy|
......
...@@ -869,5 +869,31 @@ describe ApplicationController do ...@@ -869,5 +869,31 @@ describe ApplicationController do
it { is_expected.not_to redirect_to users_sign_up_welcome_path } it { is_expected.not_to redirect_to users_sign_up_welcome_path }
end 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
end end
...@@ -62,4 +62,36 @@ describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_caching do ...@@ -62,4 +62,36 @@ describe Gitlab::Auth::IpRateLimiter, :use_clean_rails_memory_store_caching do
it_behaves_like 'whitelisted IPs' it_behaves_like 'whitelisted IPs'
end end
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 end
...@@ -79,6 +79,66 @@ describe Gitlab::Auth do ...@@ -79,6 +79,66 @@ describe Gitlab::Auth do
end end
describe 'find_for_git_client' do 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 context 'build token' do
subject { gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: project, ip: 'ip') } subject { gl_auth.find_for_git_client('gitlab-ci-token', build.token, project: project, ip: 'ip') }
...@@ -86,10 +146,6 @@ describe Gitlab::Auth do ...@@ -86,10 +146,6 @@ describe Gitlab::Auth do
let!(:build) { create(:ci_build, :running) } let!(:build) { create(:ci_build, :running) }
let(:project) { build.project } 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 it 'recognises user-less build' do
expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, described_class.build_authentication_abilities)) expect(subject).to eq(Gitlab::Auth::Result.new(nil, build.project, :ci, described_class.build_authentication_abilities))
end end
...@@ -106,10 +162,6 @@ describe Gitlab::Auth do ...@@ -106,10 +162,6 @@ describe Gitlab::Auth do
let!(:build) { create(:ci_build, status: build_status) } let!(:build) { create(:ci_build, status: build_status) }
let(:project) { build.project } 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 it 'denies authentication' do
expect(subject).to eq(Gitlab::Auth::Result.new) expect(subject).to eq(Gitlab::Auth::Result.new)
end end
...@@ -121,14 +173,12 @@ describe Gitlab::Auth do ...@@ -121,14 +173,12 @@ describe Gitlab::Auth do
project.create_drone_ci_service(active: true) project.create_drone_ci_service(active: true)
project.drone_ci_service.update(token: 'token') 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)) 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 end
it 'recognizes master passwords' do it 'recognizes master passwords' do
user = create(:user, password: 'password') 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)) 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 end
...@@ -145,7 +195,6 @@ describe Gitlab::Auth do ...@@ -145,7 +195,6 @@ describe Gitlab::Auth do
user = create(:user) user = create(:user)
token = Gitlab::LfsToken.new(user).token 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)) 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 end
...@@ -153,7 +202,6 @@ describe Gitlab::Auth do ...@@ -153,7 +202,6 @@ describe Gitlab::Auth do
key = create(:deploy_key) key = create(:deploy_key)
token = Gitlab::LfsToken.new(key).token 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)) 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 end
...@@ -171,7 +219,6 @@ describe Gitlab::Auth do ...@@ -171,7 +219,6 @@ describe Gitlab::Auth do
create(:deploy_keys_project, :write_access, deploy_key: key, project: project) create(:deploy_keys_project, :write_access, deploy_key: key, project: project)
token = Gitlab::LfsToken.new(key).token 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)) 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 end
...@@ -179,7 +226,6 @@ describe Gitlab::Auth do ...@@ -179,7 +226,6 @@ describe Gitlab::Auth do
key = create(:deploy_key) key = create(:deploy_key)
token = Gitlab::LfsToken.new(key).token 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)) 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
end end
...@@ -190,14 +236,12 @@ describe Gitlab::Auth do ...@@ -190,14 +236,12 @@ describe Gitlab::Auth do
let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) } let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) }
it 'succeeds for OAuth tokens with the `api` scope' do 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)) 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 end
it 'fails for OAuth tokens with other scopes' do 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') 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)) expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, nil))
end end
...@@ -257,7 +301,7 @@ describe Gitlab::Auth do ...@@ -257,7 +301,7 @@ describe Gitlab::Auth do
end end
context 'while using regular user and password' do context 'while using regular user and password' do
it 'falls through lfs authentication' do it 'goes through lfs authentication' do
user = create( user = create(
:user, :user,
username: 'normal_user', username: 'normal_user',
...@@ -268,7 +312,7 @@ describe Gitlab::Auth do ...@@ -268,7 +312,7 @@ describe Gitlab::Auth do
.to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, described_class.full_authentication_abilities)) .to eq(Gitlab::Auth::Result.new(user, nil, :gitlab_or_ldap, described_class.full_authentication_abilities))
end 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 = create(
:user, :user,
username: 'oauth2', username: 'oauth2',
...@@ -283,7 +327,6 @@ describe Gitlab::Auth do ...@@ -283,7 +327,6 @@ describe Gitlab::Auth do
it 'returns double nil for invalid credentials' do it 'returns double nil for invalid credentials' do
login = 'foo' 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) expect(gl_auth.find_for_git_client(login, 'bar', project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new)
end end
...@@ -301,10 +344,6 @@ describe Gitlab::Auth do ...@@ -301,10 +344,6 @@ describe Gitlab::Auth do
let(:user) { create(:user, username: username, password: 'my-secret') } let(:user) { create(:user, username: username, password: 'my-secret') }
let(:deploy_token) { create(:deploy_token, username: username, read_registry: false, projects: [project]) } 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 it 'succeeds for the token' do
auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code]) auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code])
...@@ -328,13 +367,11 @@ describe Gitlab::Auth do ...@@ -328,13 +367,11 @@ describe Gitlab::Auth do
it 'succeeds for the right token' do it 'succeeds for the right token' do
auth_success = Gitlab::Auth::Result.new(read_repository, project, :deploy_token, [:download_code]) 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')) expect(gl_auth.find_for_git_client('deployer', read_repository.token, project: project, ip: 'ip'))
.to eq(auth_success) .to eq(auth_success)
end end
it 'fails for the wrong token' do 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')) expect(gl_auth.find_for_git_client('deployer', read_registry.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -347,13 +384,11 @@ describe Gitlab::Auth do ...@@ -347,13 +384,11 @@ describe Gitlab::Auth do
it 'succeeds for the right token' do it 'succeeds for the right token' do
auth_success = Gitlab::Auth::Result.new(read_repository, project, :deploy_token, [:download_code]) 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')) expect(gl_auth.find_for_git_client('deployer', read_repository.token, project: project, ip: 'ip'))
.to eq(auth_success) .to eq(auth_success)
end end
it 'fails for the wrong token' do 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')) expect(gl_auth.find_for_git_client('deployer', read_registry.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -367,7 +402,6 @@ describe Gitlab::Auth do ...@@ -367,7 +402,6 @@ describe Gitlab::Auth do
it 'succeeds when login and token are valid' do it 'succeeds when login and token are valid' do
auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:download_code]) 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')) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_success) .to eq(auth_success)
end end
...@@ -376,32 +410,27 @@ describe Gitlab::Auth do ...@@ -376,32 +410,27 @@ describe Gitlab::Auth do
deploy_token = create(:deploy_token, username: 'deployer', read_registry: false, projects: [project]) 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]) 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')) expect(gl_auth.find_for_git_client('deployer', deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_success) .to eq(auth_success)
end end
it 'fails when login is not valid' do 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')) expect(gl_auth.find_for_git_client('random_login', deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails when token is not valid' do 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')) expect(gl_auth.find_for_git_client(login, '123123', project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails if token is nil' do 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')) expect(gl_auth.find_for_git_client(login, nil, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails if token is not related to project' do it 'fails if token is not related to project' do
another_deploy_token = create(:deploy_token) 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')) expect(gl_auth.find_for_git_client(login, another_deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -410,7 +439,6 @@ describe Gitlab::Auth do ...@@ -410,7 +439,6 @@ describe Gitlab::Auth do
deploy_token.revoke! deploy_token.revoke!
expect(deploy_token.revoked?).to be_truthy 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')) expect(gl_auth.find_for_git_client('deploy-token', deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -428,31 +456,26 @@ describe Gitlab::Auth do ...@@ -428,31 +456,26 @@ describe Gitlab::Auth do
it 'succeeds when login and token are valid' do it 'succeeds when login and token are valid' do
auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:read_container_image]) 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')) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: nil, ip: 'ip'))
.to eq(auth_success) .to eq(auth_success)
end end
it 'fails when login is not valid' do 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')) expect(gl_auth.find_for_git_client('random_login', deploy_token.token, project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails when token is not valid' do 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')) expect(gl_auth.find_for_git_client(login, '123123', project: project, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails if token is nil' do 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')) expect(gl_auth.find_for_git_client(login, nil, project: nil, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
it 'fails if token is not related to project' do 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')) expect(gl_auth.find_for_git_client(login, 'abcdef', project: nil, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -461,7 +484,6 @@ describe Gitlab::Auth do ...@@ -461,7 +484,6 @@ describe Gitlab::Auth do
deploy_token.revoke! deploy_token.revoke!
expect(deploy_token.revoked?).to be_truthy 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')) expect(gl_auth.find_for_git_client('deploy-token', deploy_token.token, project: nil, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -473,7 +495,6 @@ describe Gitlab::Auth do ...@@ -473,7 +495,6 @@ describe Gitlab::Auth do
end end
it 'fails when login and token are valid' do 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')) expect(gl_auth.find_for_git_client(login, deploy_token.token, project: nil, ip: 'ip'))
.to eq(auth_failure) .to eq(auth_failure)
end end
...@@ -586,7 +607,6 @@ describe Gitlab::Auth do ...@@ -586,7 +607,6 @@ describe Gitlab::Auth do
private private
def expect_results_with_abilities(personal_access_token, abilities, success = true) 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')) 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)) .to eq(Gitlab::Auth::Result.new(personal_access_token&.user, nil, personal_access_token.nil? ? nil : :personal_access_token, abilities))
end end
......
...@@ -456,7 +456,7 @@ describe 'Git HTTP requests' do ...@@ -456,7 +456,7 @@ describe 'Git HTTP requests' do
end end
it "responds with status 403" do 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({ expect(Gitlab::AuthLogger).to receive(:error).with({
message: 'Rack_Attack', message: 'Rack_Attack',
env: :blocklist, env: :blocklist,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment