From aaa6d80870d5215390a7cd919d91309e5a8795b7 Mon Sep 17 00:00:00 2001
From: Mayra Cabrera <mcabrera@gitlab.com>
Date: Sat, 31 Mar 2018 16:45:02 -0600
Subject: [PATCH] Implement read_registry for DeployTokens

---
 app/controllers/jwt_controller.rb | 13 +++++++++--
 spec/lib/gitlab/auth_spec.rb      | 37 ++++++++++++++++++++++++-------
 2 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb
index 7d6fe6a0232..76e7473e92c 100644
--- a/app/controllers/jwt_controller.rb
+++ b/app/controllers/jwt_controller.rb
@@ -23,10 +23,11 @@ class JwtController < ApplicationController
     @authentication_result = Gitlab::Auth::Result.new(nil, nil, :none, Gitlab::Auth.read_authentication_abilities)
 
     authenticate_with_http_basic do |login, password|
-      @authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: nil, ip: request.ip)
+      project = find_project_related(password)
+      @authentication_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
 
       if @authentication_result.failed? ||
-          (@authentication_result.actor.present? && !@authentication_result.actor.is_a?(User))
+          (@authentication_result.actor.present? && !user_or_deploy_token)
         render_unauthorized
       end
     end
@@ -57,4 +58,12 @@ class JwtController < ApplicationController
   def auth_params
     params.permit(:service, :scope, :account, :client_id)
   end
+
+  def find_project_related(password)
+    DeployToken.active.find_by(token: password)&.project
+  end
+
+  def user_or_deploy_token
+    @authentication_result.actor.is_a?(User) || @authentication_result.actor.is_a?(DeployToken)
+  end
 end
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 685a0bb54be..758fb17cd81 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -270,14 +270,6 @@ describe Gitlab::Auth do
           .to eq(auth_success)
       end
 
-      it 'fails if deploy token does not have read_repo as scope' do
-        deploy_token = create(:deploy_token, :read_registry, project: project)
-
-        expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: '')
-        expect(gl_auth.find_for_git_client('', deploy_token.token, project: project, ip: 'ip'))
-          .to eq(auth_failure)
-      end
-
       it 'fails if token is nil' do
         expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: '')
         expect(gl_auth.find_for_git_client('', nil, project: project, ip: 'ip'))
@@ -305,6 +297,35 @@ describe Gitlab::Auth do
         expect(gl_auth.find_for_git_client('deploy-token', deploy_token.token, project: project, ip: 'ip'))
           .to eq(auth_failure)
       end
+
+      context 'when registry enabled' do
+        before do
+          stub_container_registry_config(enabled: true)
+        end
+
+        it 'succeeds if deploy token does have read_registry as scope' do
+          deploy_token = create(:deploy_token, :read_registry, project: project)
+          auth_success = Gitlab::Auth::Result.new(deploy_token, project, :deploy_token, [:read_container_image])
+
+          expect(gl_auth).to receive(:rate_limit!).with('ip', success: true, login: '')
+          expect(gl_auth.find_for_git_client('', deploy_token.token, project: project, ip: 'ip'))
+            .to eq(auth_success)
+        end
+      end
+
+      context 'when registry disabled' do
+        before do
+          stub_container_registry_config(enabled: false)
+        end
+
+        it 'fails if deploy token have read_registry as scope' do
+          deploy_token = create(:deploy_token, :read_registry, project: project)
+
+          expect(gl_auth).to receive(:rate_limit!).with('ip', success: false, login: '')
+          expect(gl_auth.find_for_git_client('', deploy_token.token, project: project, ip: 'ip'))
+            .to eq(auth_failure)
+        end
+      end
     end
   end
 
-- 
2.30.9