diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 4bf5505346b..3dfd2605f01 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -1249,12 +1249,10 @@ lib/gitlab/checks/** /ee/app/controllers/groups/scim_oauth_controller.rb /ee/app/controllers/oauth/ /ee/app/controllers/omniauth_kerberos_controller.rb -/ee/app/controllers/users/registrations_identity_verification_controller.rb /ee/app/finders/auth/ /ee/app/helpers/ee/access_tokens_helper.rb /ee/app/helpers/ee/auth_helper.rb /ee/app/helpers/ee/personal_access_tokens_helper.rb -/ee/app/models/concerns/identity_verifiable.rb /ee/app/models/concerns/password_complexity.rb /ee/app/models/ee/personal_access_token.rb /ee/app/models/ee/project_authorization.rb @@ -1565,8 +1563,10 @@ ee/lib/ee/api/entities/project.rb /ee/spec/frontend/remote_development/ /ee/spec/frontend/**/remote_development/ -^[Govern::Anti-abuse] @gitlab-org/modelops/anti-abuse +[Govern::Anti-abuse] @gitlab-org/modelops/anti-abuse /ee/app/controllers/users/registrations_identity_verification_controller.rb +/ee/app/controllers/users/base_identity_verification_controller.rb +/ee/app/controllers/users/identity_verification_controller.rb /ee/app/models/concerns/identity_verifiable.rb /ee/config/routes/identity_verification.rb diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index 5b75011ac58..92efe9f06e8 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -115,19 +115,6 @@ Layout/ArgumentAlignment: - 'ee/app/services/external_status_checks/create_service.rb' - 'ee/app/services/external_status_checks/destroy_service.rb' - 'ee/app/services/external_status_checks/update_service.rb' - - 'ee/app/services/geo/framework_repository_sync_service.rb' - - 'ee/app/services/geo/prune_event_log_service.rb' - - 'ee/app/services/group_saml/saml_group_links/create_service.rb' - - 'ee/app/services/iterations/create_service.rb' - - 'ee/app/services/merge_trains/create_pipeline_service.rb' - - 'ee/app/services/registrations/standard_namespace_create_service.rb' - - 'ee/app/services/vulnerabilities/confirm_service.rb' - - 'ee/app/services/vulnerabilities/findings/find_or_create_from_security_finding_service.rb' - - 'ee/app/services/vulnerabilities/security_finding/create_merge_request_service.rb' - - 'ee/app/services/vulnerabilities/starboard_vulnerability_resolve_service.rb' - - 'ee/app/services/vulnerability_feedback/create_service.rb' - - 'ee/app/services/vulnerability_merge_request_links/create_service.rb' - - 'ee/db/geo/migrate/20180405074130_add_partial_index_project_repository_verification.rb' - 'ee/db/geo/post_migrate/20210217020154_add_unique_index_on_container_repository_registry.rb' - 'ee/db/geo/post_migrate/20210217020156_add_unique_index_on_terraform_state_version_registry.rb' - 'ee/lib/ee/gitlab/import_sources.rb' diff --git a/config/initializers/8_devise.rb b/config/initializers/8_devise.rb index 9ea26602a13..cdd178fefa7 100644 --- a/config/initializers/8_devise.rb +++ b/config/initializers/8_devise.rb @@ -160,20 +160,22 @@ Devise.setup do |config| # :none = No unlock strategy. You should handle unlocking by yourself. config.unlock_strategy = :both - # Number of authentication tries before locking an account if lock_strategy - # is failed attempts. - config.maximum_attempts = if Gitlab::CurrentSettings.max_login_attempts_column_exists? - (Gitlab::CurrentSettings.max_login_attempts || 10) - else - 10 - end + ActiveSupport.on_load(:gitlab_db_load_balancer) do + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + config.maximum_attempts = if Gitlab::CurrentSettings.max_login_attempts_column_exists? + (Gitlab::CurrentSettings.max_login_attempts || 10) + else + 10 + end - # Time interval to unlock the account if :time is enabled as unlock_strategy. - config.unlock_in = if Gitlab::CurrentSettings.failed_login_attempts_unlock_period_in_minutes_column_exists? - (Gitlab::CurrentSettings.failed_login_attempts_unlock_period_in_minutes || 10).minutes - else - 10.minutes - end + # Time interval to unlock the account if :time is enabled as unlock_strategy. + config.unlock_in = if Gitlab::CurrentSettings.failed_login_attempts_unlock_period_in_minutes_column_exists? + (Gitlab::CurrentSettings.failed_login_attempts_unlock_period_in_minutes || 10).minutes + else + 10.minutes + end + end # ==> Configuration for :recoverable # diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb index aa621602573..32b8e6e5a73 100644 --- a/config/initializers/load_balancing.rb +++ b/config/initializers/load_balancing.rb @@ -40,3 +40,5 @@ Gitlab::Database::LoadBalancing.base_models.each do |model| .setup end end + +ActiveSupport.run_load_hooks(:gitlab_db_load_balancer) diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile index 307c7d23b68..f5dba626dff 100644 --- a/danger/feature_flag/Dangerfile +++ b/danger/feature_flag/Dangerfile @@ -34,12 +34,22 @@ module Tooling @helper = helper end - def check_touched_feature_flag_files - touched_feature_flag_files.each do |feature_flag| + def check_added_feature_flag_files + added_files.each do |feature_flag| check_feature_flag_yaml(feature_flag) end end + def check_modified_feature_flag_files + modified_files.each do |feature_flag| + check_default_enabled(feature_flag) + end + end + + def feature_flag_file_added? + added_files.any? + end + def feature_flag_file_touched? touched_feature_flag_files.any? end @@ -201,9 +211,10 @@ feature_flag_dangerfile = Tooling::FeatureFlagDangerfile.new( helper: helper ) -feature_flag_dangerfile.check_touched_feature_flag_files +feature_flag_dangerfile.check_added_feature_flag_files +feature_flag_dangerfile.check_modified_feature_flag_files -if helper.security_mr? && feature_flag_dangerfile.feature_flag_file_touched? +if helper.security_mr? && feature_flag_dangerfile.feature_flag_file_added? failure("Feature flags are discouraged from security merge requests. Read the [security documentation](https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/utilities/feature_flags.md) for details.") end diff --git a/doc/administration/audit_event_types.md b/doc/administration/audit_event_types.md index e779518eb06..ca7d1e1643f 100644 --- a/doc/administration/audit_event_types.md +++ b/doc/administration/audit_event_types.md @@ -189,6 +189,8 @@ Audit event types belong to the following product categories. | [`deploy_token_creation_failed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89391) | Audit event triggered when deploy token fails to create| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Project | | [`deploy_token_destroyed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89391) | Audit event triggered when deploy token is destroyed| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Project | | [`deploy_token_revoked`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89391) | Triggered when project deploy token is revoked| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.1](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Project | +| [`deployment_approved`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153375) | Triggered when a deployment is approved| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.1](https://gitlab.com/gitlab-org/gitlab/-/issues/456685) | Project | +| [`deployment_rejected`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153375) | Triggered when a deployment is rejected| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [17.1](https://gitlab.com/gitlab-org/gitlab/-/issues/456685) | Project | | [`group_deploy_token_created`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93091) | Audit event triggered when a groups deploy token is created| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.3](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Group | | [`group_deploy_token_creation_failed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93091) | Audit event triggered when a groups deploy token fails to create| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.3](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Group | | [`group_deploy_token_destroyed`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93091) | Audit event triggered when group deploy token is destroyed| **{check-circle}** Yes | **{check-circle}** Yes | GitLab [15.3](https://gitlab.com/gitlab-org/gitlab/-/issues/363087) | Group | diff --git a/doc/administration/gitaly/bundle_uris.md b/doc/administration/gitaly/bundle_uris.md index 1e76db994d5..6e5b1b61f05 100644 --- a/doc/administration/gitaly/bundle_uris.md +++ b/doc/administration/gitaly/bundle_uris.md @@ -70,7 +70,7 @@ gitaly['env'] = { } gitaly['configuration'] = { bundle_uri: { - go_cloud_url: 'azblob://gitaly-bundleuri' + go_cloud_url: 'azblob://' } } ``` @@ -81,7 +81,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [bundle_uri] -go_cloud_url = "azblob://gitaly-bundleuri" +go_cloud_url = "azblob://" ``` ::EndTabs @@ -113,7 +113,7 @@ gitaly['env'] = { } gitaly['configuration'] = { bundle_uri: { - go_cloud_url: 'gs://gitaly-bundleuri' + go_cloud_url: 'gs://' } } ``` @@ -124,7 +124,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [bundle_uri] -go_cloud_url = "gs://gitaly-bundle_uri" +go_cloud_url = "gs://" ``` ::EndTabs @@ -156,7 +156,7 @@ gitaly['env'] = { } gitaly['configuration'] = { bundle_uri: { - go_cloud_url: 's3://gitaly-bundle_uri?region=us-west-1' + go_cloud_url: 's3://?region=us-west-1' } } ``` @@ -167,7 +167,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [bundle_uri] -go_cloud_url = "s3://gitaly-bundle_uri?region=us-west-1" +go_cloud_url = "s3://?region=us-west-1" ``` ::EndTabs @@ -197,7 +197,7 @@ gitaly['env'] = { } gitaly['configuration'] = { bundle_uri: { - go_cloud_url: 's3://gitaly-bundleuri?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true' + go_cloud_url: 's3://?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true' } } ``` @@ -208,7 +208,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [bundle_uri] -go_cloud_url = "s3://gitaly-bundleuri?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true" +go_cloud_url = "s3://?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true" ``` ::EndTabs diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md index 0491f1d2d29..ee380f7b72b 100644 --- a/doc/administration/gitaly/configure_gitaly.md +++ b/doc/administration/gitaly/configure_gitaly.md @@ -1314,7 +1314,7 @@ gitaly['env'] = { } gitaly['configuration'] = { backup: { - go_cloud_url: 'azblob://gitaly-backups' + go_cloud_url: 'azblob://' } } ``` @@ -1325,7 +1325,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [backup] -go_cloud_url = "azblob://gitaly-backups" +go_cloud_url = "azblob://" ``` ::EndTabs @@ -1354,7 +1354,7 @@ gitaly['env'] = { } gitaly['configuration'] = { backup: { - go_cloud_url: 'gs://gitaly-backups' + go_cloud_url: 'gs://' } } ``` @@ -1365,7 +1365,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [backup] -go_cloud_url = "gs://gitaly-backups" +go_cloud_url = "gs://" ``` ::EndTabs @@ -1395,7 +1395,7 @@ gitaly['env'] = { } gitaly['configuration'] = { backup: { - go_cloud_url: 's3://gitaly-backups?region=us-west-1' + go_cloud_url: 's3://?region=us-west-1' } } ``` @@ -1406,7 +1406,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [backup] -go_cloud_url = "s3://gitaly-backups?region=us-west-1" +go_cloud_url = "s3://?region=us-west-1" ``` ::EndTabs @@ -1435,7 +1435,7 @@ gitaly['env'] = { } gitaly['configuration'] = { backup: { - go_cloud_url: 's3://gitaly-backups?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true' + go_cloud_url: 's3://?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true' } } ``` @@ -1446,7 +1446,7 @@ Edit `/home/git/gitaly/config.toml` and configure `go_cloud_url`: ```toml [backup] -go_cloud_url = "s3://gitaly-backups?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true" +go_cloud_url = "s3://?region=minio&endpoint=my.minio.local:8080&disableSSL=true&s3ForcePathStyle=true" ``` ::EndTabs diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md index 7bb1d17f898..ee1a7e74f1d 100644 --- a/doc/administration/gitaly/troubleshooting.md +++ b/doc/administration/gitaly/troubleshooting.md @@ -586,3 +586,54 @@ To create a rule to allow Gitaly binary execution: ``` The new rule takes effect after the daemon restarts. + +## Update repositories after removing a storage with a duplicate path + +> - Rake task `gitlab:gitaly:update_removed_storage_projects` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/153008) in GitLab 17.1. + +In GitLab 17.0, support for configuring storages with duplicate paths [was removed](https://gitlab.com/gitlab-org/gitaly/-/issues/5598). This can mean that you +must remove duplicate storage configuration from `gitaly` configuration. + +WARNING: +Only use this Rake task when the old and new storages share the same disk path on the same Gitaly server. Using the this Rake task in any other situation +causes the repository to become unavailable. Use the [project repository storage moves API](../../api/project_repository_storage_moves.md) to transfer +projects between storages in all other situations. + +When removing from the Gitaly configuration a storage that used the same path as another storage, +the projects associated with the old storage must be reassigned to the new one. + +For example, you might have configuration similar to the following: + +```ruby +gitaly['configuration'] = { + storage: [ + { + name: 'default', + path: '/var/opt/gitlab/git-data/repositories', + }, + { + name: 'duplicate-path', + path: '/var/opt/gitlab/git-data/repositories', + }, + ], +} +``` + +If you were removing `duplicate-path` from the configuration, you would run the following +Rake task to associate any projects assigned to it to `default` instead: + +::Tabs + +:::TabTitle Linux package installations + +```shell +sudo gitlab-rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]" +``` + +:::TabTitle Self-compiled installations + +```shell +sudo -u git -H bundle exec rake "gitlab:gitaly:update_removed_storage_projects[duplicate-path, default]" RAILS_ENV=production +``` + +::EndTabs diff --git a/doc/administration/settings/security_contact_information.md b/doc/administration/settings/security_contact_information.md index edce0ef1b77..0c37f4a571d 100644 --- a/doc/administration/settings/security_contact_information.md +++ b/doc/administration/settings/security_contact_information.md @@ -24,10 +24,9 @@ required to view this file. To configure a `security.txt` file: -1. On the left sidebar, select **Search or go to**. -1. Select **Admin Area**. +1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **Settings > General**. -1. Expand the **Add security contact information** section. +1. Expand **Add security contact information**. 1. In **Content for security.txt**, enter security contact information in the format documented at . 1. Select **Save changes**. diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake index 4c19d94f4a1..7f105cfd4e8 100644 --- a/lib/tasks/gitlab/gitaly.rake +++ b/lib/tasks/gitlab/gitaly.rake @@ -31,6 +31,32 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]") end end + desc 'GitLab | Gitaly | Update removed storage projects' + task :update_removed_storage_projects, + [:removed_storage_name, :target_storage_name] => :gitlab_environment do |t, args| + warn_user_is_not_gitlab + + unless args.removed_storage_name.present? && args.target_storage_name.present? + abort %(Please specify the names of the removed storage and the storage to move projects to +Usage: rake "gitlab:gitaly:update_removed_storage_projects[removed_storage_name,target_storage_name]") + end + + project_ct = Project.where(repository_storage: args.removed_storage_name).length + + if ENV['APPLY'] == '1' + puts "Updating #{project_ct} projects from storage " \ + "#{args.removed_storage_name} to #{args.target_storage_name} in the Rails database." + + Project + .where(repository_storage: args.removed_storage_name) + .update_all(repository_storage: args.target_storage_name) + else + puts "DRY RUN: would have updated #{project_ct} projects from storage " \ + "#{args.removed_storage_name} to #{args.target_storage_name} in the Rails database." + puts "Run again with environment variable 'APPLY=1' to perform the change." + end + end + def make_cmd _, status = Gitlab::Popen.popen(%w[which gmake]) status == 0 ? 'gmake' : 'make' diff --git a/spec/initializers/8_devise_spec.rb b/spec/initializers/8_devise_spec.rb new file mode 100644 index 00000000000..d63ccec3557 --- /dev/null +++ b/spec/initializers/8_devise_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Devise initializer for GitLab', :delete, :reestablished_active_record_base, feature_category: :system_access do + def load_initializers + load Rails.root.join('config/initializers/8_devise.rb') + load Rails.root.join('config/initializers/load_balancing.rb') + end + + describe "unlock configuration" do + before do + allow(Gitlab::Application.instance.middleware).to receive(:use) + allow(Gitlab::CurrentSettings).to receive(:max_login_attempts).and_return(35) + allow(Gitlab::CurrentSettings).to receive(:failed_login_attempts_unlock_period_in_minutes).and_return(15) + load_initializers + end + + it "sets custom maximum attempts" do + expect(Devise.maximum_attempts).to be_eql(35) + end + + it "sets custom unlock_in" do + expect(Devise.unlock_in).to be_eql(15.minutes) + end + end +end diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index bb38bd2ee95..032d3e4621f 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do +RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout, feature_category: :source_code_management do before(:all) do Rake.application.rake_require 'tasks/gitlab/gitaly' end @@ -103,4 +103,54 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do end end end + + describe 'update_removed_storage_projects' do + let(:removed_storage_name) { 'removed_storage' } + let(:target_storage_name) { 'target_storage' } + let(:message) { "1 projects from storage #{removed_storage_name} to #{target_storage_name} in the Rails database." } + let_it_be(:project) { create(:project) } # rubocop: disable RSpec/AvoidTestProf -- This is not a migration spec + + before do + project.update_column(:repository_storage, removed_storage_name) + end + + subject { run_rake_task('gitlab:gitaly:update_removed_storage_projects', removed_storage_name, target_storage_name) } + + context 'no removed storage name given' do + it 'aborts and display a help message' do + # avoid writing task output to spec progresdoc/development/gotchas.mds + allow($stderr).to receive :write + expect { run_rake_task('gitlab:gitaly:update_removed_storage_projects') }.to raise_error(/Please specify the names of the removed storage and the storage to move projects to/) + end + end + + context 'no target storage name given' do + it 'aborts and display a help message' do + allow($stderr).to receive :write + expect { run_rake_task('gitlab:gitaly:update_removed_storage_projects', removed_storage_name) }.to raise_error(/Please specify the names of the removed storage and the storage to move projects to/) + end + end + + context 'dry run' do + it 'displays the number of projects and does not update them' do + allow($stdout).to receive :write + expect { subject }.to output(match(/^DRY RUN: would have updated #{message}/)).to_stdout + + project.reload + + expect(project.repository_storage).to eq(removed_storage_name) + end + end + + it 'updates the projects storage' do + stub_env('APPLY', '1') + + allow($stdout).to receive :write + expect { subject }.to output(match(/^Updating #{message}$/)).to_stdout + + project.reload + + expect(project.repository_storage).to eq(target_storage_name) + end + end end