Commit c2be21a6 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'fix-multiple-scopes' into 'master'

Support multiple scopes when authing container registry scopes

Closes #48968

See merge request gitlab-org/gitlab-ce!20617
parents 79405774 34ec29b9
......@@ -54,6 +54,22 @@ class JwtController < ApplicationController
end
def auth_params
params.permit(:service, :scope, :account, :client_id)
params.permit(:service, :account, :client_id)
.merge(additional_params)
end
def additional_params
{ scopes: scopes_param }.compact
end
# We have to parse scope here, because Docker Client does not send an array of scopes,
# but rather a flat list and we loose second scope when being processed by Rails:
# scope=scopeA&scope=scopeB
#
# This method makes to always return an array of scopes
def scopes_param
return unless params[:scope].present?
Array(Rack::Utils.parse_query(request.query_string)['scope'])
end
end
......@@ -9,11 +9,11 @@ module Auth
return error('UNAVAILABLE', status: 404, message: 'registry not enabled') unless registry.enabled
unless scope || current_user || project
unless scopes.any? || current_user || project
return error('DENIED', status: 403, message: 'access forbidden')
end
{ token: authorized_token(scope).encoded }
{ token: authorized_token(*scopes).encoded }
end
def self.full_access_token(*names)
......@@ -47,10 +47,12 @@ module Auth
end
end
def scope
return unless params[:scope]
def scopes
return [] unless params[:scopes]
@scope ||= process_scope(params[:scope])
@scopes ||= params[:scopes].map do |scope|
process_scope(scope)
end.compact
end
def process_scope(scope)
......
---
title: Support multiple scopes when authing container registry scopes
merge_request: 20617
author:
type: fixed
......@@ -70,6 +70,25 @@ describe JwtController do
it { expect(service_class).to have_received(:new).with(nil, user, parameters) }
context 'when passing a flat array of scopes' do
# We use this trick to make rails to generate a query_string:
# scope=scope1&scope=scope2
# It works because :scope and 'scope' are the same as string, but different objects
let(:parameters) do
{
:service => service_name,
:scope => 'scope1',
'scope' => 'scope2'
}
end
let(:service_parameters) do
{ service: service_name, scopes: %w(scope1 scope2) }
end
it { expect(service_class).to have_received(:new).with(nil, user, service_parameters) }
end
context 'when user has 2FA enabled' do
let(:user) { create(:user, :two_factor) }
......
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