Add configurable authenticated Git HTTP rate limit
Why
This is related to the work in Implement circuitbreaker/roundTripper using gob... (!186928 - merged) . It's recommended to read the description there to understand why an administrator would need to be able to apply a rate limit in the rails app for the circuitbreaker to work. The ability to configure rate limits for unauthenticated Git HTTP operations already exists in the Admin -> Settings -> Network part of the web gui.
This MR adds a rate limit for the authenticated git http requests in the rails app.
Some context notes
This workhorse Git over HTTP diagram is helpful context.
Key information from our docs
By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations may trigger the rate limits configured for unauthenticated requests
A deeper dive into this in local development is seen in this slack internal chat, though I've tried to surface all the information from that in the steps to validate locally further down in this description.
What
- add a new rate limit key to the jsonb rate_limits so we can have one specifically for authenticated git http
- similar to the unauthenticated git requests approach but the main difference is using the
rate_limis
jsonb column which appears to be what we want to use for rate limits (see !144289 (merged)). - rate limit is disabled by default and configurable in the Admin -> Settings -> Network tab in the existing Git HTTP settings area.
- UI and backend rate limiting are behind a new feature flag
git_authenticated_http_limit
Screenshot
before | after |
---|---|
![]() |
![]() |
Steps to Test Git HTTP Rate Limiting Locally
Prerequisites
- GDK running locally
- A test project in your GDK
- Git configured to use HTTP instead of SSH
Setup
- Configure Git to use HTTP for a test project with private visibility
- Enable and configure rate limiting:
- Enable the feature flag in rails console:
Feature.enable(:git_authenticated_http_limit)
- Go to Admin Area → Settings → Network → Git HTTP rate limits
- Check "Enable authenticated Git HTTP request rate limit"
- Set a low limit (e.g., 5-10 requests per period)
- Set a period long enough to allow hitting the limit easily and short enough to check it gets cleared out
- Save changes
- Enable the feature flag in rails console:
Testing
-
Verify rate limit works for a single user:
# Make multiple Git operations to trigger the limit for i in {1..15}; do git pull; done
- You should see a 429 error for each request after exceeding the limit
-
Verify in Redis that the limit is tracked per user:
# In Rails console Gitlab::Redis::RateLimiting.with { |redis| redis.keys("*throttle*") } # Should show something like: ["cache:gitlab:rack::attack:485700:throttle_authenticated_git_http:user:1"] # The number after `user:` should be the user ID # Check the counter value Gitlab::Redis::RateLimiting.with { |redis| redis.get("cache:gitlab:rack::attack:485700:throttle_authenticated_git_http:user:1") } # Should show the number of requests made
-
Test with a second user
-
Create another user in your GDK
-
Configure Git to use the second user's credentials
-
Make Git operations and verify they're not affected by the first user's limit
-
Check Redis to confirm separate counters:
Gitlab::Redis::RateLimiting.with { |redis| redis.keys("*throttle*") } # Should show different keys for users once they hit the limit
-
-
Verify rate limit expiration:
-
Wait for the configured period to pass
-
Check Redis again to confirm counters have expired:
Gitlab::Redis::RateLimiting.with { |redis| redis.keys("*throttle*") } # Should return an empty array after the period expires
-
Try Git operations again to confirm they work
-
-
Trying turning of the setting in Admin and via the FF to ensure rate limit does not apply in either case.
Notes
- Related to Add configurable rate limits to GitHttpController (#543784 - closed)
- Git operations first try unauthenticated, then authenticated if needed
- The rate limit is tracked per user, not per IP address