mirror of
https://github.com/bitwarden/server.git
synced 2025-04-05 21:18:13 -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:
parent
039d3cbce7
commit
7747744ff9
@ -520,6 +520,7 @@ public class GlobalSettings : IGlobalSettings
|
|||||||
|
|
||||||
public class DistributedIpRateLimitingSettings
|
public class DistributedIpRateLimitingSettings
|
||||||
{
|
{
|
||||||
|
public string RedisConnectionString { get; set; }
|
||||||
public bool Enabled { get; set; } = true;
|
public bool Enabled { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using AspNetCoreRateLimit.Redis;
|
using AspNetCoreRateLimit.Redis;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using StackExchange.Redis;
|
using StackExchange.Redis;
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ public class CustomRedisProcessingStrategy : RedisProcessingStrategy
|
|||||||
private const string _redisTimeoutCacheKey = "IpRateLimitRedisTimeout";
|
private const string _redisTimeoutCacheKey = "IpRateLimitRedisTimeout";
|
||||||
|
|
||||||
public CustomRedisProcessingStrategy(
|
public CustomRedisProcessingStrategy(
|
||||||
|
[FromKeyedServices("rate-limiter")]
|
||||||
IConnectionMultiplexer connectionMultiplexer,
|
IConnectionMultiplexer connectionMultiplexer,
|
||||||
IRateLimitConfiguration config,
|
IRateLimitConfiguration config,
|
||||||
ILogger<CustomRedisProcessingStrategy> logger,
|
ILogger<CustomRedisProcessingStrategy> logger,
|
||||||
|
@ -49,7 +49,6 @@ using Microsoft.AspNetCore.HttpOverrides;
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc.Localization;
|
using Microsoft.AspNetCore.Mvc.Localization;
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
using Microsoft.Extensions.Caching.StackExchangeRedis;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
@ -667,7 +666,8 @@ public static class ServiceCollectionExtensions
|
|||||||
services.AddHostedService<IpRateLimitSeedStartupService>();
|
services.AddHostedService<IpRateLimitSeedStartupService>();
|
||||||
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
||||||
|
|
||||||
if (!globalSettings.DistributedIpRateLimiting.Enabled || string.IsNullOrEmpty(globalSettings.Redis.ConnectionString))
|
if (!globalSettings.DistributedIpRateLimiting.Enabled ||
|
||||||
|
string.IsNullOrEmpty(globalSettings.DistributedIpRateLimiting.RedisConnectionString))
|
||||||
{
|
{
|
||||||
services.AddInMemoryRateLimiting();
|
services.AddInMemoryRateLimiting();
|
||||||
}
|
}
|
||||||
@ -679,7 +679,8 @@ public static class ServiceCollectionExtensions
|
|||||||
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
|
services.AddSingleton<IClientPolicyStore, MemoryCacheClientPolicyStore>();
|
||||||
|
|
||||||
// Use a custom Redis processing strategy that skips Ip limiting if Redis is down
|
// 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>();
|
services.AddSingleton<IProcessingStrategy, CustomRedisProcessingStrategy>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -698,22 +699,9 @@ public static class ServiceCollectionExtensions
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the IConnectionMultiplexer explicitly so it can be accessed via DI
|
services.AddStackExchangeRedisCache(options =>
|
||||||
// (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 =>
|
|
||||||
{
|
{
|
||||||
return new RedisCache(new RedisCacheOptions
|
options.Configuration = globalSettings.Redis.ConnectionString;
|
||||||
{
|
|
||||||
// Use "ProjectName:" as an instance name to namespace keys and avoid conflicts between projects
|
|
||||||
InstanceName = $"{globalSettings.ProjectName}:",
|
|
||||||
ConnectionMultiplexerFactory = () =>
|
|
||||||
Task.FromResult(s.GetRequiredService<IConnectionMultiplexer>())
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user