diff --git a/config/feature_flags/gitlab_com_derisk/exclude_git_http_from_web_rate_limiter.yml b/config/feature_flags/gitlab_com_derisk/exclude_git_http_from_web_rate_limiter.yml new file mode 100644 index 0000000000000000000000000000000000000000..32fdae51d02492e08c1e8567982998c5f4933d1d --- /dev/null +++ b/config/feature_flags/gitlab_com_derisk/exclude_git_http_from_web_rate_limiter.yml @@ -0,0 +1,10 @@ +--- +name: exclude_git_http_from_web_rate_limiter +description: +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/581142 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/213141 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/581527 +milestone: '18.6' +group: group::source code +type: gitlab_com_derisk +default_enabled: false diff --git a/lib/gitlab/rack_attack/request.rb b/lib/gitlab/rack_attack/request.rb index fc1a50a78290ff81bb08c206e5f809c567864443..283772948e0a22d8fd3e25603ed3ae0409fe1fd0 100644 --- a/lib/gitlab/rack_attack/request.rb +++ b/lib/gitlab/rack_attack/request.rb @@ -116,6 +116,7 @@ def throttle_authenticated_api? def throttle_authenticated_web? (web_request? || frontend_request?) && !throttle_authenticated_git_lfs? && + !(git_path? && !git_lfs_path? && Feature.enabled?(:exclude_git_http_from_web_rate_limiter, :instance)) && Gitlab::Throttle.settings.throttle_authenticated_web_enabled end diff --git a/spec/lib/gitlab/rack_attack/request_spec.rb b/spec/lib/gitlab/rack_attack/request_spec.rb index ce4ca9a1000d0801c2ace33d08dbe1029e9181a4..0de42dd42c0f56cd5794392e0f080e26ab7a43af 100644 --- a/spec/lib/gitlab/rack_attack/request_spec.rb +++ b/spec/lib/gitlab/rack_attack/request_spec.rb @@ -218,6 +218,79 @@ end end + describe '#throttle_authenticated_web?' do + let_it_be(:project) { create(:project) } + + let(:git_info_refs_path) { "/#{project.full_path}.git/info/refs?service=git-upload-pack" } + let(:git_lfs_path) { "/#{project.full_path}.git/info/lfs/objects/batch" } + let(:web_path) { '/users/sign_in' } + + subject { request.throttle_authenticated_web? } + + where(:path, :throttle_authenticated_web_enabled, :throttle_authenticated_git_lfs_enabled, :expected) do + ref(:web_path) | true | false | true + ref(:web_path) | false | false | false + ref(:web_path) | true | true | true + ref(:web_path) | false | true | false + + # Git HTTP paths are always excluded regardless of settings + ref(:git_info_refs_path) | true | false | false + ref(:git_info_refs_path) | false | false | false + ref(:git_info_refs_path) | true | true | false + ref(:git_info_refs_path) | false | true | false + + # Git LFS paths are excluded when LFS throttle is enabled + ref(:git_lfs_path) | true | true | false + ref(:git_lfs_path) | false | true | false + ref(:git_lfs_path) | true | false | true + ref(:git_lfs_path) | false | false | false + end + + with_them do + before do + stub_application_setting( + throttle_authenticated_web_enabled: throttle_authenticated_web_enabled, + throttle_authenticated_git_lfs_enabled: throttle_authenticated_git_lfs_enabled + ) + end + + it { is_expected.to eq expected } + end + + context 'when exclude_git_http_from_web_rate_limiter is disabled' do + where(:path, :throttle_authenticated_web_enabled, :throttle_authenticated_git_lfs_enabled, :expected) do + ref(:web_path) | true | false | true + ref(:web_path) | false | false | false + ref(:web_path) | true | true | true + ref(:web_path) | false | true | false + + # Git HTTP paths are not excluded from web rate limiter + ref(:git_info_refs_path) | true | false | true + ref(:git_info_refs_path) | false | false | false + ref(:git_info_refs_path) | true | true | true + ref(:git_info_refs_path) | false | true | false + + # Git LFS paths are excluded when LFS throttle is enabled + ref(:git_lfs_path) | true | true | false + ref(:git_lfs_path) | false | true | false + ref(:git_lfs_path) | true | false | true + ref(:git_lfs_path) | false | false | false + end + + with_them do + before do + stub_feature_flags(exclude_git_http_from_web_rate_limiter: false) + stub_application_setting( + throttle_authenticated_web_enabled: throttle_authenticated_web_enabled, + throttle_authenticated_git_lfs_enabled: throttle_authenticated_git_lfs_enabled + ) + end + + it { is_expected.to eq expected } + end + end + end + describe '#throttle_unauthenticated_git_http?' do let_it_be(:project) { create(:project) }