Skip to content
Snippets Groups Projects
Commit ff343fa0 authored by Sean McGivern's avatar Sean McGivern :red_circle: Committed by Mike Greiling
Browse files

Merge branch 'fix/mirror-user' into 'security-9-3-ee'

Fix mirroring and CI exploit

See merge request !518
parent b56c3c6a
No related branches found
No related tags found
1 merge request!2536Resolve "Trial and license purchases inside GitLab EE"
Showing with 88 additions and 18 deletions
module SafeMirrorParams
extend ActiveSupport::Concern
included do
helper_method :default_mirror_users
end
private
def valid_mirror_user?(mirror_params)
return true unless mirror_params[:mirror_user_id].present?
default_mirror_users.map(&:id).include?(mirror_params[:mirror_user_id].to_i)
end
def default_mirror_users
[current_user, @project.mirror_user].compact.uniq
end
end
class Projects::ImportsController < Projects::ApplicationController
include ContinueParams
include SafeMirrorParams
# Authorize
before_action :authorize_admin_project!
......@@ -11,7 +12,7 @@ def new
end
def create
if @project.update_attributes(import_params)
if @project.update_attributes(safe_import_params)
@project.reload.import_schedule
end
......@@ -67,4 +68,10 @@ def redirect_if_no_import
def import_params
params.require(:project).permit(:import_url, :mirror, :mirror_user_id)
end
def safe_import_params
return import_params if valid_mirror_user?(import_params)
import_params.merge(mirror_user_id: current_user.id)
end
end
class Projects::MirrorsController < Projects::ApplicationController
include RepositorySettingsRedirect
include SafeMirrorParams
# Authorize
before_action :authorize_admin_project!, except: [:update_now]
before_action :authorize_push_code!, only: [:update_now]
......@@ -12,7 +13,7 @@ def show
end
def update
if @project.update_attributes(mirror_params)
if @project.update_attributes(safe_mirror_params)
if @project.mirror?
@project.force_import_job!
......@@ -51,4 +52,10 @@ def mirror_params
params.require(:project).permit(:mirror, :import_url, :mirror_user_id,
:mirror_trigger_builds, remote_mirrors_attributes: [:url, :id, :enabled])
end
def safe_mirror_params
return mirror_params if valid_mirror_user?(mirror_params)
mirror_params.merge(mirror_user_id: current_user.id)
end
end
module Projects
module Settings
class RepositoryController < Projects::ApplicationController
include SafeMirrorParams
before_action :authorize_admin_project!
prepend ::EE::Projects::Settings::RepositoryController
......
......@@ -4,4 +4,8 @@ def branch_diverged_tooltip_message
message << "<br>To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above." if can?(current_user, :push_code, @project)
message
end
def options_for_mirror_user
options_from_collection_for_select(default_mirror_users, :id, :name, @project.mirror_user_id || current_user.id)
end
end
......@@ -36,12 +36,11 @@
= render "projects/mirrors/instructions"
.form-group
= f.label :mirror_user_id, "Mirror user", class: "label-light"
= users_select_tag("project[mirror_user_id]", class: 'input-large', selected: @project.mirror_user_id || current_user.id,
first_user: true, current_user: true, push_code_to_protected_branches: true)
= select_tag('project[mirror_user_id]', options_for_mirror_user, class: "select2 lg", required: true)
.help-block
This user will be the author of all events in the activity feed that are the result of an update,
like new branches being created or new commits being pushed to existing branches.
They need to have at least master access to this project.
You can only assign yourself to be the mirror user.
- if @project.builds_enabled?
= render "shared/mirror_trigger_builds_setting", f: f
= f.submit 'Save changes', class: 'btn btn-create', name: 'update_remote_mirror'
......
......@@ -6,3 +6,4 @@
Trigger pipelines when branches or tags are updated from the upstream repository.
Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners.
Only enable this if you know they can handle the load.
<strong>CI will run using the credentials assigned above.</strong>
---
title: Prevent mirror user to be assigned to users other than the current one
merge_request:
author:
......@@ -2,16 +2,15 @@
describe Projects::ImportsController do
let(:user) { create(:user) }
let(:project) { create(:empty_project) }
before do
sign_in(user)
project.team << [user, :master]
end
describe 'GET #show' do
context 'when repository does not exists' do
let(:project) { create(:empty_project) }
before do
sign_in(user)
project.team << [user, :master]
end
it 'renders template' do
get :show, namespace_id: project.namespace.to_param, project_id: project
......@@ -28,11 +27,6 @@
context 'when repository exists' do
let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
before do
sign_in(user)
project.team << [user, :master]
end
context 'when import is in progress' do
before do
project.update_attribute(:import_status, :started)
......@@ -125,4 +119,23 @@
end
end
end
context 'POST #create' do
context 'mirror user is not the current user' do
it 'should only assign the current user' do
allow_any_instance_of(EE::Project).to receive(:add_import_job)
new_user = create(:user)
project.add_master(new_user)
post :create, namespace_id: project.namespace.to_param,
project_id: project,
project: { mirror: true, mirror_user_id: new_user.id, import_url: 'http://local.dev' },
format: :json
expect(project.reload.mirror).to eq(true)
expect(project.reload.mirror_user.id).to eq(user.id)
end
end
end
end
......@@ -71,6 +71,20 @@
expect(project.reload.mirror).to eq(true)
expect(project.reload.import_url).to eq('http://local.dev')
end
context 'mirror user is not the current user' do
it 'should only assign the current user' do
expect_any_instance_of(EE::Project).to receive(:force_import_job!)
new_user = create(:user)
project.add_master(new_user)
do_put(project, mirror: true, mirror_user_id: new_user.id, import_url: 'http://local.dev')
expect(project.reload.mirror).to eq(true)
expect(project.reload.mirror_user.id).to eq(project.owner.id)
end
end
end
end
end
......
......@@ -60,7 +60,7 @@
click_button('Save changes')
expect(find('.select2-chosen')).to have_content(user2.name)
expect(find('.select2-chosen')).to have_content(user.name)
end
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment