Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/auth')
-rw-r--r--spec/lib/gitlab/auth/auth_finders_spec.rb17
-rw-r--r--spec/lib/gitlab/auth/crowd/authentication_spec.rb48
-rw-r--r--spec/lib/gitlab/auth/ldap/user_spec.rb17
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb17
-rw-r--r--spec/lib/gitlab/auth/otp/session_enforcer_spec.rb41
-rw-r--r--spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb24
-rw-r--r--spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb87
-rw-r--r--spec/lib/gitlab/auth/request_authenticator_spec.rb56
8 files changed, 278 insertions, 29 deletions
diff --git a/spec/lib/gitlab/auth/auth_finders_spec.rb b/spec/lib/gitlab/auth/auth_finders_spec.rb
index 3c19ef0bd1b..f927d5912bb 100644
--- a/spec/lib/gitlab/auth/auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/auth_finders_spec.rb
@@ -147,6 +147,13 @@ RSpec.describe Gitlab::Auth::AuthFinders do
expect(find_user_from_feed_token(:rss)).to eq user
end
+ it 'returns nil if valid feed_token and disabled' do
+ allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true)
+ set_param(:feed_token, user.feed_token)
+
+ expect(find_user_from_feed_token(:rss)).to be_nil
+ end
+
it 'returns nil if feed_token is blank' do
expect(find_user_from_feed_token(:rss)).to be_nil
end
@@ -377,6 +384,16 @@ RSpec.describe Gitlab::Auth::AuthFinders do
expect { find_personal_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
+
+ context 'when using a non-prefixed access token' do
+ let(:personal_access_token) { create(:personal_access_token, :no_prefix, user: user) }
+
+ it 'returns user' do
+ set_header('HTTP_AUTHORIZATION', "Bearer #{personal_access_token.token}")
+
+ expect(find_user_from_access_token).to eq user
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/auth/crowd/authentication_spec.rb b/spec/lib/gitlab/auth/crowd/authentication_spec.rb
new file mode 100644
index 00000000000..71eb8036fdd
--- /dev/null
+++ b/spec/lib/gitlab/auth/crowd/authentication_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Crowd::Authentication do
+ let(:provider) { 'crowd' }
+ let(:login) { generate(:username) }
+ let(:password) { 'password' }
+ let(:crowd_auth) { described_class.new(provider) }
+ let(:user_info) { { user: login } }
+
+ describe 'login' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:enabled?).with(provider).and_return(true)
+ allow(crowd_auth).to receive(:user_info_from_authentication).and_return(user_info)
+ end
+
+ it "finds the user if authentication is successful" do
+ create(:omniauth_user, extern_uid: login, username: login, provider: provider)
+
+ expect(crowd_auth.login(login, password)).to be_truthy
+ end
+
+ it "is false if the user does not exist" do
+ expect(crowd_auth.login(login, password)).to be_falsey
+ end
+
+ it "is false if the authentication fails" do
+ allow(crowd_auth).to receive(:user_info_from_authentication).and_return(nil)
+
+ expect(crowd_auth.login(login, password)).to be_falsey
+ end
+
+ it "fails when crowd is disabled" do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:enabled?).with('crowd').and_return(false)
+
+ expect(crowd_auth.login(login, password)).to be_falsey
+ end
+
+ it "fails if no login is supplied" do
+ expect(crowd_auth.login('', password)).to be_falsey
+ end
+
+ it "fails if no password is supplied" do
+ expect(crowd_auth.login(login, '')).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/ldap/user_spec.rb b/spec/lib/gitlab/auth/ldap/user_spec.rb
index ccaed94b5c8..e910ac09448 100644
--- a/spec/lib/gitlab/auth/ldap/user_spec.rb
+++ b/spec/lib/gitlab/auth/ldap/user_spec.rb
@@ -49,23 +49,6 @@ RSpec.describe Gitlab::Auth::Ldap::User do
end
end
- describe '.find_by_uid_and_provider' do
- let(:dn) { 'CN=John Åström, CN=Users, DC=Example, DC=com' }
-
- it 'retrieves the correct user' do
- special_info = {
- name: 'John Åström',
- email: 'john@example.com',
- nickname: 'jastrom'
- }
- special_hash = OmniAuth::AuthHash.new(uid: dn, provider: 'ldapmain', info: special_info)
- special_chars_user = described_class.new(special_hash)
- user = special_chars_user.save
-
- expect(described_class.find_by_uid_and_provider(dn, 'ldapmain')).to eq user
- end
- end
-
describe 'find or create' do
it "finds the user if already existing" do
create(:omniauth_user, extern_uid: 'uid=john smith,ou=people,dc=example,dc=com', provider: 'ldapmain')
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index 243d0a4cb45..6c6cee9c273 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -25,6 +25,23 @@ RSpec.describe Gitlab::Auth::OAuth::User do
let(:ldap_user) { Gitlab::Auth::Ldap::Person.new(Net::LDAP::Entry.new, 'ldapmain') }
+ describe '.find_by_uid_and_provider' do
+ let(:dn) { 'CN=John Åström, CN=Users, DC=Example, DC=com' }
+
+ it 'retrieves the correct user' do
+ special_info = {
+ name: 'John Åström',
+ email: 'john@example.com',
+ nickname: 'jastrom'
+ }
+ special_hash = OmniAuth::AuthHash.new(uid: dn, provider: 'ldapmain', info: special_info)
+ special_chars_user = described_class.new(special_hash)
+ user = special_chars_user.save
+
+ expect(described_class.find_by_uid_and_provider(dn, 'ldapmain')).to eq user
+ end
+ end
+
describe '#persisted?' do
let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
diff --git a/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb b/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb
new file mode 100644
index 00000000000..928aade4008
--- /dev/null
+++ b/spec/lib/gitlab/auth/otp/session_enforcer_spec.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Otp::SessionEnforcer, :clean_gitlab_redis_shared_state do
+ let_it_be(:key) { create(:key)}
+
+ describe '#update_session' do
+ it 'registers a session in Redis' do
+ redis = double(:redis)
+ expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
+
+ expect(redis).to(
+ receive(:setex)
+ .with("#{described_class::OTP_SESSIONS_NAMESPACE}:#{key.id}",
+ described_class::DEFAULT_EXPIRATION,
+ true)
+ .once)
+
+ described_class.new(key).update_session
+ end
+ end
+
+ describe '#access_restricted?' do
+ subject { described_class.new(key).access_restricted? }
+
+ context 'with existing session' do
+ before do
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set("#{described_class::OTP_SESSIONS_NAMESPACE}:#{key.id}", true )
+ end
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'without an existing session' do
+ it { is_expected.to be_truthy }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb b/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
index 18fd6d08057..88a245b6b10 100644
--- a/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/otp/strategies/forti_authenticator_spec.rb
@@ -12,30 +12,32 @@ RSpec.describe Gitlab::Auth::Otp::Strategies::FortiAuthenticator do
let(:api_token) { 's3cr3t' }
let(:forti_authenticator_auth_url) { "https://#{host}:#{port}/api/v1/auth/" }
+ let(:response_status) { 200 }
subject(:validate) { described_class.new(user).validate(otp_code) }
before do
- stub_feature_flags(forti_authenticator: true)
+ stub_feature_flags(forti_authenticator: user)
stub_forti_authenticator_config(
+ enabled: true,
host: host,
port: port,
username: api_username,
- token: api_token
+ access_token: api_token
)
request_body = { username: user.username,
token_code: otp_code }
stub_request(:post, forti_authenticator_auth_url)
- .with(body: JSON(request_body), headers: { 'Content-Type' => 'application/json' })
- .to_return(status: response_status, body: '', headers: {})
+ .with(body: JSON(request_body),
+ headers: { 'Content-Type': 'application/json' },
+ basic_auth: [api_username, api_token])
+ .to_return(status: response_status, body: '')
end
context 'successful validation' do
- let(:response_status) { 200 }
-
it 'returns success' do
expect(validate[:status]).to eq(:success)
end
@@ -49,6 +51,16 @@ RSpec.describe Gitlab::Auth::Otp::Strategies::FortiAuthenticator do
end
end
+ context 'unexpected error' do
+ it 'returns error' do
+ error_message = 'boom!'
+ stub_request(:post, forti_authenticator_auth_url).to_raise(StandardError.new(error_message))
+
+ expect(validate[:status]).to eq(:error)
+ expect(validate[:message]).to eq(error_message)
+ end
+ end
+
def stub_forti_authenticator_config(forti_authenticator_settings)
allow(::Gitlab.config.forti_authenticator).to(receive_messages(forti_authenticator_settings))
end
diff --git a/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb b/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
new file mode 100644
index 00000000000..1580fc82279
--- /dev/null
+++ b/spec/lib/gitlab/auth/otp/strategies/forti_token_cloud_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Auth::Otp::Strategies::FortiTokenCloud do
+ let_it_be(:user) { create(:user) }
+ let(:otp_code) { 42 }
+
+ let(:url) { 'https://ftc.example.com:9696/api/v1' }
+ let(:client_id) { 'client_id' }
+ let(:client_secret) { 's3cr3t' }
+ let(:access_token_create_url) { url + '/login' }
+ let(:otp_verification_url) { url + '/auth' }
+ let(:access_token) { 'an_access_token' }
+ let(:access_token_create_response_body) { '' }
+
+ subject(:validate) { described_class.new(user).validate(otp_code) }
+
+ before do
+ stub_feature_flags(forti_token_cloud: user)
+
+ stub_const("#{described_class}::BASE_API_URL", url)
+
+ stub_forti_token_cloud_config(
+ enabled: true,
+ client_id: client_id,
+ client_secret: client_secret
+ )
+
+ access_token_request_body = { client_id: client_id,
+ client_secret: client_secret }
+
+ stub_request(:post, access_token_create_url)
+ .with(body: JSON(access_token_request_body), headers: { 'Content-Type' => 'application/json' })
+ .to_return(
+ status: access_token_create_response_status,
+ body: Gitlab::Json.generate(access_token_create_response_body),
+ headers: {}
+ )
+ end
+
+ context 'access token is created successfully' do
+ let(:access_token_create_response_body) { { access_token: access_token, expires_in: 3600 } }
+ let(:access_token_create_response_status) { 201 }
+
+ before do
+ otp_verification_request_body = { username: user.username,
+ token: otp_code }
+
+ stub_request(:post, otp_verification_url)
+ .with(body: JSON(otp_verification_request_body),
+ headers: {
+ 'Content-Type' => 'application/json',
+ 'Authorization' => "Bearer #{access_token}"
+ })
+ .to_return(status: otp_verification_response_status, body: '', headers: {})
+ end
+
+ context 'otp verification is successful' do
+ let(:otp_verification_response_status) { 200 }
+
+ it 'returns success' do
+ expect(validate[:status]).to eq(:success)
+ end
+ end
+
+ context 'otp verification is not successful' do
+ let(:otp_verification_response_status) { 401 }
+
+ it 'returns error' do
+ expect(validate[:status]).to eq(:error)
+ end
+ end
+ end
+
+ context 'access token creation fails' do
+ let(:access_token_create_response_status) { 400 }
+
+ it 'returns error' do
+ expect(validate[:status]).to eq(:error)
+ end
+ end
+
+ def stub_forti_token_cloud_config(forti_token_cloud_settings)
+ allow(::Gitlab.config.forti_token_cloud).to(receive_messages(forti_token_cloud_settings))
+ end
+end
diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb
index b89ceb37076..ef6b1d72712 100644
--- a/spec/lib/gitlab/auth/request_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb
@@ -50,13 +50,13 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_return(access_token_user)
allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
- expect(subject.find_sessionless_user([:api])).to eq access_token_user
+ expect(subject.find_sessionless_user(:api)).to eq access_token_user
end
it 'returns feed_token user if no access_token user found' do
allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
- expect(subject.find_sessionless_user([:api])).to eq feed_token_user
+ expect(subject.find_sessionless_user(:api)).to eq feed_token_user
end
it 'returns static_object_token user if no feed_token user found' do
@@ -64,7 +64,7 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
.to receive(:find_user_from_static_object_token)
.and_return(static_object_token_user)
- expect(subject.find_sessionless_user([:api])).to eq static_object_token_user
+ expect(subject.find_sessionless_user(:api)).to eq static_object_token_user
end
it 'returns job_token user if no static_object_token user found' do
@@ -72,17 +72,61 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
.to receive(:find_user_from_job_token)
.and_return(job_token_user)
- expect(subject.find_sessionless_user([:api])).to eq job_token_user
+ expect(subject.find_sessionless_user(:api)).to eq job_token_user
end
it 'returns nil if no user found' do
- expect(subject.find_sessionless_user([:api])).to be_blank
+ expect(subject.find_sessionless_user(:api)).to be_blank
end
it 'rescue Gitlab::Auth::AuthenticationError exceptions' do
allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_raise(Gitlab::Auth::UnauthorizedError)
- expect(subject.find_sessionless_user([:api])).to be_blank
+ expect(subject.find_sessionless_user(:api)).to be_blank
+ end
+ end
+
+ describe '#find_personal_access_token_from_http_basic_auth' do
+ let_it_be(:personal_access_token) { create(:personal_access_token) }
+ let_it_be(:user) { personal_access_token.user }
+
+ before do
+ allow(subject).to receive(:has_basic_credentials?).and_return(true)
+ allow(subject).to receive(:user_name_and_password).and_return([user.username, personal_access_token.token])
+ end
+
+ context 'with API requests' do
+ before do
+ env['SCRIPT_NAME'] = '/api/endpoint'
+ end
+
+ it 'tries to find the user' do
+ expect(subject.user([:api])).to eq user
+ end
+
+ it 'returns nil if the token is revoked' do
+ personal_access_token.revoke!
+
+ expect(subject.user([:api])).to be_blank
+ end
+
+ it 'returns nil if the token does not have API scope' do
+ personal_access_token.update!(scopes: ['read_registry'])
+
+ expect(subject.user([:api])).to be_blank
+ end
+ end
+
+ context 'without API requests' do
+ before do
+ env['SCRIPT_NAME'] = '/web/endpoint'
+ end
+
+ it 'does not search for job users' do
+ expect(PersonalAccessToken).not_to receive(:find_by_token)
+
+ expect(subject.user([:api])).to be_nil
+ end
end
end