Commit 6381dc98 authored by Krasimir Angelov's avatar Krasimir Angelov

Implement authetication for Conan Packages API

Add new Conan API endpoint `/users/authenticate` that when valid
personal access tokens is provided (as password for HTTP Basic Auth)
will respond with the same access token in the response body.

For subsequent requests the token will be provided by the Conan client
as bearer in the HTTP_AUTHORIZATION header.

The downside of this approach is that the access token will be stored
locally by the Conan client in a SQLite database.
parent 01e37ab6
......@@ -3,20 +3,48 @@ module API
class ConanPackages < Grape::API
before do
not_found! unless Feature.enabled?(:conan_package_registry)
require_packages_enabled!
end
helpers ::API::Helpers::PackagesHelpers
before do
require_packages_enabled!
require_conan_authentication!
end
namespace 'packages/conan/v1/users/' do
format :txt
desc 'Authenticate user' do
detail 'This feature was introduced in GitLab 12.2'
end
get 'authenticate' do
encoded_credentials = headers['Authorization'].to_s.split('Basic ', 2).second
token = Base64.decode64(encoded_credentials || '').split(':', 2).second
request.env['HTTP_PRIVATE_TOKEN'] = token
desc 'Ping the Conan API' do
detail 'This feature was introduced in GitLab 12.2'
authenticate!
token
end
end
get 'packages/conan/v1/ping' do
nil
namespace 'packages/conan/v1/' do
before do
require_conan_authentication!
end
helpers do
def require_conan_authentication!
token = headers['Authorization'].to_s.split('Bearer ', 2).second
request.env['HTTP_PRIVATE_TOKEN'] = token
authenticate!
end
end
desc 'Ping the Conan API' do
detail 'This feature was introduced in GitLab 12.2'
end
get 'ping' do
header 'X-Conan-Server-Capabilities', [].join(',')
end
end
end
end
......@@ -23,12 +23,6 @@ module API
def authorize_destroy_package!
authorize!(:destroy_package, user_project)
end
def require_conan_authentication!
# TODO: implement Conan server authentication
# To be implemented in https://gitlab.com/gitlab-org/gitlab-ee/issues/12568
unauthorized!
end
end
end
end
......@@ -2,45 +2,72 @@
require 'spec_helper'
describe API::ConanPackages do
set(:guest) { create(:user) }
let(:api_user) { guest }
before do
stub_licensed_features(packages: true)
end
describe 'GET /api/v4/packages/conan/v1/ping' do
let(:url) { '/packages/conan/v1/ping' }
subject { get api(url, api_user) }
context 'feature flag disabled' do
before do
stub_feature_flags(conan_package_registry: false)
end
it 'returns not found' do
subject
it 'responds with 404 Not Found' do
get api('/packages/conan/v1/ping')
expect(response).to have_gitlab_http_status(404)
end
end
context 'feature flag enabled' do
it 'rejects with no authorization' do
subject
it 'responds with 401 Unauthorized when no token provided' do
get api('/packages/conan/v1/ping')
expect(response).to have_gitlab_http_status(401)
end
it 'responds with 200 OK when valid token is provided' do
personal_access_token = create(:personal_access_token)
headers = { 'HTTP_AUTHORIZATION' => "Bearer #{personal_access_token.token}" }
get api('/packages/conan/v1/ping'), headers: headers
expect(response).to have_gitlab_http_status(200)
expect(response.headers['X-Conan-Server-Capabilities']).to eq("")
end
it 'responds with 401 Unauthorized when invalid token is provided' do
headers = { 'HTTP_AUTHORIZATION' => "Bearer wrong-token" }
get api('/packages/conan/v1/ping'), headers: headers
expect(response).to have_gitlab_http_status(401)
end
context 'packages feature disabled' do
it 'fails' do
it 'responds with 404 Not Found' do
stub_packages_setting(enabled: false)
subject
get api('/packages/conan/v1/ping')
expect(response).to have_gitlab_http_status(404)
end
end
end
end
describe 'GET /api/v4/packages/conan/v1/users/authenticate' do
it 'responds with 401 Unauthorized when invalid token is provided' do
get api("/packages/conan/v1/users/authenticate")
expect(response).to have_gitlab_http_status(401)
end
it 'responds with 200 OK and the token when valid token is provided' do
personal_access_token = create(:personal_access_token)
headers = { 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials("foo", personal_access_token.token) }
get api("/packages/conan/v1/users/authenticate"), headers: headers
expect(response).to have_gitlab_http_status(200)
expect(response.body).to eq(personal_access_token.token)
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