Commit b67a72df authored by Imre Farkas's avatar Imre Farkas

Merge branch 'group-token-http-authenticate' into 'master'

Group token HTTP authentication

See merge request gitlab-org/gitlab!65788
parents 6de091d8 e59a8e9a
...@@ -199,13 +199,29 @@ module Gitlab ...@@ -199,13 +199,29 @@ module Gitlab
return unless valid_scoped_token?(token, all_available_scopes) return unless valid_scoped_token?(token, all_available_scopes)
return if project && token.user.project_bot? && !project.bots.include?(token.user) if project && token.user.project_bot?
return unless token_bot_in_project?(token.user, project) || token_bot_in_group?(token.user, project)
end
if can_user_login_with_non_expired_password?(token.user) || token.user.project_bot? if can_user_login_with_non_expired_password?(token.user) || token.user.project_bot?
Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes)) Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes))
end end
end end
def token_bot_in_project?(user, project)
project.bots.include?(user)
end
# rubocop: disable CodeReuse/ActiveRecord
# A workaround for adding group-level automation is to add the bot user of a project access token as a group member.
# In order to make project access tokens work this way during git authentication, we need to add an additional check for group membership.
# This is a temporary workaround until service accounts are implemented.
def token_bot_in_group?(user, project)
project.group && project.group.members_with_parents.where(user_id: user.id).exists?
end
# rubocop: enable CodeReuse/ActiveRecord
def valid_oauth_token?(token) def valid_oauth_token?(token)
token && token.accessible? && valid_scoped_token?(token, [:api]) token && token.accessible? && valid_scoped_token?(token, [:api])
end end
......
...@@ -360,32 +360,23 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do ...@@ -360,32 +360,23 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end end
end end
context 'when using a project access token' do context 'when using a resource access token' do
let_it_be(:project_bot_user) { create(:user, :project_bot) } shared_examples 'with a valid access token' do
let_it_be(:project_access_token) { create(:personal_access_token, user: project_bot_user) }
context 'with valid project access token' do
before do
project.add_maintainer(project_bot_user)
end
it 'successfully authenticates the project bot' do it 'successfully authenticates the project bot' do
expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: project, ip: 'ip')) expect(gl_auth.find_for_git_client(project_bot_user.username, access_token.token, project: project, ip: 'ip'))
.to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities)) .to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities))
end end
it 'successfully authenticates the project bot with a nil project' do it 'successfully authenticates the project bot with a nil project' do
expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: nil, ip: 'ip')) expect(gl_auth.find_for_git_client(project_bot_user.username, access_token.token, project: nil, ip: 'ip'))
.to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities)) .to eq(Gitlab::Auth::Result.new(project_bot_user, nil, :personal_access_token, described_class.full_authentication_abilities))
end end
end end
context 'with invalid project access token' do shared_examples 'with an invalid access token' do
context 'when project bot is not a project member' do it 'fails for a non-member' do
it 'fails for a non-project member' do expect(gl_auth.find_for_git_client(project_bot_user.username, access_token.token, project: project, ip: 'ip'))
expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: project, ip: 'ip')) .to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
.to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
end
end end
context 'when project bot user is blocked' do context 'when project bot user is blocked' do
...@@ -394,11 +385,61 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do ...@@ -394,11 +385,61 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
end end
it 'fails for a blocked project bot' do it 'fails for a blocked project bot' do
expect(gl_auth.find_for_git_client(project_bot_user.username, project_access_token.token, project: project, ip: 'ip')) expect(gl_auth.find_for_git_client(project_bot_user.username, access_token.token, project: project, ip: 'ip'))
.to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil)) .to eq(Gitlab::Auth::Result.new(nil, nil, nil, nil))
end end
end end
end end
context 'when using a personal namespace project access token' do
let_it_be(:project_bot_user) { create(:user, :project_bot) }
let_it_be(:access_token) { create(:personal_access_token, user: project_bot_user) }
context 'when the token belongs to the project' do
before do
project.add_maintainer(project_bot_user)
end
it_behaves_like 'with a valid access token'
end
it_behaves_like 'with an invalid access token'
end
context 'when in a group namespace' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
context 'when using a project access token' do
let_it_be(:project_bot_user) { create(:user, :project_bot) }
let_it_be(:access_token) { create(:personal_access_token, user: project_bot_user) }
context 'when token user belongs to the project' do
before do
project.add_maintainer(project_bot_user)
end
it_behaves_like 'with a valid access token'
end
it_behaves_like 'with an invalid access token'
end
context 'when using a group access token' do
let_it_be(:project_bot_user) { create(:user, name: 'Group token bot', email: "group_#{group.id}_bot@example.com", username: "group_#{group.id}_bot", user_type: :project_bot) }
let_it_be(:access_token) { create(:personal_access_token, user: project_bot_user) }
context 'when the token belongs to the group' do
before do
group.add_maintainer(project_bot_user)
end
it_behaves_like 'with a valid access token'
end
it_behaves_like 'with an invalid access token'
end
end
end end
end end
......
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