Separate statically- and dynamically-configured rate limiters
This commit is contained in:
parent
13e346d4eb
commit
9628f147f1
|
@ -108,6 +108,7 @@ import org.whispersystems.textsecuregcm.experiment.ExperimentEnrollmentManager;
|
|||
import org.whispersystems.textsecuregcm.filters.ContentLengthFilter;
|
||||
import org.whispersystems.textsecuregcm.filters.RemoteDeprecationFilter;
|
||||
import org.whispersystems.textsecuregcm.filters.TimestampResponseFilter;
|
||||
import org.whispersystems.textsecuregcm.limits.DynamicRateLimiters;
|
||||
import org.whispersystems.textsecuregcm.limits.PreKeyRateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.PushChallengeManager;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager;
|
||||
|
@ -472,7 +473,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
PubSubManager pubSubManager = new PubSubManager(pubsubClient, dispatchManager);
|
||||
APNSender apnSender = new APNSender(apnSenderExecutor, accountsManager, config.getApnConfiguration());
|
||||
GCMSender gcmSender = new GCMSender(gcmSenderExecutor, accountsManager, config.getGcmConfiguration().getApiKey());
|
||||
RateLimiters rateLimiters = new RateLimiters(config.getLimitsConfiguration(), dynamicConfigurationManager, rateLimitersCluster);
|
||||
RateLimiters rateLimiters = new RateLimiters(config.getLimitsConfiguration(), rateLimitersCluster);
|
||||
DynamicRateLimiters dynamicRateLimiters = new DynamicRateLimiters(rateLimitersCluster, dynamicConfigurationManager);
|
||||
ProvisioningManager provisioningManager = new ProvisioningManager(pubSubManager);
|
||||
IssuedReceiptsManager issuedReceiptsManager = new IssuedReceiptsManager(
|
||||
config.getDynamoDbTables().getIssuedReceipts().getTableName(),
|
||||
|
@ -492,8 +494,8 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
|
||||
RateLimitResetMetricsManager rateLimitResetMetricsManager = new RateLimitResetMetricsManager(metricsCluster, Metrics.globalRegistry);
|
||||
|
||||
UnsealedSenderRateLimiter unsealedSenderRateLimiter = new UnsealedSenderRateLimiter(rateLimiters, rateLimitersCluster, dynamicConfigurationManager, rateLimitResetMetricsManager);
|
||||
PreKeyRateLimiter preKeyRateLimiter = new PreKeyRateLimiter(rateLimiters, dynamicConfigurationManager, rateLimitResetMetricsManager);
|
||||
UnsealedSenderRateLimiter unsealedSenderRateLimiter = new UnsealedSenderRateLimiter(dynamicRateLimiters, rateLimitersCluster, dynamicConfigurationManager, rateLimitResetMetricsManager);
|
||||
PreKeyRateLimiter preKeyRateLimiter = new PreKeyRateLimiter(dynamicRateLimiters, dynamicConfigurationManager, rateLimitResetMetricsManager);
|
||||
|
||||
ApnFallbackManager apnFallbackManager = new ApnFallbackManager(pushSchedulerCluster, apnSender, accountsManager);
|
||||
TwilioSmsSender twilioSmsSender = new TwilioSmsSender(config.getTwilioConfiguration(), dynamicConfigurationManager);
|
||||
|
@ -510,7 +512,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
TransitionalRecaptchaClient transitionalRecaptchaClient = new TransitionalRecaptchaClient(legacyRecaptchaClient, enterpriseRecaptchaClient);
|
||||
PushChallengeManager pushChallengeManager = new PushChallengeManager(apnSender, gcmSender, pushChallengeDynamoDb);
|
||||
RateLimitChallengeManager rateLimitChallengeManager = new RateLimitChallengeManager(pushChallengeManager,
|
||||
transitionalRecaptchaClient, preKeyRateLimiter, unsealedSenderRateLimiter, rateLimiters,
|
||||
transitionalRecaptchaClient, preKeyRateLimiter, unsealedSenderRateLimiter, dynamicRateLimiters,
|
||||
dynamicConfigurationManager);
|
||||
|
||||
MessagePersister messagePersister = new MessagePersister(messagesCache, messagesManager, accountsManager, dynamicConfigurationManager, Duration.ofMinutes(config.getMessageCacheConfiguration().getPersistDelayMinutes()));
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright 2013-2021 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.limits;
|
||||
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.CardinalityRateLimitConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.RateLimitConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class DynamicRateLimiters {
|
||||
|
||||
private final FaultTolerantRedisCluster cacheCluster;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
|
||||
private final AtomicReference<CardinalityRateLimiter> unsealedSenderCardinalityLimiter;
|
||||
private final AtomicReference<RateLimiter> unsealedIpLimiter;
|
||||
private final AtomicReference<RateLimiter> rateLimitResetLimiter;
|
||||
private final AtomicReference<RateLimiter> recaptchaChallengeAttemptLimiter;
|
||||
private final AtomicReference<RateLimiter> recaptchaChallengeSuccessLimiter;
|
||||
private final AtomicReference<RateLimiter> pushChallengeAttemptLimiter;
|
||||
private final AtomicReference<RateLimiter> pushChallengeSuccessLimiter;
|
||||
private final AtomicReference<RateLimiter> dailyPreKeysLimiter;
|
||||
|
||||
public DynamicRateLimiters(final FaultTolerantRedisCluster rateLimitCluster,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager) {
|
||||
|
||||
this.cacheCluster = rateLimitCluster;
|
||||
this.dynamicConfigurationManager = dynamicConfigurationManager;
|
||||
|
||||
this.dailyPreKeysLimiter = new AtomicReference<>(
|
||||
createDailyPreKeysLimiter(this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getDailyPreKeys()));
|
||||
|
||||
this.unsealedSenderCardinalityLimiter = new AtomicReference<>(createUnsealedSenderCardinalityLimiter(
|
||||
this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getUnsealedSenderNumber()));
|
||||
|
||||
this.unsealedIpLimiter = new AtomicReference<>(
|
||||
createUnsealedIpLimiter(this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getUnsealedSenderIp()));
|
||||
|
||||
this.rateLimitResetLimiter = new AtomicReference<>(
|
||||
createRateLimitResetLimiter(this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getRateLimitReset()));
|
||||
|
||||
this.recaptchaChallengeAttemptLimiter = new AtomicReference<>(createRecaptchaChallengeAttemptLimiter(
|
||||
this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getRecaptchaChallengeAttempt()));
|
||||
|
||||
this.recaptchaChallengeSuccessLimiter = new AtomicReference<>(createRecaptchaChallengeSuccessLimiter(
|
||||
this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getRecaptchaChallengeSuccess()));
|
||||
|
||||
this.pushChallengeAttemptLimiter = new AtomicReference<>(createPushChallengeAttemptLimiter(this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getPushChallengeAttempt()));
|
||||
|
||||
this.pushChallengeSuccessLimiter = new AtomicReference<>(createPushChallengeSuccessLimiter(this.cacheCluster,
|
||||
this.dynamicConfigurationManager.getConfiguration().getLimits().getPushChallengeSuccess()));
|
||||
}
|
||||
|
||||
public CardinalityRateLimiter getUnsealedSenderCardinalityLimiter() {
|
||||
CardinalityRateLimitConfiguration currentConfiguration = dynamicConfigurationManager.getConfiguration().getLimits()
|
||||
.getUnsealedSenderNumber();
|
||||
|
||||
return this.unsealedSenderCardinalityLimiter.updateAndGet(rateLimiter -> {
|
||||
if (rateLimiter.hasConfiguration(currentConfiguration)) {
|
||||
return rateLimiter;
|
||||
} else {
|
||||
return createUnsealedSenderCardinalityLimiter(cacheCluster, currentConfiguration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RateLimiter getUnsealedIpLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
unsealedIpLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getUnsealedSenderIp(),
|
||||
this::createUnsealedIpLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRateLimitResetLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
rateLimitResetLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getRateLimitReset(),
|
||||
this::createRateLimitResetLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRecaptchaChallengeAttemptLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
recaptchaChallengeAttemptLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getRecaptchaChallengeAttempt(),
|
||||
this::createRecaptchaChallengeAttemptLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRecaptchaChallengeSuccessLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
recaptchaChallengeSuccessLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getRecaptchaChallengeSuccess(),
|
||||
this::createRecaptchaChallengeSuccessLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getPushChallengeAttemptLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
pushChallengeAttemptLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getPushChallengeAttempt(),
|
||||
this::createPushChallengeAttemptLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getPushChallengeSuccessLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
pushChallengeSuccessLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getPushChallengeSuccess(),
|
||||
this::createPushChallengeSuccessLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getDailyPreKeysLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
dailyPreKeysLimiter,
|
||||
dynamicConfigurationManager.getConfiguration().getLimits().getDailyPreKeys(),
|
||||
this::createDailyPreKeysLimiter);
|
||||
}
|
||||
|
||||
private RateLimiter updateAndGetRateLimiter(final AtomicReference<RateLimiter> rateLimiter,
|
||||
RateLimitConfiguration currentConfiguration,
|
||||
BiFunction<FaultTolerantRedisCluster, RateLimitConfiguration, RateLimiter> rateLimitFactory) {
|
||||
|
||||
return rateLimiter.updateAndGet(limiter -> {
|
||||
if (limiter.hasConfiguration(currentConfiguration)) {
|
||||
return limiter;
|
||||
} else {
|
||||
return rateLimitFactory.apply(cacheCluster, currentConfiguration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private CardinalityRateLimiter createUnsealedSenderCardinalityLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
CardinalityRateLimitConfiguration configuration) {
|
||||
return new CardinalityRateLimiter(cacheCluster, "unsealedSender", configuration.getTtl(),
|
||||
configuration.getMaxCardinality());
|
||||
}
|
||||
|
||||
private RateLimiter createUnsealedIpLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "unsealedIp");
|
||||
}
|
||||
|
||||
public RateLimiter createRateLimitResetLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "rateLimitReset");
|
||||
}
|
||||
|
||||
public RateLimiter createRecaptchaChallengeAttemptLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "recaptchaChallengeAttempt");
|
||||
}
|
||||
|
||||
public RateLimiter createRecaptchaChallengeSuccessLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "recaptchaChallengeSuccess");
|
||||
}
|
||||
|
||||
public RateLimiter createPushChallengeAttemptLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "pushChallengeAttempt");
|
||||
}
|
||||
|
||||
public RateLimiter createPushChallengeSuccessLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "pushChallengeSuccess");
|
||||
}
|
||||
|
||||
public RateLimiter createDailyPreKeysLimiter(FaultTolerantRedisCluster cacheCluster,
|
||||
RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "dailyPreKeys");
|
||||
}
|
||||
|
||||
private RateLimiter createLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration,
|
||||
String name) {
|
||||
return new RateLimiter(cacheCluster, name,
|
||||
configuration.getBucketSize(),
|
||||
configuration.getLeakRatePerMinute());
|
||||
}
|
||||
}
|
|
@ -28,11 +28,11 @@ public class PreKeyRateLimiter {
|
|||
private static final String RATE_LIMITED_ACCOUNTS_UNENFORCED_HLL_KEY = "PreKeyRateLimiter::rateLimitedAccounts::unenforced";
|
||||
private static final long RATE_LIMITED_ACCOUNTS_HLL_TTL_SECONDS = Duration.days(1).toSeconds();
|
||||
|
||||
private final RateLimiters rateLimiters;
|
||||
private final DynamicRateLimiters rateLimiters;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
private final RateLimitResetMetricsManager metricsManager;
|
||||
|
||||
public PreKeyRateLimiter(final RateLimiters rateLimiters,
|
||||
public PreKeyRateLimiter(final DynamicRateLimiters rateLimiters,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager,
|
||||
final RateLimitResetMetricsManager metricsManager) {
|
||||
this.rateLimiters = rateLimiters;
|
||||
|
|
|
@ -26,7 +26,7 @@ public class RateLimitChallengeManager {
|
|||
private final PreKeyRateLimiter preKeyRateLimiter;
|
||||
private final UnsealedSenderRateLimiter unsealedSenderRateLimiter;
|
||||
|
||||
private final RateLimiters rateLimiters;
|
||||
private final DynamicRateLimiters rateLimiters;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
|
||||
public static final String OPTION_RECAPTCHA = "recaptcha";
|
||||
|
@ -43,7 +43,7 @@ public class RateLimitChallengeManager {
|
|||
final RecaptchaClient recaptchaClient,
|
||||
final PreKeyRateLimiter preKeyRateLimiter,
|
||||
final UnsealedSenderRateLimiter unsealedSenderRateLimiter,
|
||||
final RateLimiters rateLimiters,
|
||||
final DynamicRateLimiters rateLimiters,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager) {
|
||||
|
||||
this.pushChallengeManager = pushChallengeManager;
|
||||
|
|
|
@ -5,14 +5,8 @@
|
|||
package org.whispersystems.textsecuregcm.limits;
|
||||
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiFunction;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.CardinalityRateLimitConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.RateLimitConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
|
||||
public class RateLimiters {
|
||||
|
||||
|
@ -41,22 +35,7 @@ public class RateLimiters {
|
|||
|
||||
private final RateLimiter checkAccountExistenceLimiter;
|
||||
|
||||
private final AtomicReference<CardinalityRateLimiter> unsealedSenderCardinalityLimiter;
|
||||
private final AtomicReference<RateLimiter> unsealedIpLimiter;
|
||||
private final AtomicReference<RateLimiter> rateLimitResetLimiter;
|
||||
private final AtomicReference<RateLimiter> recaptchaChallengeAttemptLimiter;
|
||||
private final AtomicReference<RateLimiter> recaptchaChallengeSuccessLimiter;
|
||||
private final AtomicReference<RateLimiter> pushChallengeAttemptLimiter;
|
||||
private final AtomicReference<RateLimiter> pushChallengeSuccessLimiter;
|
||||
private final AtomicReference<RateLimiter> dailyPreKeysLimiter;
|
||||
|
||||
private final FaultTolerantRedisCluster cacheCluster;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfig;
|
||||
|
||||
public RateLimiters(RateLimitsConfiguration config, DynamicConfigurationManager<DynamicConfiguration> dynamicConfig, FaultTolerantRedisCluster cacheCluster) {
|
||||
this.cacheCluster = cacheCluster;
|
||||
this.dynamicConfig = dynamicConfig;
|
||||
|
||||
public RateLimiters(RateLimitsConfiguration config, FaultTolerantRedisCluster cacheCluster) {
|
||||
this.smsDestinationLimiter = new RateLimiter(cacheCluster, "smsDestination",
|
||||
config.getSmsDestination().getBucketSize(),
|
||||
config.getSmsDestination().getLeakRatePerMinute());
|
||||
|
@ -132,93 +111,6 @@ public class RateLimiters {
|
|||
this.checkAccountExistenceLimiter = new RateLimiter(cacheCluster, "checkAccountExistence",
|
||||
config.getCheckAccountExistence().getBucketSize(),
|
||||
config.getCheckAccountExistence().getLeakRatePerMinute());
|
||||
|
||||
this.dailyPreKeysLimiter = new AtomicReference<>(createDailyPreKeysLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getDailyPreKeys()));
|
||||
|
||||
this.unsealedSenderCardinalityLimiter = new AtomicReference<>(createUnsealedSenderCardinalityLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getUnsealedSenderNumber()));
|
||||
this.unsealedIpLimiter = new AtomicReference<>(createUnsealedIpLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getUnsealedSenderIp()));
|
||||
|
||||
this.rateLimitResetLimiter = new AtomicReference<>(
|
||||
createRateLimitResetLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getRateLimitReset()));
|
||||
|
||||
this.recaptchaChallengeAttemptLimiter = new AtomicReference<>(createRecaptchaChallengeAttemptLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getRecaptchaChallengeAttempt()));
|
||||
this.recaptchaChallengeSuccessLimiter = new AtomicReference<>(createRecaptchaChallengeSuccessLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getRecaptchaChallengeSuccess()));
|
||||
this.pushChallengeAttemptLimiter = new AtomicReference<>(createPushChallengeAttemptLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getPushChallengeAttempt()));
|
||||
this.pushChallengeSuccessLimiter = new AtomicReference<>(createPushChallengeSuccessLimiter(cacheCluster, dynamicConfig.getConfiguration().getLimits().getPushChallengeSuccess()));
|
||||
}
|
||||
|
||||
public CardinalityRateLimiter getUnsealedSenderCardinalityLimiter() {
|
||||
CardinalityRateLimitConfiguration currentConfiguration = dynamicConfig.getConfiguration().getLimits().getUnsealedSenderNumber();
|
||||
|
||||
return this.unsealedSenderCardinalityLimiter.updateAndGet(rateLimiter -> {
|
||||
if (rateLimiter.hasConfiguration(currentConfiguration)) {
|
||||
return rateLimiter;
|
||||
} else {
|
||||
return createUnsealedSenderCardinalityLimiter(cacheCluster, currentConfiguration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RateLimiter getUnsealedIpLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
unsealedIpLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getUnsealedSenderIp(),
|
||||
this::createUnsealedIpLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRateLimitResetLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
rateLimitResetLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getRateLimitReset(),
|
||||
this::createRateLimitResetLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRecaptchaChallengeAttemptLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
recaptchaChallengeAttemptLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getRecaptchaChallengeAttempt(),
|
||||
this::createRecaptchaChallengeAttemptLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getRecaptchaChallengeSuccessLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
recaptchaChallengeSuccessLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getRecaptchaChallengeSuccess(),
|
||||
this::createRecaptchaChallengeSuccessLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getPushChallengeAttemptLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
pushChallengeAttemptLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getPushChallengeAttempt(),
|
||||
this::createPushChallengeAttemptLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getPushChallengeSuccessLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
pushChallengeSuccessLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getPushChallengeSuccess(),
|
||||
this::createPushChallengeSuccessLimiter);
|
||||
}
|
||||
|
||||
public RateLimiter getDailyPreKeysLimiter() {
|
||||
return updateAndGetRateLimiter(
|
||||
dailyPreKeysLimiter,
|
||||
dynamicConfig.getConfiguration().getLimits().getDailyPreKeys(),
|
||||
this::createDailyPreKeysLimiter);
|
||||
}
|
||||
|
||||
private RateLimiter updateAndGetRateLimiter(final AtomicReference<RateLimiter> rateLimiter,
|
||||
RateLimitConfiguration currentConfiguration,
|
||||
BiFunction<FaultTolerantRedisCluster, RateLimitConfiguration, RateLimiter> rateLimitFactory) {
|
||||
|
||||
return rateLimiter.updateAndGet(limiter -> {
|
||||
if (limiter.hasConfiguration(currentConfiguration)) {
|
||||
return limiter;
|
||||
} else {
|
||||
return rateLimitFactory.apply(cacheCluster, currentConfiguration);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RateLimiter getAllocateDeviceLimiter() {
|
||||
|
@ -296,43 +188,4 @@ public class RateLimiters {
|
|||
public RateLimiter getCheckAccountExistenceLimiter() {
|
||||
return checkAccountExistenceLimiter;
|
||||
}
|
||||
|
||||
private CardinalityRateLimiter createUnsealedSenderCardinalityLimiter(FaultTolerantRedisCluster cacheCluster, CardinalityRateLimitConfiguration configuration) {
|
||||
return new CardinalityRateLimiter(cacheCluster, "unsealedSender", configuration.getTtl(), configuration.getMaxCardinality());
|
||||
}
|
||||
|
||||
private RateLimiter createUnsealedIpLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration)
|
||||
{
|
||||
return createLimiter(cacheCluster, configuration, "unsealedIp");
|
||||
}
|
||||
|
||||
public RateLimiter createRateLimitResetLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "rateLimitReset");
|
||||
}
|
||||
|
||||
public RateLimiter createRecaptchaChallengeAttemptLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "recaptchaChallengeAttempt");
|
||||
}
|
||||
|
||||
public RateLimiter createRecaptchaChallengeSuccessLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "recaptchaChallengeSuccess");
|
||||
}
|
||||
|
||||
public RateLimiter createPushChallengeAttemptLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "pushChallengeAttempt");
|
||||
}
|
||||
|
||||
public RateLimiter createPushChallengeSuccessLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "pushChallengeSuccess");
|
||||
}
|
||||
|
||||
public RateLimiter createDailyPreKeysLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration) {
|
||||
return createLimiter(cacheCluster, configuration, "dailyPreKeys");
|
||||
}
|
||||
|
||||
private RateLimiter createLimiter(FaultTolerantRedisCluster cacheCluster, RateLimitConfiguration configuration, String name) {
|
||||
return new RateLimiter(cacheCluster, name,
|
||||
configuration.getBucketSize(),
|
||||
configuration.getLeakRatePerMinute());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.whispersystems.textsecuregcm.util.Util;
|
|||
|
||||
public class UnsealedSenderRateLimiter {
|
||||
|
||||
private final RateLimiters rateLimiters;
|
||||
private final DynamicRateLimiters rateLimiters;
|
||||
private final FaultTolerantRedisCluster rateLimitCluster;
|
||||
private final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager;
|
||||
private final RateLimitResetMetricsManager metricsManager;
|
||||
|
@ -37,7 +37,7 @@ public class UnsealedSenderRateLimiter {
|
|||
private static final long RATE_LIMITED_ACCOUNTS_HLL_TTL_SECONDS = Duration.days(1).toSeconds();
|
||||
|
||||
|
||||
public UnsealedSenderRateLimiter(final RateLimiters rateLimiters,
|
||||
public UnsealedSenderRateLimiter(final DynamicRateLimiters rateLimiters,
|
||||
final FaultTolerantRedisCluster rateLimitCluster,
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager,
|
||||
final RateLimitResetMetricsManager metricsManager) {
|
||||
|
|
|
@ -26,12 +26,12 @@ class PreKeyRateLimiterTest {
|
|||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
final DynamicRateLimiters rateLimiters = mock(DynamicRateLimiters.class);
|
||||
|
||||
dailyPreKeyLimiter = mock(RateLimiter.class);
|
||||
when(rateLimiters.getDailyPreKeysLimiter()).thenReturn(dailyPreKeyLimiter);
|
||||
|
||||
final DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||
rateLimitChallengeConfiguration = mock(DynamicRateLimitChallengeConfiguration.class);
|
||||
final DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class RateLimitChallengeManagerTest {
|
|||
private PreKeyRateLimiter preKeyRateLimiter;
|
||||
private UnsealedSenderRateLimiter unsealedSenderRateLimiter;
|
||||
private DynamicRateLimitChallengeConfiguration rateLimitChallengeConfiguration;
|
||||
private RateLimiters rateLimiters;
|
||||
private DynamicRateLimiters rateLimiters;
|
||||
|
||||
private RateLimitChallengeManager rateLimitChallengeManager;
|
||||
|
||||
|
@ -45,9 +45,9 @@ class RateLimitChallengeManagerTest {
|
|||
recaptchaClient = mock(RecaptchaClient.class);
|
||||
preKeyRateLimiter = mock(PreKeyRateLimiter.class);
|
||||
unsealedSenderRateLimiter = mock(UnsealedSenderRateLimiter.class);
|
||||
rateLimiters = mock(RateLimiters.class);
|
||||
rateLimiters = mock(DynamicRateLimiters.class);
|
||||
|
||||
final DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||
final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||
final DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
|
||||
rateLimitChallengeConfiguration = mock(DynamicRateLimitChallengeConfiguration.class);
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class UnsealedSenderRateLimiterTest {
|
|||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
|
||||
final RateLimiters rateLimiters = mock(RateLimiters.class);
|
||||
final DynamicRateLimiters rateLimiters = mock(DynamicRateLimiters.class);
|
||||
final CardinalityRateLimiter cardinalityRateLimiter =
|
||||
new CardinalityRateLimiter(REDIS_CLUSTER_EXTENSION.getRedisCluster(), "test", Duration.ofDays(1), 1);
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ import org.whispersystems.textsecuregcm.configuration.RateLimitsConfiguration.Ra
|
|||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicConfiguration;
|
||||
import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicRateLimitsConfiguration;
|
||||
import org.whispersystems.textsecuregcm.limits.CardinalityRateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.DynamicRateLimiters;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.storage.DynamicConfigurationManager;
|
||||
|
||||
|
@ -36,7 +36,7 @@ class DynamicRateLimitsTest {
|
|||
|
||||
@Test
|
||||
void testUnchangingConfiguration() {
|
||||
RateLimiters rateLimiters = new RateLimiters(new RateLimitsConfiguration(), dynamicConfig, redisCluster);
|
||||
DynamicRateLimiters rateLimiters = new DynamicRateLimiters(redisCluster, dynamicConfig);
|
||||
|
||||
RateLimiter limiter = rateLimiters.getUnsealedIpLimiter();
|
||||
|
||||
|
@ -64,7 +64,7 @@ class DynamicRateLimitsTest {
|
|||
|
||||
when(dynamicConfig.getConfiguration()).thenReturn(configuration);
|
||||
|
||||
RateLimiters rateLimiters = new RateLimiters(new RateLimitsConfiguration(), dynamicConfig, redisCluster);
|
||||
DynamicRateLimiters rateLimiters = new DynamicRateLimiters(redisCluster, dynamicConfig);
|
||||
|
||||
CardinalityRateLimiter limiter = rateLimiters.getUnsealedSenderCardinalityLimiter();
|
||||
|
||||
|
|
Loading…
Reference in New Issue