Commit 32e65111 authored by Mathieu Parent's avatar Mathieu Parent

Refactor Gitlab::Auth::AuthFinders specs

parent 8f0404da
...@@ -7,7 +7,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -7,7 +7,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do
include HttpBasicAuthHelpers include HttpBasicAuthHelpers
# Create the feed_token and static_object_token for the user # Create the feed_token and static_object_token for the user
let_it_be(:user) { create(:user).tap(&:feed_token).tap(&:static_object_token) } let_it_be(:user, freeze: true) { create(:user).tap(&:feed_token).tap(&:static_object_token) }
let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user) }
let_it_be(:project, freeze: true) { create(:project, :private) }
let_it_be(:pipeline, freeze: true) { create(:ci_pipeline, project: project) }
let_it_be(:job, freeze: true) { create(:ci_build, :running, pipeline: pipeline, user: user) }
let_it_be(:failed_job, freeze: true) { create(:ci_build, :failed, pipeline: pipeline, user: user) }
let_it_be(:project2, freeze: true) { create(:project, :private) }
let_it_be(:pipeline2, freeze: true) { create(:ci_pipeline, project: project2) }
let_it_be(:job2, freeze: true) { create(:ci_build, :running, pipeline: pipeline2, user: user) }
let(:env) do let(:env) do
{ {
'rack.input' => '' 'rack.input' => ''
...@@ -15,6 +26,12 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -15,6 +26,12 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
let(:request) { ActionDispatch::Request.new(env) } let(:request) { ActionDispatch::Request.new(env) }
let(:params) { {} }
before_all do
project.add_developer(user)
project2.add_developer(user)
end
def set_param(key, value) def set_param(key, value)
request.update_param(key, value) request.update_param(key, value)
...@@ -28,75 +45,93 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -28,75 +45,93 @@ RSpec.describe Gitlab::Auth::AuthFinders do
env.merge!(basic_auth_header(username, password)) env.merge!(basic_auth_header(username, password))
end end
shared_examples 'find user from job token' do def set_bearer_token(token)
env['HTTP_AUTHORIZATION'] = "Bearer #{token}"
end
shared_examples 'find user from job token' do |without_job_token_allowed|
context 'when route is allowed to be authenticated' do context 'when route is allowed to be authenticated' do
let(:route_authentication_setting) { { job_token_allowed: true } } let(:route_authentication_setting) { { job_token_allowed: true } }
it "returns an Unauthorized exception for an invalid token" do context 'for an invalid token' do
set_token('invalid token') let(:token) { 'invalid token' }
it "returns an Unauthorized exception" do
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError) expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
expect(@current_authenticated_job).to be_nil
end end
context 'with a running job' do
before do
job.update!(status: :running)
end end
it 'return user if token is valid' do context 'with a running job' do
set_token(job.token) let(:token) { job.token }
it 'return user' do
expect(subject).to eq(user) expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job expect(@current_authenticated_job).to eq job
end end
end end
context 'with a job that is not running' do context 'with a job that is not running' do
before do let(:token) { failed_job.token }
job.update!(status: :failed)
end
it 'returns an Unauthorized exception' do it 'returns an Unauthorized exception' do
set_token(job.token) expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
expect(@current_authenticated_job).to be_nil
end
end
end
context 'when route is not allowed to be authenticated' do
let(:route_authentication_setting) { { job_token_allowed: false } }
context 'with a running job' do
let(:token) { job.token }
if without_job_token_allowed == :error
it 'returns an Unauthorized exception' do
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError) expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
expect(@current_authenticated_job).to be_nil
end
elsif without_job_token_allowed == :user
it 'returns the user' do
expect(subject).to eq(user)
expect(@current_authenticated_job).to eq job
end
else
it 'returns nil' do
is_expected.to be_nil
expect(@current_authenticated_job).to be_nil
end
end end
end end
end end
end end
describe '#find_user_from_bearer_token' do describe '#find_user_from_bearer_token' do
let_it_be_with_reload(:job) { create(:ci_build, user: user) }
subject { find_user_from_bearer_token } subject { find_user_from_bearer_token }
context 'when the token is passed as an oauth token' do context 'when the token is passed as an oauth token' do
def set_token(token) before do
env['HTTP_AUTHORIZATION'] = "Bearer #{token}" set_bearer_token(token)
end end
context 'with a job token' do it_behaves_like 'find user from job token', :error
it_behaves_like 'find user from job token'
end end
context 'with oauth token' do context 'with oauth token' 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) }
let(:token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api').token } let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
before do before do
set_token(token) set_bearer_token(doorkeeper_access_token.token)
end end
it { is_expected.to eq user } it { is_expected.to eq user }
end end
end
context 'with a personal access token' do context 'with a personal access token' do
let_it_be(:pat) { create(:personal_access_token, user: user) }
let(:token) { pat.token }
before do before do
env[described_class::PRIVATE_TOKEN_HEADER] = pat.token env[described_class::PRIVATE_TOKEN_HEADER] = personal_access_token.token
end end
it { is_expected.to eq user } it { is_expected.to eq user }
...@@ -277,7 +312,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -277,7 +312,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#deploy_token_from_request' do describe '#deploy_token_from_request' do
let_it_be(:deploy_token) { create(:deploy_token) } let_it_be(:deploy_token, freeze: true) { create(:deploy_token) }
let_it_be(:route_authentication_setting) { { deploy_token_allowed: true } } let_it_be(:route_authentication_setting) { { deploy_token_allowed: true } }
subject { deploy_token_from_request } subject { deploy_token_from_request }
...@@ -293,11 +328,13 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -293,11 +328,13 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'with deploy token headers' do context 'with deploy token headers' do
context 'with valid deploy token' do
before do before do
set_header(described_class::DEPLOY_TOKEN_HEADER, deploy_token.token) set_header(described_class::DEPLOY_TOKEN_HEADER, deploy_token.token)
end end
it { is_expected.to eq deploy_token } it { is_expected.to eq deploy_token }
end
it_behaves_like 'an unauthenticated route' it_behaves_like 'an unauthenticated route'
...@@ -311,17 +348,19 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -311,17 +348,19 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'with oauth headers' do context 'with oauth headers' do
context 'with valid token' do
before do before do
set_header('HTTP_AUTHORIZATION', "Bearer #{deploy_token.token}") set_bearer_token(deploy_token.token)
end end
it { is_expected.to eq deploy_token } it { is_expected.to eq deploy_token }
it_behaves_like 'an unauthenticated route' it_behaves_like 'an unauthenticated route'
end
context 'with invalid token' do context 'with invalid token' do
before do before do
set_header('HTTP_AUTHORIZATION', "Bearer invalid_token") set_bearer_token('invalid_token')
end end
it { is_expected.to be_nil } it { is_expected.to be_nil }
...@@ -348,8 +387,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -348,8 +387,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#find_user_from_access_token' do describe '#find_user_from_access_token' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
before do before do
set_header('SCRIPT_NAME', 'url.atom') set_header('SCRIPT_NAME', 'url.atom')
end end
...@@ -374,24 +411,34 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -374,24 +411,34 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'with OAuth headers' do context 'with OAuth headers' do
it 'returns user' do context 'with valid personal access token' do
set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}") before do
set_bearer_token(personal_access_token.token)
end
it 'returns user' do
expect(find_user_from_access_token).to eq user expect(find_user_from_access_token).to eq user
end end
end
it 'returns exception if invalid personal_access_token' do context 'with invalid personal_access_token' do
env['HTTP_AUTHORIZATION'] = 'Bearer invalid_20byte_token' before do
set_bearer_token('invalid_20byte_token')
end
it 'returns exception' do
expect { find_personal_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError) expect { find_personal_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
end end
end
context 'when using a non-prefixed access token' do context 'when using a non-prefixed access token' do
let_it_be(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) } let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, :no_prefix, user: user) }
it 'returns user' do before do
set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}") set_bearer_token(personal_access_token.token)
end
it 'returns user' do
expect(find_user_from_access_token).to eq user expect(find_user_from_access_token).to eq user
end end
end end
...@@ -399,8 +446,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -399,8 +446,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#find_user_from_web_access_token' do describe '#find_user_from_web_access_token' do
let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
before do before do
set_header(described_class::PRIVATE_TOKEN_HEADER, personal_access_token.token) set_header(described_class::PRIVATE_TOKEN_HEADER, personal_access_token.token)
end end
...@@ -451,9 +496,9 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -451,9 +496,9 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'when the token has read_api scope' do context 'when the token has read_api scope' do
before do let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, user: user, scopes: ['read_api']) }
personal_access_token.update!(scopes: ['read_api'])
before do
set_header('SCRIPT_NAME', '/api/endpoint') set_header('SCRIPT_NAME', '/api/endpoint')
end end
...@@ -481,8 +526,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -481,8 +526,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#find_personal_access_token' do describe '#find_personal_access_token' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
before do before do
set_header('SCRIPT_NAME', 'url.atom') set_header('SCRIPT_NAME', 'url.atom')
end end
...@@ -516,21 +559,23 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -516,21 +559,23 @@ RSpec.describe Gitlab::Auth::AuthFinders do
describe '#find_oauth_access_token' do describe '#find_oauth_access_token' 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) }
let(:token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') } let(:doorkeeper_access_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
context 'passed as header' do context 'passed as header' do
it 'returns token if valid oauth_access_token' do before do
set_header('HTTP_AUTHORIZATION', "Bearer #{token.token}") set_bearer_token(doorkeeper_access_token.token)
end
expect(find_oauth_access_token.token).to eq token.token it 'returns token if valid oauth_access_token' do
expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
end end
end end
context 'passed as param' do context 'passed as param' do
it 'returns user if valid oauth_access_token' do it 'returns user if valid oauth_access_token' do
set_param(:access_token, token.token) set_param(:access_token, doorkeeper_access_token.token)
expect(find_oauth_access_token.token).to eq token.token expect(find_oauth_access_token.token).to eq doorkeeper_access_token.token
end end
end end
...@@ -538,12 +583,16 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -538,12 +583,16 @@ RSpec.describe Gitlab::Auth::AuthFinders do
expect(find_oauth_access_token).to be_nil expect(find_oauth_access_token).to be_nil
end end
it 'returns exception if invalid oauth_access_token' do context 'with invalid token' do
set_header('HTTP_AUTHORIZATION', "Bearer invalid_token") before do
set_bearer_token('invalid_token')
end
it 'returns exception if invalid oauth_access_token' do
expect { find_oauth_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError) expect { find_oauth_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
end end
end end
end
describe '#find_personal_access_token_from_http_basic_auth' do describe '#find_personal_access_token_from_http_basic_auth' do
def auth_header_with(token) def auth_header_with(token)
...@@ -551,7 +600,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -551,7 +600,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'access token is valid' do context 'access token is valid' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:route_authentication_setting) { { basic_auth_personal_access_token: true } } let(:route_authentication_setting) { { basic_auth_personal_access_token: true } }
it 'finds the token from basic auth' do it 'finds the token from basic auth' do
...@@ -572,8 +620,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -572,8 +620,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'route_setting is not set' do context 'route_setting is not set' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
it 'returns nil' do it 'returns nil' do
auth_header_with(personal_access_token.token) auth_header_with(personal_access_token.token)
...@@ -582,7 +628,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -582,7 +628,6 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'route_setting is not correct' do context 'route_setting is not correct' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let(:route_authentication_setting) { { basic_auth_personal_access_token: false } } let(:route_authentication_setting) { { basic_auth_personal_access_token: false } }
it 'returns nil' do it 'returns nil' do
...@@ -629,44 +674,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -629,44 +674,18 @@ RSpec.describe Gitlab::Auth::AuthFinders do
context 'with CI username' do context 'with CI username' do
let(:username) { ::Gitlab::Auth::CI_JOB_USER } let(:username) { ::Gitlab::Auth::CI_JOB_USER }
let_it_be(:user) { create(:user) } before do
let_it_be(:build) { create(:ci_build, user: user, status: :running) } set_basic_auth_header(username, token)
it 'returns nil without password' do
set_basic_auth_header(username, nil)
is_expected.to be_nil
end
it 'returns user with valid token' do
set_basic_auth_header(username, build.token)
is_expected.to eq user
expect(@current_authenticated_job).to eq build
end
it 'raises error with invalid token' do
set_basic_auth_header(username, 'token')
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end end
it 'returns exception if the job is not running' do it_behaves_like 'find user from job token', :user
set_basic_auth_header(username, build.token)
build.success!
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end end
end end
describe '#validate_access_token!' do describe '#validate_access_token!' do
subject { validate_access_token! } subject { validate_access_token! }
let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
context 'with a job token' do context 'with a job token' do
let_it_be(:job) { create(:ci_build, user: user, status: :running) }
let(:route_authentication_setting) { { job_token_allowed: true } } let(:route_authentication_setting) { { job_token_allowed: true } }
before do before do
...@@ -684,6 +703,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -684,6 +703,8 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'token is not valid' do context 'token is not valid' do
let_it_be_with_reload(:personal_access_token) { create(:personal_access_token, user: user) }
before do before do
allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token) allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token)
end end
...@@ -706,7 +727,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -706,7 +727,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
context 'with impersonation token' do context 'with impersonation token' do
let_it_be(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) } let_it_be(:personal_access_token, freeze: true) { create(:personal_access_token, :impersonation, user: user) }
context 'when impersonation is disabled' do context 'when impersonation is disabled' do
before do before do
...@@ -722,96 +743,30 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -722,96 +743,30 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#find_user_from_job_token' do describe '#find_user_from_job_token' do
let_it_be(:job) { create(:ci_build, user: user, status: :running) }
let(:route_authentication_setting) { { job_token_allowed: true } }
subject { find_user_from_job_token } subject { find_user_from_job_token }
context 'when the job token is in the headers' do context 'when the token is in the headers' do
it 'returns the user if valid job token' do
set_header(described_class::JOB_TOKEN_HEADER, job.token)
is_expected.to eq(user)
expect(@current_authenticated_job).to eq(job)
end
it 'returns nil without job token' do
set_header(described_class::JOB_TOKEN_HEADER, '')
is_expected.to be_nil
end
it 'returns exception if invalid job token' do
set_header(described_class::JOB_TOKEN_HEADER, 'invalid token')
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
it 'returns exception if the job is not running' do
set_header(described_class::JOB_TOKEN_HEADER, job.token)
job.success!
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
context 'when route is not allowed to be authenticated' do
let(:route_authentication_setting) { { job_token_allowed: false } }
it 'sets current_user to nil' do
set_header(described_class::JOB_TOKEN_HEADER, job.token)
allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(true)
is_expected.to be_nil
end
end
end
context 'when the job token is in the params' do
shared_examples 'job token params' do |token_key_name|
before do before do
set_param(token_key_name, token) set_header(described_class::JOB_TOKEN_HEADER, token)
end end
context 'with valid job token' do it_behaves_like 'find user from job token'
let(:token) { job.token }
it 'returns the user' do
is_expected.to eq(user)
expect(@current_authenticated_job).to eq(job)
end
end end
context 'with empty job token' do context 'when the token is in the job_token param' do
let(:token) { '' } before do
set_param(described_class::JOB_TOKEN_PARAM, token)
it 'returns nil' do
is_expected.to be_nil
end
end end
context 'with invalid job token' do it_behaves_like 'find user from job token'
let(:token) { 'invalid token' }
it 'returns exception' do
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end end
context 'when route is not allowed to be authenticated' do context 'when the token is in the token param' do
let(:route_authentication_setting) { { job_token_allowed: false } } before do
let(:token) { job.token } set_param(described_class::RUNNER_JOB_TOKEN_PARAM, token)
it 'sets current_user to nil' do
allow_any_instance_of(Gitlab::UserAccess).to receive(:allowed?).and_return(true)
is_expected.to be_nil
end
end
end end
it_behaves_like 'job token params', described_class::JOB_TOKEN_PARAM it_behaves_like 'find user from job token'
it_behaves_like 'job token params', described_class::RUNNER_JOB_TOKEN_PARAM
end end
context 'when the job token is provided via basic auth' do context 'when the job token is provided via basic auth' do
...@@ -834,7 +789,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -834,7 +789,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#cluster_agent_token_from_authorization_token' do describe '#cluster_agent_token_from_authorization_token' do
let_it_be(:agent_token) { create(:cluster_agent_token) } let_it_be(:agent_token, freeze: true) { create(:cluster_agent_token) }
context 'when route_setting is empty' do context 'when route_setting is empty' do
it 'returns nil' do it 'returns nil' do
...@@ -884,7 +839,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do ...@@ -884,7 +839,7 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end end
describe '#find_runner_from_token' do describe '#find_runner_from_token' do
let_it_be(:runner) { create(:ci_runner) } let_it_be(:runner, freeze: true) { create(:ci_runner) }
context 'with API requests' do context 'with API requests' do
before do before do
......
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