From 44e7804ddb408d85f091c7a5cd36e0fdbec63d13 Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Mon, 20 Jun 2016 21:13:53 -0500
Subject: [PATCH 1/7] Allow GitLab Shell to check for allowed access based on
 the used Git protocol.

---
 hooks/pre-receive    | 5 ++++-
 lib/gitlab_access.rb | 7 ++++---
 lib/gitlab_net.rb    | 3 ++-
 lib/gitlab_shell.rb  | 2 +-
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/hooks/pre-receive b/hooks/pre-receive
index 1f8a9d5..6ed9a2c 100755
--- a/hooks/pre-receive
+++ b/hooks/pre-receive
@@ -5,12 +5,15 @@
 
 refs = $stdin.read
 key_id  = ENV['GL_ID']
+protocol = ENV['PROTOCOL']
 repo_path = Dir.pwd
 
 require_relative '../lib/gitlab_custom_hook'
 require_relative '../lib/gitlab_access'
 
-if GitlabAccess.new(repo_path, key_id, refs).exec &&
+protocol ||= 'http'
+
+if GitlabAccess.new(repo_path, key_id, refs, protocol).exec &&
     GitlabCustomHook.new.pre_receive(refs, repo_path)
   exit 0
 else
diff --git a/lib/gitlab_access.rb b/lib/gitlab_access.rb
index 10afeef..bab2c4c 100644
--- a/lib/gitlab_access.rb
+++ b/lib/gitlab_access.rb
@@ -9,18 +9,19 @@ class GitlabAccess
 
   include NamesHelper
 
-  attr_reader :config, :repo_path, :repo_name, :changes
+  attr_reader :config, :repo_path, :repo_name, :changes, :protocol
 
-  def initialize(repo_path, actor, changes)
+  def initialize(repo_path, actor, changes, protocol = nil)
     @config = GitlabConfig.new
     @repo_path = repo_path.strip
     @actor = actor
     @repo_name = extract_repo_name(@repo_path.dup)
     @changes = changes.lines
+    @protocol = protocol
   end
 
   def exec
-    status = api.check_access('git-receive-pack', @repo_name, @actor, @changes)
+    status = api.check_access('git-receive-pack', @repo_name, @actor, @changes, @protocol)
 
     raise AccessDeniedError, status.message unless status.allowed?
 
diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb
index dd9a4b0..24e97be 100644
--- a/lib/gitlab_net.rb
+++ b/lib/gitlab_net.rb
@@ -14,7 +14,7 @@ class GitlabNet
   CHECK_TIMEOUT = 5
   READ_TIMEOUT = 300
 
-  def check_access(cmd, repo, actor, changes)
+  def check_access(cmd, repo, actor, changes, protocol = nil)
     project_name = repo.gsub("'", "")
     project_name = project_name.gsub(/\.git\Z/, "")
     project_name = project_name.gsub(/\A\//, "")
@@ -24,6 +24,7 @@ class GitlabNet
       action: cmd,
       changes: changes,
       project: project_name,
+      protocol: protocol
     }
 
     if actor =~ /\Akey\-\d+\Z/
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index c5d5c02..2bb8a4d 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -85,7 +85,7 @@ class GitlabShell
   end
 
   def verify_access
-    status = api.check_access(@git_access, @repo_name, @key_id, '_any')
+    status = api.check_access(@git_access, @repo_name, @key_id, '_any', 'ssh')
 
     raise AccessDeniedError, status.message unless status.allowed?
 
-- 
GitLab


From 1c18095c9f2b80d380122c8c71f98a07387c1e66 Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Mon, 20 Jun 2016 21:14:44 -0500
Subject: [PATCH 2/7] Added CHANGELOG item

---
 CHANGELOG | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG b/CHANGELOG
index 58a9e39..a806079 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 v3.1.0
   - Refactor repository paths handling to allow multiple git mount points
+  - Allow GitLab Shell to check for allowed access based on the used Git protocol
 
 v3.0.1
   - Update PostReceive worker to provide enqueued_at time.
-- 
GitLab


From fd41b8a433164f36f7cf70b358115c5f56f06670 Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Mon, 20 Jun 2016 21:57:37 -0500
Subject: [PATCH 3/7] Simplify protocol assign, and populate ENV['PROTOCOL']
 variable when calling hooks via SSH

---
 hooks/pre-receive         | 4 +---
 lib/gitlab_shell.rb       | 3 ++-
 spec/gitlab_shell_spec.rb | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/hooks/pre-receive b/hooks/pre-receive
index 6ed9a2c..a7eeb30 100755
--- a/hooks/pre-receive
+++ b/hooks/pre-receive
@@ -5,14 +5,12 @@
 
 refs = $stdin.read
 key_id  = ENV['GL_ID']
-protocol = ENV['PROTOCOL']
+protocol = ENV['PROTOCOL'] || 'http'
 repo_path = Dir.pwd
 
 require_relative '../lib/gitlab_custom_hook'
 require_relative '../lib/gitlab_access'
 
-protocol ||= 'http'
-
 if GitlabAccess.new(repo_path, key_id, refs, protocol).exec &&
     GitlabCustomHook.new.pre_receive(refs, repo_path)
   exit 0
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index 2bb8a4d..3dc10b6 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -131,7 +131,8 @@ class GitlabShell
       'PATH' => ENV['PATH'],
       'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
       'LANG' => ENV['LANG'],
-      'GL_ID' => @key_id
+      'GL_ID' => @key_id,
+      'PROTOCOL' => 'ssh'
     }
 
     if @config.git_annex_enabled?
diff --git a/spec/gitlab_shell_spec.rb b/spec/gitlab_shell_spec.rb
index 79fa49b..0b0a817 100644
--- a/spec/gitlab_shell_spec.rb
+++ b/spec/gitlab_shell_spec.rb
@@ -242,7 +242,7 @@ describe GitlabShell do
       after { subject.exec(ssh_cmd) }
 
       it "should call api.check_access" do
-        api.should_receive(:check_access).with('git-upload-pack', 'gitlab-ci.git', key_id, '_any')
+        api.should_receive(:check_access).with('git-upload-pack', 'gitlab-ci.git', key_id, '_any', 'ssh')
       end
 
       it "should disallow access and log the attempt if check_access returns false status" do
-- 
GitLab


From 4cd4cf673844f8f381609f9c3264c33f2843935d Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Tue, 21 Jun 2016 21:10:09 -0500
Subject: [PATCH 4/7] Added better tests for the protocol check

---
 spec/gitlab_access_spec.rb                  |  3 +-
 spec/gitlab_net_spec.rb                     | 36 +++++++++++++++++
 spec/vcr_cassettes/http-access-disabled.yml | 44 +++++++++++++++++++++
 spec/vcr_cassettes/ssh-access-disabled.yml  | 44 +++++++++++++++++++++
 4 files changed, 126 insertions(+), 1 deletion(-)
 create mode 100644 spec/vcr_cassettes/http-access-disabled.yml
 create mode 100644 spec/vcr_cassettes/ssh-access-disabled.yml

diff --git a/spec/gitlab_access_spec.rb b/spec/gitlab_access_spec.rb
index 98848ae..2781aa9 100644
--- a/spec/gitlab_access_spec.rb
+++ b/spec/gitlab_access_spec.rb
@@ -11,7 +11,7 @@ describe GitlabAccess do
     end
   end
   subject do
-    GitlabAccess.new(repo_path, 'key-123', 'wow').tap do |access|
+    GitlabAccess.new(repo_path, 'key-123', 'wow', 'ssh').tap do |access|
       access.stub(exec_cmd: :exec_called)
       access.stub(api: api)
     end
@@ -25,6 +25,7 @@ describe GitlabAccess do
     it { subject.repo_name.should == repo_name }
     it { subject.repo_path.should == repo_path }
     it { subject.changes.should == ['wow'] }
+    it { subject.protocol.should == 'ssh' }
   end
 
   describe "#exec" do
diff --git a/spec/gitlab_net_spec.rb b/spec/gitlab_net_spec.rb
index 0643868..b236247 100644
--- a/spec/gitlab_net_spec.rb
+++ b/spec/gitlab_net_spec.rb
@@ -130,6 +130,42 @@ describe GitlabNet, vcr: true do
       end
     end
 
