container_registry_authentication_service.rb 1.9 KB
Newer Older
1 2
module Auth
  class ContainerRegistryAuthenticationService < BaseService
K
Kamil Trzcinski 已提交
3 4
    AUDIENCE = 'container_registry'

5
    def execute
K
Kamil Trzcinski 已提交
6 7
      return error('not found', 404) unless registry.enabled

8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
      if params[:offline_token]
        return error('forbidden', 403) unless current_user
      end

      return error('forbidden', 401) if scopes.blank?

      { token: authorized_token(scopes).encoded }
    end

    private

    def authorized_token(access)
      token = ::JWT::RSAToken.new(registry.key)
      token.issuer = registry.issuer
      token.audience = params[:service]
      token.subject = current_user.try(:username)
      token[:access] = access
      token
    end

    def scopes
      return unless params[:scope]

      @scopes ||= begin
        scope = process_scope(params[:scope])
        [scope].compact
      end
    end

    def process_scope(scope)
      type, name, actions = scope.split(':', 3)
      actions = actions.split(',')

      case type
      when 'repository'
        process_repository_access(type, name, actions)
      end
    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)
K
Kamil Trzcinski 已提交
59 60
      return false unless requested_project.container_registry_enabled?

61 62
      case requested_action
      when 'pull'
K
Kamil Trzcinski 已提交
63
        requested_project == project || can?(current_user, :read_container_registry, requested_project)
64 65 66 67 68 69 70 71 72 73 74 75
      when 'push'
        requested_project == project || can?(current_user, :create_container_registry, requested_project)
      else
        false
      end
    end

    def registry
      Gitlab.config.registry
    end
  end
end