Commit 90466e70 authored by Fabio Pitino's avatar Fabio Pitino

Cancel all running CI jobs when user is blocked

This prevents a MITM attack where attacker could
still access Git repository if any jobs were
running long enough.
parent 7099ecf7
......@@ -267,6 +267,16 @@ class User < ApplicationRecord
BLOCKED_MESSAGE
end
end
# rubocop: disable CodeReuse/ServiceClass
# Ideally we should not call a service object here but user.block
# is also bcalled by Users::MigrateToGhostUserService which references
# this state transition object in order to do a rollback.
# For this reason the tradeoff is to disable this cop.
after_transition any => :blocked do |user|
Ci::CancelUserPipelinesService.new.execute(user)
end
# rubocop: enable CodeReuse/ServiceClass
end
# Scopes
......
# frozen_string_literal: true
module Ci
class CancelUserPipelinesService
# rubocop: disable CodeReuse/ActiveRecord
# This is a bug with CodeReuse/ActiveRecord cop
# https://gitlab.com/gitlab-org/gitlab/issues/32332
def execute(user)
user.pipelines.cancelable.find_each(&:cancel_running)
end
# rubocop: enable CodeReuse/ActiveRecord
end
end
---
title: Cancel all running CI jobs triggered by the user who is just blocked
merge_request:
author:
type: security
......@@ -1097,11 +1097,27 @@ describe User do
describe 'blocking user' do
let(:user) { create(:user, name: 'John Smith') }
it "blocks user" do
it 'blocks user' do
user.block
expect(user.blocked?).to be_truthy
end
context 'when user has running CI pipelines' do
let(:service) { double }
before do
pipeline = create(:ci_pipeline, :running, user: user)
create(:ci_build, :running, pipeline: pipeline)
end
it 'cancels all running pipelines and related jobs' do
expect(Ci::CancelUserPipelinesService).to receive(:new).and_return(service)
expect(service).to receive(:execute).with(user)
user.block
end
end
end
describe '.filter_items' do
......
# frozen_string_literal: true
require 'spec_helper'
describe Ci::CancelUserPipelinesService do
describe '#execute' do
let(:user) { create(:user) }
subject { described_class.new.execute(user) }
context 'when user has running CI pipelines' do
let(:pipeline) { create(:ci_pipeline, :running, user: user) }
let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
it 'cancels all running pipelines and related jobs' do
subject
expect(pipeline.reload).to be_canceled
expect(build.reload).to be_canceled
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment