Commit 0f9e1f3b authored by Marius Bobin's avatar Marius Bobin Committed by Ash McKenzie

Auth requests with job token as auth header

Git requests made by the runner include the authentication
params in the HTTP basic auth header.

Fixes User and IP Rate Limits throttles so that runner requests
using a valid job token as basic auth will not be counted in
Unauthenticated request rate limit.
parent 47b10c4c
---
title: Authenticate requests with job token as basic auth header for request limiting
merge_request: 21562
author:
type: fixed
......@@ -21,6 +21,7 @@ module Gitlab
prepend_if_ee('::EE::Gitlab::Auth::AuthFinders') # rubocop: disable Cop/InjectEnterpriseEditionModule
include Gitlab::Utils::StrongMemoize
include ActionController::HttpAuthentication::Basic
PRIVATE_TOKEN_HEADER = 'HTTP_PRIVATE_TOKEN'
PRIVATE_TOKEN_PARAM = :private_token
......@@ -67,6 +68,19 @@ module Gitlab
job.user
end
def find_user_from_basic_auth_job
return unless has_basic_credentials?(current_request)
login, password = user_name_and_password(current_request)
return unless login.present? && password.present?
return unless ::Ci::Build::CI_REGISTRY_USER == login
job = ::Ci::Build.find_by_token(password)
raise UnauthorizedError unless job
job.user
end
# We only allow Private Access Tokens with `api` scope to be used by web
# requests on RSS feeds or ICS files for backwards compatibility.
# It is also used by GraphQL/API requests.
......
......@@ -32,7 +32,8 @@ module Gitlab
def find_sessionless_user(request_format)
find_user_from_web_access_token(request_format) ||
find_user_from_feed_token(request_format) ||
find_user_from_static_object_token(request_format)
find_user_from_static_object_token(request_format) ||
find_user_from_basic_auth_job
rescue Gitlab::Auth::AuthenticationError
nil
end
......
......@@ -335,6 +335,72 @@ describe Gitlab::Auth::AuthFinders do
end
end
describe '#find_user_from_basic_auth_job' do
def basic_http_auth(username, password)
ActionController::HttpAuthentication::Basic.encode_credentials(username, password)
end
def set_auth(username, password)
env['HTTP_AUTHORIZATION'] = basic_http_auth(username, password)
end
subject { find_user_from_basic_auth_job }
context 'when the request does not have AUTHORIZATION header' do
it { is_expected.to be_nil }
end
context 'with wrong credentials' do
it 'returns nil without user and password' do
set_auth(nil, nil)
is_expected.to be_nil
end
it 'returns nil without password' do
set_auth('some-user', nil)
is_expected.to be_nil
end
it 'returns nil without user' do
set_auth(nil, 'password')
is_expected.to be_nil
end
it 'returns nil without CI username' do
set_auth('user', 'password')
is_expected.to be_nil
end
end
context 'with CI username' do
let(:username) { ::Ci::Build::CI_REGISTRY_USER }
let(:user) { create(:user) }
let(:build) { create(:ci_build, user: user) }
it 'returns nil without password' do
set_auth(username, nil)
is_expected.to be_nil
end
it 'returns user with valid token' do
set_auth(username, build.token)
is_expected.to eq user
end
it 'raises error with invalid token' do
set_auth(username, 'token')
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
end
describe '#validate_access_token!' do
let(:personal_access_token) { create(:personal_access_token, user: user) }
......
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