diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index bd7631c7e78dbd23b64f48abbeb1d95035219c51..79c4f9a02601a658f05b0266af2108af750e6d7c 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -13,6 +13,9 @@ class RegistrationsController < Devise::RegistrationsController before_action :ensure_destroy_prerequisites_met, only: [:destroy] before_action :load_recaptcha, only: :new before_action :set_invite_params, only: :new + before_action only: [:create] do + check_rate_limit!(:user_sign_up, scope: request.ip) if Feature.enabled?(:rate_limit_user_sign_up_endpoint, default_enabled: :yaml) + end feature_category :authentication_and_authorization diff --git a/config/feature_flags/development/rate_limit_user_sign_up_endpoint.yml b/config/feature_flags/development/rate_limit_user_sign_up_endpoint.yml new file mode 100644 index 0000000000000000000000000000000000000000..af1957e54c8704f6fb5e6359c94223d539357a13 --- /dev/null +++ b/config/feature_flags/development/rate_limit_user_sign_up_endpoint.yml @@ -0,0 +1,8 @@ +--- +name: rate_limit_user_sign_up_endpoint +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/77835 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/349843 +milestone: '14.7' +type: development +group: group::optimize +default_enabled: false diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index dac1f686da7062c6012c9f6ead439b861bafa166..b90f1f4da0dd333b493fc65f69fce2367525e595 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -51,6 +51,7 @@ def rate_limits web_hook_calls: { interval: 1.minute }, users_get_by_id: { threshold: 10, interval: 1.minute }, username_exists: { threshold: 20, interval: 1.minute }, + user_sign_up: { threshold: 20, interval: 1.minute }, profile_resend_email_confirmation: { threshold: 5, interval: 1.minute }, profile_update_username: { threshold: 10, interval: 1.minute }, update_environment_canary_ingress: { threshold: 1, interval: 1.minute }, diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 889401e78f8715b7e4f1d7de3749cbac43ad3e05..d5fe32ac09434f765d51d1078cf96c027dd30b4b 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -20,6 +20,10 @@ end describe '#create' do + before do + allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(false) + end + let_it_be(:base_user_params) do { first_name: 'first', last_name: 'last', username: 'new_username', email: 'new@user.com', password: 'Any_password' } end @@ -410,6 +414,18 @@ end end + context 'when the rate limit has been reached' do + it 'returns status 429 Too Many Requests', :aggregate_failures do + ip = '1.2.3.4' + expect(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).with(:user_sign_up, scope: ip).and_return(true) + + controller.request.env['REMOTE_ADDR'] = ip + post(:create, params: user_params, session: session_params) + + expect(response).to have_gitlab_http_status(:too_many_requests) + end + end + it "logs a 'User Created' message" do expect(Gitlab::AppLogger).to receive(:info).with(/\AUser Created: username=new_username email=new@user.com.+\z/).and_call_original