2016-05-14 12:11:48 -04:00
|
|
|
module Auth
|
|
|
|
class ContainerRegistryAuthenticationService < BaseService
|
2016-05-31 07:48:05 -04:00
|
|
|
include Gitlab::CurrentSettings
|
2016-05-30 11:12:50 -04:00
|
|
|
|
2016-05-14 12:15:19 -04:00
|
|
|
AUDIENCE = 'container_registry'
|
|
|
|
|
2016-05-14 12:11:48 -04:00
|
|
|
def execute
|
2016-05-14 12:15:19 -04:00
|
|
|
return error('not found', 404) unless registry.enabled
|
|
|
|
|
2016-05-30 10:57:39 -04:00
|
|
|
unless current_user || project
|
2016-05-15 11:46:54 -04:00
|
|
|
return error('forbidden', 403) unless scope
|
2016-05-14 12:11:48 -04:00
|
|
|
end
|
|
|
|
|
2016-05-14 19:23:31 -04:00
|
|
|
{ token: authorized_token(scope).encoded }
|
2016-05-14 12:11:48 -04:00
|
|
|
end
|
|
|
|
|
2016-05-14 12:15:19 -04:00
|
|
|
def self.full_access_token(*names)
|
|
|
|
registry = Gitlab.config.registry
|
2016-05-15 09:47:48 -04:00
|
|
|
token = JSONWebToken::RSAToken.new(registry.key)
|
2016-05-14 12:15:19 -04:00
|
|
|
token.issuer = registry.issuer
|
|
|
|
token.audience = AUDIENCE
|
2016-05-31 07:48:05 -04:00
|
|
|
token.expire_time = token_expire_at
|
2016-07-06 09:26:59 -04:00
|
|
|
|
2016-05-14 12:15:19 -04:00
|
|
|
token[:access] = names.map do |name|
|
2016-05-20 19:43:11 -04:00
|
|
|
{ type: 'repository', name: name, actions: %w(*) }
|
2016-05-14 12:15:19 -04:00
|
|
|
end
|
2016-07-19 08:17:47 -04:00
|
|
|
|
2016-05-14 12:15:19 -04:00
|
|
|
token.encoded
|
|
|
|
end
|
|
|
|
|
2016-07-19 08:17:47 -04:00
|
|
|
def self.token_expire_at
|
|
|
|
Time.now + current_application_settings.container_registry_token_expire_delay.minutes
|
|
|
|
end
|
|
|
|
|
2016-05-14 12:11:48 -04:00
|
|
|
private
|
|
|
|
|
2016-05-14 19:23:31 -04:00
|
|
|
def authorized_token(*accesses)
|
|
|
|
token = JSONWebToken::RSAToken.new(registry.key)
|
2016-05-14 12:11:48 -04:00
|
|
|
token.issuer = registry.issuer
|
|
|
|
token.audience = params[:service]
|
|
|
|
token.subject = current_user.try(:username)
|
2016-07-19 08:17:47 -04:00
|
|
|
token.expire_time = self.class.token_expire_at
|
2016-05-15 09:52:26 -04:00
|
|
|
token[:access] = accesses.compact
|
2016-05-14 12:11:48 -04:00
|
|
|
token
|
|
|
|
end
|
|
|
|
|
2016-05-14 19:23:31 -04:00
|
|
|
def scope
|
2016-05-14 12:11:48 -04:00
|
|
|
return unless params[:scope]
|
|
|
|
|
2016-05-14 19:23:31 -04:00
|
|
|
@scope ||= process_scope(params[:scope])
|
2016-05-14 12:11:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def process_scope(scope)
|
|
|
|
type, name, actions = scope.split(':', 3)
|
|
|
|
actions = actions.split(',')
|
2016-05-14 19:23:31 -04:00
|
|
|
return unless type == 'repository'
|
2016-05-14 12:11:48 -04:00
|
|
|
|
2016-05-14 19:23:31 -04:00
|
|
|
process_repository_access(type, name, actions)
|
2016-05-14 12:11:48 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def process_repository_access(type, name, actions)
|
|
|
|
requested_project = Project.find_with_namespace(name)
|
|
|
|
return unless requested_project
|
|
|
|
|
|
|
|
actions = actions.select do |action|
|
|
|
|
can_access?(requested_project, action)
|
|
|
|
end
|
|
|
|
|
|
|
|
{ type: type, name: name, actions: actions } if actions.present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def can_access?(requested_project, requested_action)
|
2016-05-14 15:22:45 -04:00
|
|
|
return false unless requested_project.container_registry_enabled?
|
|
|
|
|
2016-05-14 12:11:48 -04:00
|
|
|
case requested_action
|
|
|
|
when 'pull'
|
2016-05-14 19:23:31 -04:00
|
|
|
requested_project == project || can?(current_user, :read_container_image, requested_project)
|
2016-05-14 12:11:48 -04:00
|
|
|
when 'push'
|
2016-05-14 19:23:31 -04:00
|
|
|
requested_project == project || can?(current_user, :create_container_image, requested_project)
|
2016-05-14 12:11:48 -04:00
|
|
|
else
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def registry
|
|
|
|
Gitlab.config.registry
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|