Added write_repository scope for personal access token
This commit is contained in:
parent
922fae29ca
commit
0aa56d895d
|
@ -49,7 +49,7 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
|
||||||
|
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def set_index_vars
|
def set_index_vars
|
||||||
@scopes = Gitlab::Auth.available_scopes(current_user)
|
@scopes = Gitlab::Auth.available_scopes_for(current_user)
|
||||||
|
|
||||||
@impersonation_token ||= finder.build
|
@impersonation_token ||= finder.build
|
||||||
@inactive_impersonation_tokens = finder(state: 'inactive').execute
|
@inactive_impersonation_tokens = finder(state: 'inactive').execute
|
||||||
|
|
|
@ -22,7 +22,7 @@ class JwtController < ApplicationController
|
||||||
private
|
private
|
||||||
|
|
||||||
def authenticate_project_or_user
|
def authenticate_project_or_user
|
||||||
@authentication_result = Gitlab::Auth::Result.new(nil, nil, :none, Gitlab::Auth.read_authentication_abilities)
|
@authentication_result = Gitlab::Auth::Result.new(nil, nil, :none, Gitlab::Auth.read_only_authentication_abilities)
|
||||||
|
|
||||||
authenticate_with_http_basic do |login, password|
|
authenticate_with_http_basic do |login, password|
|
||||||
@authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip)
|
@authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip)
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
|
||||||
|
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
def set_index_vars
|
def set_index_vars
|
||||||
@scopes = Gitlab::Auth.available_scopes(current_user)
|
@scopes = Gitlab::Auth.available_scopes_for(current_user)
|
||||||
|
|
||||||
@inactive_personal_access_tokens = finder(state: 'inactive').execute
|
@inactive_personal_access_tokens = finder(state: 'inactive').execute
|
||||||
@active_personal_access_tokens = finder(state: 'active').execute.order(:expires_at)
|
@active_personal_access_tokens = finder(state: 'active').execute.order(:expires_at)
|
||||||
|
|
|
@ -83,7 +83,7 @@ class Projects::GitHttpClientController < Projects::ApplicationController
|
||||||
|
|
||||||
def render_missing_personal_access_token
|
def render_missing_personal_access_token
|
||||||
render plain: "HTTP Basic: Access denied\n" \
|
render plain: "HTTP Basic: Access denied\n" \
|
||||||
"You must use a personal access token with 'api' scope for Git over HTTP.\n" \
|
"You must use a personal access token with 'read_repository' or 'write_repository' scope for Git over HTTP.\n" \
|
||||||
"You can generate one at #{profile_personal_access_tokens_url}",
|
"You can generate one at #{profile_personal_access_tokens_url}",
|
||||||
status: :unauthorized
|
status: :unauthorized
|
||||||
end
|
end
|
||||||
|
|
|
@ -56,7 +56,7 @@ class PersonalAccessToken < ApplicationRecord
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def validate_scopes
|
def validate_scopes
|
||||||
unless revoked || scopes.all? { |scope| Gitlab::Auth.available_scopes.include?(scope.to_sym) }
|
unless revoked || scopes.all? { |scope| Gitlab::Auth.all_available_scopes.include?(scope.to_sym) }
|
||||||
errors.add :scopes, "can only contain available scopes"
|
errors.add :scopes, "can only contain available scopes"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Added write_repository scope for personal access token
|
||||||
|
merge_request: 26021
|
||||||
|
author: Horatiu Eugen Vlad
|
||||||
|
type: added
|
|
@ -60,7 +60,8 @@ en:
|
||||||
scopes:
|
scopes:
|
||||||
api: Access the authenticated user's API
|
api: Access the authenticated user's API
|
||||||
read_user: Read the authenticated user's personal information
|
read_user: Read the authenticated user's personal information
|
||||||
read_repository: Allows read-access to the repository
|
read_repository: Allows read-only access to the repository
|
||||||
|
write_repository: Allows read-write access to the repository
|
||||||
read_registry: Grants permission to read container registry images
|
read_registry: Grants permission to read container registry images
|
||||||
openid: Authenticate using OpenID Connect
|
openid: Authenticate using OpenID Connect
|
||||||
sudo: Perform API actions as any user in the system
|
sudo: Perform API actions as any user in the system
|
||||||
|
@ -73,6 +74,8 @@ en:
|
||||||
Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users.
|
Grants read-only access to the authenticated user's profile through the /user API endpoint, which includes username, public email, and full name. Also grants access to read-only API endpoints under /users.
|
||||||
read_repository:
|
read_repository:
|
||||||
Grants read-only access to repositories on private projects using Git-over-HTTP (not using the API).
|
Grants read-only access to repositories on private projects using Git-over-HTTP (not using the API).
|
||||||
|
write_repository:
|
||||||
|
Grants read-write access to repositories on private projects using Git-over-HTTP (not using the API).
|
||||||
read_registry:
|
read_registry:
|
||||||
Grants read-only access to container registry images on private projects.
|
Grants read-only access to container registry images on private projects.
|
||||||
openid:
|
openid:
|
||||||
|
|
|
@ -40,10 +40,11 @@ the following table.
|
||||||
| Scope | Description |
|
| Scope | Description |
|
||||||
| ----- | ----------- |
|
| ----- | ----------- |
|
||||||
|`read_user` | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed ([introduced][ce-5951] in GitLab 8.15). |
|
|`read_user` | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed ([introduced][ce-5951] in GitLab 8.15). |
|
||||||
| `api` | Grants complete access to the API and Container Registry (read/write) ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) in GitLab 8.15). Required for accessing Git repositories over HTTP when 2FA is enabled. |
|
| `api` | Grants complete access to the API and Container Registry (read/write) ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) in GitLab 8.15). |
|
||||||
| `read_registry` | Allows to read (pull) [container registry] images if a project is private and authorization is required ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 9.3). |
|
| `read_registry` | Allows to read (pull) [container registry] images if a project is private and authorization is required ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 9.3). |
|
||||||
| `sudo` | Allows performing API actions as any user in the system (if the authenticated user is an admin) ([introduced][ce-14838] in GitLab 10.2). |
|
| `sudo` | Allows performing API actions as any user in the system (if the authenticated user is an admin) ([introduced][ce-14838] in GitLab 10.2). |
|
||||||
| `read_repository` | Allows read-access (pull) to the repository through git clone. |
|
| `read_repository` | Allows read-only access (pull) to the repository through git clone. |
|
||||||
|
| `write_repository` | Allows read-write access (pull, push) to the repository through git clone. Required for accessing Git repositories over HTTP when 2FA is enabled. |
|
||||||
|
|
||||||
[2fa]: ../account/two_factor_authentication.md
|
[2fa]: ../account/two_factor_authentication.md
|
||||||
[api]: ../../api/README.md
|
[api]: ../../api/README.md
|
||||||
|
|
|
@ -4,10 +4,17 @@ module Gitlab
|
||||||
module Auth
|
module Auth
|
||||||
MissingPersonalAccessTokenError = Class.new(StandardError)
|
MissingPersonalAccessTokenError = Class.new(StandardError)
|
||||||
|
|
||||||
|
# Scopes used for GitLab API access
|
||||||
|
API_SCOPES = [:api, :read_user].freeze
|
||||||
|
|
||||||
|
# Scopes used for GitLab Repository access
|
||||||
|
REPOSITORY_SCOPES = [:read_repository, :write_repository].freeze
|
||||||
|
|
||||||
|
# Scopes used for GitLab Docker Registry access
|
||||||
REGISTRY_SCOPES = [:read_registry].freeze
|
REGISTRY_SCOPES = [:read_registry].freeze
|
||||||
|
|
||||||
# Scopes used for GitLab API access
|
# Scopes used for GitLab as admin
|
||||||
API_SCOPES = [:api, :read_user, :sudo, :read_repository].freeze
|
ADMIN_SCOPES = [:sudo].freeze
|
||||||
|
|
||||||
# Scopes used for OpenID Connect
|
# Scopes used for OpenID Connect
|
||||||
OPENID_SCOPES = [:openid].freeze
|
OPENID_SCOPES = [:openid].freeze
|
||||||
|
@ -159,7 +166,7 @@ module Gitlab
|
||||||
|
|
||||||
token = PersonalAccessTokensFinder.new(state: 'active').find_by_token(password)
|
token = PersonalAccessTokensFinder.new(state: 'active').find_by_token(password)
|
||||||
|
|
||||||
if token && valid_scoped_token?(token, available_scopes)
|
if token && valid_scoped_token?(token, all_available_scopes)
|
||||||
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
|
||||||
|
@ -176,7 +183,8 @@ module Gitlab
|
||||||
abilities_by_scope = {
|
abilities_by_scope = {
|
||||||
api: full_authentication_abilities,
|
api: full_authentication_abilities,
|
||||||
read_registry: [:read_container_image],
|
read_registry: [:read_container_image],
|
||||||
read_repository: [:download_code]
|
read_repository: [:download_code],
|
||||||
|
write_repository: [:download_code, :push_code]
|
||||||
}
|
}
|
||||||
|
|
||||||
scopes.flat_map do |scope|
|
scopes.flat_map do |scope|
|
||||||
|
@ -196,7 +204,7 @@ module Gitlab
|
||||||
|
|
||||||
scopes = abilities_for_scopes(token.scopes)
|
scopes = abilities_for_scopes(token.scopes)
|
||||||
|
|
||||||
if valid_scoped_token?(token, available_scopes)
|
if valid_scoped_token?(token, all_available_scopes)
|
||||||
Gitlab::Auth::Result.new(token, token.project, :deploy_token, scopes)
|
Gitlab::Auth::Result.new(token, token.project, :deploy_token, scopes)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -222,7 +230,7 @@ module Gitlab
|
||||||
elsif token_handler.deploy_key_pushable?(project)
|
elsif token_handler.deploy_key_pushable?(project)
|
||||||
read_write_authentication_abilities
|
read_write_authentication_abilities
|
||||||
else
|
else
|
||||||
read_authentication_abilities
|
read_only_authentication_abilities
|
||||||
end
|
end
|
||||||
|
|
||||||
if token_handler.token_valid?(encoded_token)
|
if token_handler.token_valid?(encoded_token)
|
||||||
|
@ -258,7 +266,7 @@ module Gitlab
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_authentication_abilities
|
def read_only_authentication_abilities
|
||||||
[
|
[
|
||||||
:read_project,
|
:read_project,
|
||||||
:download_code,
|
:download_code,
|
||||||
|
@ -267,7 +275,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_write_authentication_abilities
|
def read_write_authentication_abilities
|
||||||
read_authentication_abilities + [
|
read_only_authentication_abilities + [
|
||||||
:push_code,
|
:push_code,
|
||||||
:create_container_image
|
:create_container_image
|
||||||
]
|
]
|
||||||
|
@ -279,15 +287,19 @@ module Gitlab
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def available_scopes(current_user = nil)
|
def available_scopes_for(current_user)
|
||||||
scopes = API_SCOPES + registry_scopes
|
scopes = non_admin_available_scopes
|
||||||
scopes.delete(:sudo) if current_user && !current_user.admin?
|
scopes += ADMIN_SCOPES if current_user.admin?
|
||||||
scopes
|
scopes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def all_available_scopes
|
||||||
|
non_admin_available_scopes + ADMIN_SCOPES
|
||||||
|
end
|
||||||
|
|
||||||
# Other available scopes
|
# Other available scopes
|
||||||
def optional_scopes
|
def optional_scopes
|
||||||
available_scopes + OPENID_SCOPES + PROFILE_SCOPES - DEFAULT_SCOPES
|
all_available_scopes + OPENID_SCOPES + PROFILE_SCOPES - DEFAULT_SCOPES
|
||||||
end
|
end
|
||||||
|
|
||||||
def registry_scopes
|
def registry_scopes
|
||||||
|
@ -298,6 +310,10 @@ module Gitlab
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def non_admin_available_scopes
|
||||||
|
API_SCOPES + REPOSITORY_SCOPES + registry_scopes
|
||||||
|
end
|
||||||
|
|
||||||
def find_build_by_token(token)
|
def find_build_by_token(token)
|
||||||
::Ci::Build.running.find_by_token(token)
|
::Ci::Build.running.find_by_token(token)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,15 @@ describe Gitlab::Auth do
|
||||||
|
|
||||||
describe 'constants' do
|
describe 'constants' do
|
||||||
it 'API_SCOPES contains all scopes for API access' do
|
it 'API_SCOPES contains all scopes for API access' do
|
||||||
expect(subject::API_SCOPES).to eq %i[api read_user sudo read_repository]
|
expect(subject::API_SCOPES).to eq %i[api read_user]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'ADMIN_SCOPES contains all scopes for ADMIN access' do
|
||||||
|
expect(subject::ADMIN_SCOPES).to eq %i[sudo]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'REPOSITORY_SCOPES contains all scopes for REPOSITORY access' do
|
||||||
|
expect(subject::REPOSITORY_SCOPES).to eq %i[read_repository write_repository]
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'OPENID_SCOPES contains all scopes for OpenID Connect' do
|
it 'OPENID_SCOPES contains all scopes for OpenID Connect' do
|
||||||
|
@ -19,7 +27,29 @@ describe Gitlab::Auth do
|
||||||
it 'optional_scopes contains all non-default scopes' do
|
it 'optional_scopes contains all non-default scopes' do
|
||||||
stub_container_registry_config(enabled: true)
|
stub_container_registry_config(enabled: true)
|
||||||
|
|
||||||
expect(subject.optional_scopes).to eq %i[read_user sudo read_repository read_registry openid profile email]
|
expect(subject.optional_scopes).to eq %i[read_user read_repository write_repository read_registry sudo openid profile email]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'available_scopes' do
|
||||||
|
it 'contains all non-default scopes' do
|
||||||
|
stub_container_registry_config(enabled: true)
|
||||||
|
|
||||||
|
expect(subject.all_available_scopes).to eq %i[api read_user read_repository write_repository read_registry sudo]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains for non-admin user all non-default scopes without ADMIN access' do
|
||||||
|
stub_container_registry_config(enabled: true)
|
||||||
|
user = create(:user, admin: false)
|
||||||
|
|
||||||
|
expect(subject.available_scopes_for(user)).to eq %i[api read_user read_repository write_repository read_registry]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains for admin user all non-default scopes with ADMIN access' do
|
||||||
|
stub_container_registry_config(enabled: true)
|
||||||
|
user = create(:user, admin: true)
|
||||||
|
|
||||||
|
expect(subject.available_scopes_for(user)).to eq %i[api read_user read_repository write_repository read_registry sudo]
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'registry_scopes' do
|
context 'registry_scopes' do
|
||||||
|
@ -122,7 +152,7 @@ describe Gitlab::Auth do
|
||||||
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).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, read_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, read_only_authentication_abilities))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not try password auth before oauth' do
|
it 'does not try password auth before oauth' do
|
||||||
|
@ -150,7 +180,7 @@ describe Gitlab::Auth do
|
||||||
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).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, read_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, read_only_authentication_abilities))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -182,8 +212,19 @@ describe Gitlab::Auth do
|
||||||
it 'succeeds for personal access tokens with the `api` scope' do
|
it 'succeeds for personal access tokens with the `api` scope' do
|
||||||
personal_access_token = create(:personal_access_token, scopes: ['api'])
|
personal_access_token = create(:personal_access_token, scopes: ['api'])
|
||||||
|
|
||||||
expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: '')
|
expect_results_with_abilities(personal_access_token, full_authentication_abilities)
|
||||||
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, full_authentication_abilities))
|
end
|
||||||
|
|
||||||
|
it 'succeeds for personal access tokens with the `read_repository` scope' do
|
||||||
|
personal_access_token = create(:personal_access_token, scopes: ['read_repository'])
|
||||||
|
|
||||||
|
expect_results_with_abilities(personal_access_token, [:download_code])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'succeeds for personal access tokens with the `write_repository` scope' do
|
||||||
|
personal_access_token = create(:personal_access_token, scopes: ['write_repository'])
|
||||||
|
|
||||||
|
expect_results_with_abilities(personal_access_token, [:download_code, :push_code])
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when registry is enabled' do
|
context 'when registry is enabled' do
|
||||||
|
@ -194,28 +235,24 @@ describe Gitlab::Auth do
|
||||||
it 'succeeds for personal access tokens with the `read_registry` scope' do
|
it 'succeeds for personal access tokens with the `read_registry` scope' do
|
||||||
personal_access_token = create(:personal_access_token, scopes: ['read_registry'])
|
personal_access_token = create(:personal_access_token, scopes: ['read_registry'])
|
||||||
|
|
||||||
expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: '')
|
expect_results_with_abilities(personal_access_token, [:read_container_image])
|
||||||
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, [:read_container_image]))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'succeeds if it is an impersonation token' do
|
it 'succeeds if it is an impersonation token' do
|
||||||
impersonation_token = create(:personal_access_token, :impersonation, scopes: ['api'])
|
impersonation_token = create(:personal_access_token, :impersonation, scopes: ['api'])
|
||||||
|
|
||||||
expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: '')
|
expect_results_with_abilities(impersonation_token, full_authentication_abilities)
|
||||||
expect(gl_auth.find_for_git_client('', impersonation_token.token, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(impersonation_token.user, nil, :personal_access_token, full_authentication_abilities))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'limits abilities based on scope' do
|
it 'limits abilities based on scope' do
|
||||||
personal_access_token = create(:personal_access_token, scopes: %w[read_user sudo])
|
personal_access_token = create(:personal_access_token, scopes: %w[read_user sudo])
|
||||||
|
|
||||||
expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: '')
|
expect_results_with_abilities(personal_access_token, [])
|
||||||
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, []))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'fails if password is nil' do
|
it 'fails if password is nil' do
|
||||||
expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: '')
|
expect_results_with_abilities(nil, nil, false)
|
||||||
expect(gl_auth.find_for_git_client('', nil, project: nil, ip: 'ip')).to eq(Gitlab::Auth::Result.new(nil, nil))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -479,7 +516,7 @@ describe Gitlab::Auth do
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_authentication_abilities
|
def read_only_authentication_abilities
|
||||||
[
|
[
|
||||||
:read_project,
|
:read_project,
|
||||||
:download_code,
|
:download_code,
|
||||||
|
@ -488,7 +525,7 @@ describe Gitlab::Auth do
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_write_authentication_abilities
|
def read_write_authentication_abilities
|
||||||
read_authentication_abilities + [
|
read_only_authentication_abilities + [
|
||||||
:push_code,
|
:push_code,
|
||||||
:create_container_image
|
:create_container_image
|
||||||
]
|
]
|
||||||
|
@ -499,4 +536,10 @@ describe Gitlab::Auth do
|
||||||
:admin_container_image
|
:admin_container_image
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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'))
|
||||||
|
.to eq(Gitlab::Auth::Result.new(personal_access_token&.user, nil, personal_access_token.nil? ? nil : :personal_access_token, abilities))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -549,14 +549,14 @@ describe 'Git HTTP requests' do
|
||||||
it 'rejects pulls with personal access token error message' do
|
it 'rejects pulls with personal access token error message' do
|
||||||
download(path, user: user.username, password: user.password) do |response|
|
download(path, user: user.username, password: user.password) do |response|
|
||||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||||
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
|
expect(response.body).to include('You must use a personal access token with \'read_repository\' or \'write_repository\' scope for Git over HTTP')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects the push attempt with personal access token error message' do
|
it 'rejects the push attempt with personal access token error message' do
|
||||||
upload(path, user: user.username, password: user.password) do |response|
|
upload(path, user: user.username, password: user.password) do |response|
|
||||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||||
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
|
expect(response.body).to include('You must use a personal access token with \'read_repository\' or \'write_repository\' scope for Git over HTTP')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -566,6 +566,47 @@ describe 'Git HTTP requests' do
|
||||||
|
|
||||||
it_behaves_like 'pulls are allowed'
|
it_behaves_like 'pulls are allowed'
|
||||||
it_behaves_like 'pushes are allowed'
|
it_behaves_like 'pushes are allowed'
|
||||||
|
|
||||||
|
it 'rejects the push attempt for read_repository scope' do
|
||||||
|
read_access_token = create(:personal_access_token, user: user, scopes: [:read_repository])
|
||||||
|
|
||||||
|
upload(path, user: user.username, password: read_access_token.token) do |response|
|
||||||
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
|
expect(response.body).to include('You are not allowed to upload code')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts the push attempt for write_repository scope' do
|
||||||
|
write_access_token = create(:personal_access_token, user: user, scopes: [:write_repository])
|
||||||
|
|
||||||
|
upload(path, user: user.username, password: write_access_token.token) do |response|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts the pull attempt for read_repository scope' do
|
||||||
|
read_access_token = create(:personal_access_token, user: user, scopes: [:read_repository])
|
||||||
|
|
||||||
|
download(path, user: user.username, password: read_access_token.token) do |response|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts the pull attempt for api scope' do
|
||||||
|
read_access_token = create(:personal_access_token, user: user, scopes: [:api])
|
||||||
|
|
||||||
|
download(path, user: user.username, password: read_access_token.token) do |response|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'accepts the push attempt for api scope' do
|
||||||
|
write_access_token = create(:personal_access_token, user: user, scopes: [:api])
|
||||||
|
|
||||||
|
upload(path, user: user.username, password: write_access_token.token) do |response|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -577,14 +618,14 @@ describe 'Git HTTP requests' do
|
||||||
it 'rejects pulls with personal access token error message' do
|
it 'rejects pulls with personal access token error message' do
|
||||||
download(path, user: 'foo', password: 'bar') do |response|
|
download(path, user: 'foo', password: 'bar') do |response|
|
||||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||||
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
|
expect(response.body).to include('You must use a personal access token with \'read_repository\' or \'write_repository\' scope for Git over HTTP')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'rejects pushes with personal access token error message' do
|
it 'rejects pushes with personal access token error message' do
|
||||||
upload(path, user: 'foo', password: 'bar') do |response|
|
upload(path, user: 'foo', password: 'bar') do |response|
|
||||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||||
expect(response.body).to include('You must use a personal access token with \'api\' scope for Git over HTTP')
|
expect(response.body).to include('You must use a personal access token with \'read_repository\' or \'write_repository\' scope for Git over HTTP')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -598,7 +639,7 @@ describe 'Git HTTP requests' do
|
||||||
it 'does not display the personal access token error message' do
|
it 'does not display the personal access token error message' do
|
||||||
upload(path, user: 'foo', password: 'bar') do |response|
|
upload(path, user: 'foo', password: 'bar') do |response|
|
||||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||||
expect(response.body).not_to include('You must use a personal access token with \'api\' scope for Git over HTTP')
|
expect(response.body).not_to include('You must use a personal access token with \'read_repository\' or \'write_repository\' scope for Git over HTTP')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -142,7 +142,7 @@ describe JwtController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'allows read access' do
|
it 'allows read access' do
|
||||||
expect(service).to receive(:execute).with(authentication_abilities: Gitlab::Auth.read_authentication_abilities)
|
expect(service).to receive(:execute).with(authentication_abilities: Gitlab::Auth.read_only_authentication_abilities)
|
||||||
|
|
||||||
get '/jwt/auth', params: parameters
|
get '/jwt/auth', params: parameters
|
||||||
end
|
end
|
||||||
|
|
|
@ -187,7 +187,7 @@ describe 'OpenID Connect requests' do
|
||||||
expect(response).to have_gitlab_http_status(200)
|
expect(response).to have_gitlab_http_status(200)
|
||||||
expect(json_response['issuer']).to eq('http://localhost')
|
expect(json_response['issuer']).to eq('http://localhost')
|
||||||
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
|
expect(json_response['jwks_uri']).to eq('http://www.example.com/oauth/discovery/keys')
|
||||||
expect(json_response['scopes_supported']).to eq(%w[api read_user sudo read_repository openid profile email])
|
expect(json_response['scopes_supported']).to eq(%w[api read_user read_repository write_repository sudo openid profile email])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue