From 38dadcee569adfbbb1c9dc99634bba4e9a9128bc Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 29 Mar 2023 23:49:08 +0000 Subject: Add latest changes from gitlab-org/security/gitlab@15-9-stable-ee --- ...ify_last_error_from_project_mirror_data_spec.rb | 84 ++++++++++++++++++++++ spec/lib/gitlab/url_sanitizer_spec.rb | 31 ++++---- ...ify_last_error_from_project_mirror_data_spec.rb | 37 ++++++++++ .../push_options_handler_service_spec.rb | 15 ++++ 4 files changed, 155 insertions(+), 12 deletions(-) create mode 100644 spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb create mode 100644 spec/migrations/nullify_last_error_from_project_mirror_data_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb b/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb new file mode 100644 index 00000000000..62f908ed79b --- /dev/null +++ b/spec/lib/gitlab/background_migration/nullify_last_error_from_project_mirror_data_spec.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::NullifyLastErrorFromProjectMirrorData, feature_category: :source_code_management do # rubocop:disable Layout/LineLength + it 'nullifies last_error column on all rows' do + namespaces = table(:namespaces) + projects = table(:projects) + project_import_states = table(:project_mirror_data) + + group = namespaces.create!(name: 'gitlab', path: 'gitlab-org') + + project_namespace_1 = namespaces.create!(name: 'gitlab', path: 'gitlab-org') + project_namespace_2 = namespaces.create!(name: 'gitlab', path: 'gitlab-org') + project_namespace_3 = namespaces.create!(name: 'gitlab', path: 'gitlab-org') + + project_1 = projects.create!( + namespace_id: group.id, + project_namespace_id: project_namespace_1.id, + name: 'test1' + ) + project_2 = projects.create!( + namespace_id: group.id, + project_namespace_id: project_namespace_2.id, + name: 'test2' + ) + project_3 = projects.create!( + namespace_id: group.id, + project_namespace_id: project_namespace_3.id, + name: 'test3' + ) + + project_import_state_1 = project_import_states.create!( + project_id: project_1.id, + status: 0, + last_update_started_at: 1.hour.ago, + last_update_scheduled_at: 1.hour.ago, + last_update_at: 1.hour.ago, + last_successful_update_at: 2.days.ago, + last_error: '13:fetch remote: "fatal: unable to look up user:pass@gitlab.com (port 9418) (nodename nor servname provided, or not known)\n": exit status 128.', # rubocop:disable Layout/LineLength + correlation_id_value: SecureRandom.uuid, + jid: SecureRandom.uuid + ) + + project_import_states.create!( + project_id: project_2.id, + status: 1, + last_update_started_at: 1.hour.ago, + last_update_scheduled_at: 1.hour.ago, + last_update_at: 1.hour.ago, + last_successful_update_at: nil, + next_execution_timestamp: 1.day.from_now, + last_error: '', + correlation_id_value: SecureRandom.uuid, + jid: SecureRandom.uuid + ) + + project_import_state_3 = project_import_states.create!( + project_id: project_3.id, + status: 2, + last_update_started_at: 1.hour.ago, + last_update_scheduled_at: 1.hour.ago, + last_update_at: 1.hour.ago, + last_successful_update_at: 1.hour.ago, + next_execution_timestamp: 1.day.from_now, + last_error: nil, + correlation_id_value: SecureRandom.uuid, + jid: SecureRandom.uuid + ) + + migration = described_class.new( + start_id: project_import_state_1.id, + end_id: project_import_state_3.id, + batch_table: :project_mirror_data, + batch_column: :id, + sub_batch_size: 1, + pause_ms: 0, + connection: ApplicationRecord.connection + ) + + w_last_error_count = -> { project_import_states.where.not(last_error: nil).count } # rubocop:disable CodeReuse/ActiveRecord + expect { migration.perform }.to change(&w_last_error_count).from(2).to(0) + end +end diff --git a/spec/lib/gitlab/url_sanitizer_spec.rb b/spec/lib/gitlab/url_sanitizer_spec.rb index 0ffbf5f81e7..c02cbef8328 100644 --- a/spec/lib/gitlab/url_sanitizer_spec.rb +++ b/spec/lib/gitlab/url_sanitizer_spec.rb @@ -10,29 +10,36 @@ RSpec.describe Gitlab::UrlSanitizer do # We want to try with multi-line content because is how error messages are formatted described_class.sanitize(%Q{ remote: Not Found - fatal: repository '#{url}' not found + fatal: repository `#{url}` not found }) end where(:input, :output) do - 'http://user:pass@test.com/root/repoC.git/' | 'http://*****:*****@test.com/root/repoC.git/' - 'https://user:pass@test.com/root/repoA.git/' | 'https://*****:*****@test.com/root/repoA.git/' - 'ssh://user@host.test/path/to/repo.git' | 'ssh://*****@host.test/path/to/repo.git' - - # git protocol does not support authentication but clean any details anyway - 'git://user:pass@host.test/path/to/repo.git' | 'git://*****:*****@host.test/path/to/repo.git' - 'git://host.test/path/to/repo.git' | 'git://host.test/path/to/repo.git' + # http(s), ssh, git, relative, and schemeless URLs should all be masked correctly + urls = ['http://', 'https://', 'ssh://', 'git://', '//', ''].flat_map do |protocol| + [ + ["#{protocol}test.com", "#{protocol}test.com"], + ["#{protocol}test.com/", "#{protocol}test.com/"], + ["#{protocol}test.com/path/to/repo.git", "#{protocol}test.com/path/to/repo.git"], + ["#{protocol}user@test.com", "#{protocol}*****@test.com"], + ["#{protocol}user:pass@test.com", "#{protocol}*****:*****@test.com"], + ["#{protocol}user:@test.com", "#{protocol}*****@test.com"], + ["#{protocol}:pass@test.com", "#{protocol}:*****@test.com"] + ] + end # SCP-style URLs are left unmodified - 'user@server:project.git' | 'user@server:project.git' - 'user:pass@server:project.git' | 'user:pass@server:project.git' + urls << ['user@server:project.git', 'user@server:project.git'] + urls << ['user:@server:project.git', 'user:@server:project.git'] + urls << [':pass@server:project.git', ':pass@server:project.git'] + urls << ['user:pass@server:project.git', 'user:pass@server:project.git'] # return an empty string for invalid URLs - 'ssh://' | '' + urls << ['ssh://', ''] end with_them do - it { expect(sanitize_url(input)).to include("repository '#{output}' not found") } + it { expect(sanitize_url(input)).to include("repository `#{output}` not found") } end end diff --git a/spec/migrations/nullify_last_error_from_project_mirror_data_spec.rb b/spec/migrations/nullify_last_error_from_project_mirror_data_spec.rb new file mode 100644 index 00000000000..6c5679b674e --- /dev/null +++ b/spec/migrations/nullify_last_error_from_project_mirror_data_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' + +require_migration! + +RSpec.describe NullifyLastErrorFromProjectMirrorData, feature_category: :source_code_management do + let(:migration) { described_class::MIGRATION } + + before do + migrate! + end + + describe '#up' do + it 'schedules background jobs for each batch of projects' do + expect(migration).to( + have_scheduled_batched_migration( + table_name: :project_mirror_data, + column_name: :id, + interval: described_class::INTERVAL, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + ) + end + end + + describe '#down' do + before do + schema_migrate_down! + end + + it 'deletes all batched migration records' do + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/services/merge_requests/push_options_handler_service_spec.rb b/spec/services/merge_requests/push_options_handler_service_spec.rb index 251bf6f0d9d..03f3d56cdd2 100644 --- a/spec/services/merge_requests/push_options_handler_service_spec.rb +++ b/spec/services/merge_requests/push_options_handler_service_spec.rb @@ -861,6 +861,21 @@ RSpec.describe MergeRequests::PushOptionsHandlerService do end end + describe 'when user does not have access to target project' do + let(:push_options) { { create: true, target: 'my-branch' } } + let(:changes) { default_branch_changes } + + before do + allow(user1).to receive(:can?).with(:read_code, project).and_return(false) + end + + it 'records an error', :sidekiq_inline do + service.execute + + expect(service.errors).to eq(["User access was denied"]) + end + end + describe 'when MRs are not enabled' do let(:project) { create(:project, :public, :repository).tap { |pr| pr.add_developer(user1) } } let(:push_options) { { create: true } } -- cgit v1.2.3