+    context 'ssh access has been disabled' do
+      it 'should deny pull access for dev.gitlab.org' do
+        VCR.use_cassette('ssh-access-disabled') do
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'ssh')
+          access.allowed?.should be_false
+          access.message.should eq 'Git access over SSH is not allowed'
+        end
+      end
+
+      it 'should deny pull access for dev.gitlab.org' do
+        VCR.use_cassette('ssh-access-disabled') do
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'ssh')
+          access.allowed?.should be_false
+          access.message.should eq 'Git access over SSH is not allowed'
+        end
+      end
+    end
+
+    context 'http access has been disabled' do
+      it 'should deny pull access for dev.gitlab.org' do
+        VCR.use_cassette('http-access-disabled') do
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'http')
+          access.allowed?.should be_false
+          access.message.should eq 'Git access over HTTP is not allowed'
+        end
+      end
+
+      it 'should deny pull access for dev.gitlab.org' do
+        VCR.use_cassette('http-access-disabled') do
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'http')
+          access.allowed?.should be_false
+          access.message.should eq 'Git access over HTTP is not allowed'
+        end
+      end
+    end
+
     context 'ssh key without access to project' do
       it 'should deny pull access for dev.gitlab.org' do
         VCR.use_cassette("denied-pull") do
diff --git a/spec/vcr_cassettes/http-access-disabled.yml b/spec/vcr_cassettes/http-access-disabled.yml
new file mode 100644
index 0000000..36e27a9
--- /dev/null
+++ b/spec/vcr_cassettes/http-access-disabled.yml
@@ -0,0 +1,44 @@
+---
+http_interactions:
+- request:
+    method: post
+    uri: https://dev.gitlab.org/api/v3/internal/allowed
+    body:
+      encoding: US-ASCII
+      string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&project=gitlab%2Fgitlabhq&protocol=http&key_id=2&secret_token=a123
+    headers:
+      Accept-Encoding:
+      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+      Accept:
+      - "*/*"
+      User-Agent:
+      - Ruby
+      Content-Type:
+      - application/x-www-form-urlencoded
+  response:
+    status:
+      code: 200
+      message: OK
+    headers:
+      Cache-Control:
+      - no-cache
+      Content-Length:
+      - '30'
+      Content-Type:
+      - application/json
+      Date:
+      - Wed, 22 Jun 2016 01:03:41 GMT
+      Status:
+      - 200 OK
+      Vary:
+      - Origin
+      X-Request-Id:
+      - 55b7af2c-3559-41d2-b301-9b86ad1d8fac
+      X-Runtime:
+      - '2.280895'
+    body:
+      encoding: UTF-8
+      string: '{"status": false, "message":"Git access over HTTP is not allowed"}'
+    http_version: 
+  recorded_at: Wed, 22 Jun 2016 01:03:41 GMT
+recorded_with: VCR 2.4.0
\ No newline at end of file
diff --git a/spec/vcr_cassettes/ssh-access-disabled.yml b/spec/vcr_cassettes/ssh-access-disabled.yml
new file mode 100644
index 0000000..656d0aa
--- /dev/null
+++ b/spec/vcr_cassettes/ssh-access-disabled.yml
@@ -0,0 +1,44 @@
+---
+http_interactions:
+- request:
+    method: post
+    uri: https://dev.gitlab.org/api/v3/internal/allowed
+    body:
+      encoding: US-ASCII
+      string: action=git-receive-pack&changes=0000000000000000000000000000000000000000+92d0970eefd7acb6d548878925ce2208cfe2d2ec+refs%2Fheads%2Fbranch4&project=gitlab%2Fgitlabhq&protocol=ssh&key_id=2&secret_token=a123
+    headers:
+      Accept-Encoding:
+      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+      Accept:
+      - "*/*"
+      User-Agent:
+      - Ruby
+      Content-Type:
+      - application/x-www-form-urlencoded
+  response:
+    status:
+      code: 200
+      message: OK
+    headers:
+      Cache-Control:
+      - no-cache
+      Content-Length:
+      - '30'
+      Content-Type:
+      - application/json
+      Date:
+      - Wed, 22 Jun 2016 01:01:41 GMT
+      Status:
+      - 200 OK
+      Vary:
+      - Origin
+      X-Request-Id:
+      - 55b7af2c-3559-41d2-b301-9b86ad1d8fac
+      X-Runtime:
+      - '2.280895'
+    body:
+      encoding: UTF-8
+      string: '{"status": false, "message":"Git access over SSH is not allowed"}'
+    http_version:
+  recorded_at: Wed, 22 Jun 2016 01:01:41 GMT
+recorded_with: VCR 2.4.0
-- 
GitLab


