1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00

[PM-6153] Dedicated redis connection for rate limiter (#3763)

* rearrange how redis is registered

* separate redis connection string for rate limiter
This commit is contained in:
Kyle Spearrin 2024-02-07 17:38:18 -05:00 committed by GitHub
parent 039d3cbce7
commit 7747744ff9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 9 additions and 18 deletions

View File

@ -520,6 +520,7 @@ public class GlobalSettings : IGlobalSettings
public class DistributedIpRateLimitingSettings
{
public string RedisConnectionString { get; set; }
public bool Enabled { get; set; } = true;
/// <summary>

View File

@ -2,6 +2,7 @@
using AspNetCoreRateLimit.Redis;
using Bit.Core.Settings;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
@ -26,6 +27,7 @@ public class CustomRedisProcessingStrategy : RedisProcessingStrategy
private const string _redisTimeoutCacheKey = "IpRateLimitRedisTimeout";
public CustomRedisProcessingStrategy(
[FromKeyedServices("rate-limiter")]
IConnectionMultiplexer connectionMultiplexer,
IRateLimitConfiguration config,
ILogger<CustomRedisProcessingStrategy> logger,

View File

@ -49,7 +49,6 @@ using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@ -667,7 +666,8 @@ public static class ServiceCollectionExtensions
services.AddHostedService<IpRateLimitSeedStartupService>();
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
if (!globalSettings.DistributedIpRateLimiting.Enabled || string.IsNullOrEmpty(globalSettings.Redis.ConnectionString))
if (!globalSettings.DistributedIpRateLimiting.Enabled ||
string.IsNullOrEmpty(globalSettings.DistributedIpRateLimiting.RedisConnectionString))
{
services.AddInMemoryRateLimiting();
}
@ -679,7 +679,8 @@ public static class ServiceCollectionExtensions
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
// Use a custom Redis processing strategy that skips Ip limiting if Redis is down
// Requires a registered IConnectionMultiplexer
services.AddKeyedSingleton<IConnectionMultiplexer>("rate-limiter", (_, provider) =>
ConnectionMultiplexer.Connect(globalSettings.DistributedIpRateLimiting.RedisConnectionString));
services.AddSingleton<IProcessingStrategy, CustomRedisProcessingStrategy>();
}
}
@ -698,22 +699,9 @@ public static class ServiceCollectionExtensions
return;
}
// Register the IConnectionMultiplexer explicitly so it can be accessed via DI
// (e.g. for the IP rate limiting store)
services.AddSingleton<IConnectionMultiplexer>(
_ => ConnectionMultiplexer.Connect(globalSettings.Redis.ConnectionString));
// Explicitly register IDistributedCache to re-use existing IConnectionMultiplexer
// to reduce the number of redundant connections to the Redis instance
services.AddSingleton<IDistributedCache>(s =>
services.AddStackExchangeRedisCache(options =>
{
return new RedisCache(new RedisCacheOptions
{
// Use "ProjectName:" as an instance name to namespace keys and avoid conflicts between projects
InstanceName = $"{globalSettings.ProjectName}:",
ConnectionMultiplexerFactory = () =>
Task.FromResult(s.GetRequiredService<IConnectionMultiplexer>())
});
options.Configuration = globalSettings.Redis.ConnectionString;
});
}