Commit 96c08aedad9004d39d1bd7978a28d71f50a734a3

Authored by Heitor
1 parent bd6b0bc9

Verify GitLab headers on push webhook

Gitlab sends the 'X-Gitlab-Event' header for all the webhook requests.
Verify it so we reduce the chance that robots call the hooks
accidentally.

Signed off by: Daniel Miranda <danielkza2@gmail.com>
app/controllers/repositories_controller.rb
@@ -97,13 +97,17 @@ class RepositoriesController &lt; ApplicationController @@ -97,13 +97,17 @@ class RepositoriesController &lt; ApplicationController
97 end 97 end
98 98
99 def notify_push 99 def notify_push
  100 + gitlab_event = request.headers['X-Gitlab-Event']
  101 + if gitlab_event.nil? || !gitlab_event.end_with?('Push Hook')
  102 + return render nothing: true, status: :unprocessable_entity
  103 + end
100 set_repository 104 set_repository
101 - @repository.cancel_processing_of_repository if @repository.last_processing_state.end_with? 'ING' 105 + @repository.cancel_processing_of_repository unless %w(READY, ERROR).include? @repository.last_processing_state
102 @repository.process 106 @repository.process
103 - render :nothing => true, :status => :ok 107 + render nothing: true, status: :ok
104 end 108 end
105 109
106 -private 110 + private
107 def set_project_id_repository_types_and_configurations 111 def set_project_id_repository_types_and_configurations
108 @project_id = params[:project_id] 112 @project_id = params[:project_id]
109 @repository_types = Repository.repository_types 113 @repository_types = Repository.repository_types
spec/controllers/repositories_controller_spec.rb
@@ -475,9 +475,14 @@ describe RepositoriesController, :type =&gt; :controller do @@ -475,9 +475,14 @@ describe RepositoriesController, :type =&gt; :controller do
475 end 475 end
476 476
477 describe 'notify_push' do 477 describe 'notify_push' do
478 - context 'with a valid repository' do  
479 - let(:repository) { FactoryGirl.build(:repository) } 478 + let(:repository) { FactoryGirl.build(:repository) }
480 479
  480 + def post_push
  481 + @request.env['HTTP_X_GITLAB_EVENT'] = ['Push Hook', 'Tag Push Hook'].sample
  482 + post :notify_push, id: repository.id
  483 + end
  484 +
  485 + context 'with a valid repository' do
481 before :each do 486 before :each do
482 Repository.expects(:find).with(repository.id).returns(repository) 487 Repository.expects(:find).with(repository.id).returns(repository)
483 end 488 end
@@ -487,7 +492,7 @@ describe RepositoriesController, :type =&gt; :controller do @@ -487,7 +492,7 @@ describe RepositoriesController, :type =&gt; :controller do
487 repository.expects(:last_processing_state).returns('INTERPRETING') 492 repository.expects(:last_processing_state).returns('INTERPRETING')
488 repository.expects(:cancel_processing_of_repository).once 493 repository.expects(:cancel_processing_of_repository).once
489 repository.expects(:process).once 494 repository.expects(:process).once
490 - post :notify_push, id: repository.id 495 + post_push
491 end 496 end
492 497
493 it { is_expected.to respond_with(:ok) } 498 it { is_expected.to respond_with(:ok) }
@@ -497,7 +502,7 @@ describe RepositoriesController, :type =&gt; :controller do @@ -497,7 +502,7 @@ describe RepositoriesController, :type =&gt; :controller do
497 before do 502 before do
498 repository.expects(:last_processing_state).returns('ERROR') 503 repository.expects(:last_processing_state).returns('ERROR')
499 repository.expects(:process).once 504 repository.expects(:process).once
500 - post :notify_push, id: repository.id 505 + post_push
501 end 506 end
502 507
503 it { is_expected.to respond_with(:ok) } 508 it { is_expected.to respond_with(:ok) }
@@ -507,7 +512,7 @@ describe RepositoriesController, :type =&gt; :controller do @@ -507,7 +512,7 @@ describe RepositoriesController, :type =&gt; :controller do
507 before do 512 before do
508 repository.expects(:last_processing_state).returns('READY') 513 repository.expects(:last_processing_state).returns('READY')
509 repository.expects(:process).once 514 repository.expects(:process).once
510 - post :notify_push, id: repository.id 515 + post_push
511 end 516 end
512 517
513 it { is_expected.to respond_with(:ok) } 518 it { is_expected.to respond_with(:ok) }
@@ -515,14 +520,20 @@ describe RepositoriesController, :type =&gt; :controller do @@ -515,14 +520,20 @@ describe RepositoriesController, :type =&gt; :controller do
515 end 520 end
516 521
517 context 'with an invalid repository' do 522 context 'with an invalid repository' do
518 - let(:repository_id) { 1 }  
519 -  
520 before :each do 523 before :each do
521 - Repository.expects(:find).with(repository_id).raises(KalibroClient::Errors::RecordNotFound)  
522 - post :notify_push, id: repository_id 524 + Repository.expects(:find).with(repository.id).raises(KalibroClient::Errors::RecordNotFound)
  525 + post_push
523 end 526 end
524 527
525 it { is_expected.to respond_with(:not_found) } 528 it { is_expected.to respond_with(:not_found) }
526 end 529 end
  530 +
  531 + context 'with an invalid header' do
  532 + before :each do
  533 + post :notify_push, id: repository.id
  534 + end
  535 +
  536 + it { is_expected.to respond_with(:unprocessable_entity) }
  537 + end
527 end 538 end
528 end 539 end