From 6aa601866c66a62b4ab3db3fa55ab1b5e84e444d Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Wed, 22 Jun 2016 12:54:27 -0500
Subject: [PATCH 5/7] Rename ENV['PROTOCOL'] to ENV['GL_PROTOCOL'] and make it
 mandatory with no fallback value

---
 hooks/pre-receive       |  2 +-
 lib/gitlab_access.rb    |  2 +-
 lib/gitlab_net.rb       |  2 +-
 lib/gitlab_shell.rb     |  2 +-
 spec/gitlab_net_spec.rb | 14 +++++++-------
 5 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hooks/pre-receive b/hooks/pre-receive
index a7eeb30..a4b2e32 100755
--- a/hooks/pre-receive
+++ b/hooks/pre-receive
@@ -5,7 +5,7 @@
 
 refs = $stdin.read
 key_id  = ENV['GL_ID']
-protocol = ENV['PROTOCOL'] || 'http'
+protocol = ENV['GL_PROTOCOL']
 repo_path = Dir.pwd
 
 require_relative '../lib/gitlab_custom_hook'
diff --git a/lib/gitlab_access.rb b/lib/gitlab_access.rb
index bab2c4c..04806b2 100644
--- a/lib/gitlab_access.rb
+++ b/lib/gitlab_access.rb
@@ -11,7 +11,7 @@ class GitlabAccess
 
   attr_reader :config, :repo_path, :repo_name, :changes, :protocol
 
-  def initialize(repo_path, actor, changes, protocol = nil)
+  def initialize(repo_path, actor, changes, protocol)
     @config = GitlabConfig.new
     @repo_path = repo_path.strip
     @actor = actor
diff --git a/lib/gitlab_net.rb b/lib/gitlab_net.rb
index 24e97be..e10a07a 100644
--- a/lib/gitlab_net.rb
+++ b/lib/gitlab_net.rb
@@ -14,7 +14,7 @@ class GitlabNet
   CHECK_TIMEOUT = 5
   READ_TIMEOUT = 300
 
-  def check_access(cmd, repo, actor, changes, protocol = nil)
+  def check_access(cmd, repo, actor, changes, protocol)
     project_name = repo.gsub("'", "")
     project_name = project_name.gsub(/\.git\Z/, "")
     project_name = project_name.gsub(/\A\//, "")
diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index 3dc10b6..1e94369 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -132,7 +132,7 @@ class GitlabShell
       'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
       'LANG' => ENV['LANG'],
       'GL_ID' => @key_id,
-      'PROTOCOL' => 'ssh'
+      'GL_PROTOCOL' => 'ssh'
     }
 
     if @config.git_annex_enabled?
diff --git a/spec/gitlab_net_spec.rb b/spec/gitlab_net_spec.rb
index b236247..2bbf98b 100644
--- a/spec/gitlab_net_spec.rb
+++ b/spec/gitlab_net_spec.rb
@@ -110,7 +110,7 @@ describe GitlabNet, vcr: true do
     context 'ssh key with access to project' do
       it 'should allow pull access for dev.gitlab.org' do
         VCR.use_cassette("allowed-pull") do
-          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes)
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes, 'ssh')
           access.allowed?.should be_true
         end
       end
@@ -118,13 +118,13 @@ describe GitlabNet, vcr: true do
       it 'adds the secret_token to the request' do
         VCR.use_cassette("allowed-pull") do
           Net::HTTP::Post.any_instance.should_receive(:set_form_data).with(hash_including(secret_token: 'a123'))
-          gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes)
+          gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-126', changes, 'ssh')
         end
       end
 
       it 'should allow push access for dev.gitlab.org' do
         VCR.use_cassette("allowed-push") do
-          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'key-126', changes)
+          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'key-126', changes, 'ssh')
           access.allowed?.should be_true
         end
       end
@@ -169,21 +169,21 @@ describe GitlabNet, vcr: true do
     context 'ssh key without access to project' do
       it 'should deny pull access for dev.gitlab.org' do
         VCR.use_cassette("denied-pull") do
-          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes)
+          access = gitlab_net.check_access('git-receive-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'ssh')
           access.allowed?.should be_false
         end
       end
 
       it 'should deny push access for dev.gitlab.org' do
         VCR.use_cassette("denied-push") do
-          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'key-2', changes)
+          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'key-2', changes, 'ssh')
           access.allowed?.should be_false
         end
       end
 
       it 'should deny push access for dev.gitlab.org (with user)' do
         VCR.use_cassette("denied-push-with-user") do
-          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'user-1', changes)
+          access = gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'user-1', changes, 'ssh')
           access.allowed?.should be_false
         end
       end
@@ -192,7 +192,7 @@ describe GitlabNet, vcr: true do
     it "raises an exception if the connection fails" do
       Net::HTTP.any_instance.stub(:request).and_raise(StandardError)
       expect {
-        gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'user-1', changes)
+        gitlab_net.check_access('git-upload-pack', 'gitlab/gitlabhq.git', 'user-1', changes, 'ssh')
       }.to raise_error(GitlabNet::ApiUnreachableError)
     end
   end
-- 
GitLab


From 52c3150ed3340c59faf88fd191af0f92fc318fc5 Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Thu, 23 Jun 2016 09:34:39 -0500
Subject: [PATCH 6/7] Make use of a constant for the used SSH protocol

---
 lib/gitlab_shell.rb | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/gitlab_shell.rb b/lib/gitlab_shell.rb
index 1e94369..d9812ce 100644
--- a/lib/gitlab_shell.rb
+++ b/lib/gitlab_shell.rb
@@ -8,6 +8,7 @@ class GitlabShell
   class InvalidRepositoryPathError < StandardError; end
 
   GIT_COMMANDS = %w(git-upload-pack git-receive-pack git-upload-archive git-annex-shell git-lfs-authenticate).freeze
+  GL_PROTOCOL = 'ssh'.freeze
 
   attr_accessor :key_id, :repo_name, :git_cmd
   attr_reader :repo_path
@@ -85,7 +86,7 @@ class GitlabShell
   end
 
   def verify_access
-    status = api.check_access(@git_access, @repo_name, @key_id, '_any', 'ssh')
+    status = api.check_access(@git_access, @repo_name, @key_id, '_any', GL_PROTOCOL)
 
     raise AccessDeniedError, status.message unless status.allowed?
 
@@ -132,7 +133,7 @@ class GitlabShell
       'LD_LIBRARY_PATH' => ENV['LD_LIBRARY_PATH'],
       'LANG' => ENV['LANG'],
       'GL_ID' => @key_id,
-      'GL_PROTOCOL' => 'ssh'
+      'GL_PROTOCOL' => GL_PROTOCOL
     }
 
     if @config.git_annex_enabled?
-- 
GitLab


From 02b8071c60f26318d660864450ca869cc8e6b7cf Mon Sep 17 00:00:00 2001
From: Patricio Cano <suprnova32@gmail.com>
Date: Tue, 5 Jul 2016 18:16:53 -0500
Subject: [PATCH 7/7] Bump VERSION to 3.2.0

---
 CHANGELOG | 4 +++-
 VERSION   | 2 +-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index a806079..31cda72 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,8 @@
+v3.2.0
+  - Allow GitLab Shell to check for allowed access based on the used Git protocol
+
 v3.1.0
   - Refactor repository paths handling to allow multiple git mount points
-  - Allow GitLab Shell to check for allowed access based on the used Git protocol
 
 v3.0.1
   - Update PostReceive worker to provide enqueued_at time.
diff --git a/VERSION b/VERSION
index fd2a018..944880f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.1.0
+3.2.0
-- 
GitLab