Measure rate limit challenge responses by platform
This commit is contained in:
parent
a6182acc9c
commit
99eda80a78
|
@ -15,21 +15,31 @@ import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import io.micrometer.core.instrument.Metrics;
|
||||||
|
import io.micrometer.core.instrument.Tag;
|
||||||
|
import io.micrometer.core.instrument.Tags;
|
||||||
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
import org.whispersystems.textsecuregcm.auth.AuthenticatedAccount;
|
||||||
import org.whispersystems.textsecuregcm.entities.AnswerChallengeRequest;
|
import org.whispersystems.textsecuregcm.entities.AnswerChallengeRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.AnswerPushChallengeRequest;
|
import org.whispersystems.textsecuregcm.entities.AnswerPushChallengeRequest;
|
||||||
import org.whispersystems.textsecuregcm.entities.AnswerRecaptchaChallengeRequest;
|
import org.whispersystems.textsecuregcm.entities.AnswerRecaptchaChallengeRequest;
|
||||||
import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager;
|
import org.whispersystems.textsecuregcm.limits.RateLimitChallengeManager;
|
||||||
|
import org.whispersystems.textsecuregcm.metrics.UserAgentTagUtil;
|
||||||
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
||||||
import org.whispersystems.textsecuregcm.util.ForwardedIpUtil;
|
import org.whispersystems.textsecuregcm.util.ForwardedIpUtil;
|
||||||
|
|
||||||
|
import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
|
||||||
|
|
||||||
@Path("/v1/challenge")
|
@Path("/v1/challenge")
|
||||||
public class ChallengeController {
|
public class ChallengeController {
|
||||||
|
|
||||||
private final RateLimitChallengeManager rateLimitChallengeManager;
|
private final RateLimitChallengeManager rateLimitChallengeManager;
|
||||||
|
|
||||||
|
private static final String CHALLENGE_RESPONSE_COUNTER_NAME = name(ChallengeController.class, "challengeResponse");
|
||||||
|
private static final String CHALLENGE_TYPE_TAG = "type";
|
||||||
|
|
||||||
public ChallengeController(final RateLimitChallengeManager rateLimitChallengeManager) {
|
public ChallengeController(final RateLimitChallengeManager rateLimitChallengeManager) {
|
||||||
this.rateLimitChallengeManager = rateLimitChallengeManager;
|
this.rateLimitChallengeManager = rateLimitChallengeManager;
|
||||||
}
|
}
|
||||||
|
@ -40,16 +50,20 @@ public class ChallengeController {
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response handleChallengeResponse(@Auth final AuthenticatedAccount auth,
|
public Response handleChallengeResponse(@Auth final AuthenticatedAccount auth,
|
||||||
@Valid final AnswerChallengeRequest answerRequest,
|
@Valid final AnswerChallengeRequest answerRequest,
|
||||||
@HeaderParam("X-Forwarded-For") String forwardedFor) throws RetryLaterException {
|
@HeaderParam("X-Forwarded-For") final String forwardedFor,
|
||||||
|
@HeaderParam(HttpHeaders.USER_AGENT) final String userAgent) throws RetryLaterException {
|
||||||
|
|
||||||
|
Tags tags = Tags.of(UserAgentTagUtil.getPlatformTag(userAgent));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (answerRequest instanceof AnswerPushChallengeRequest) {
|
if (answerRequest instanceof final AnswerPushChallengeRequest pushChallengeRequest) {
|
||||||
final AnswerPushChallengeRequest pushChallengeRequest = (AnswerPushChallengeRequest) answerRequest;
|
tags = tags.and(CHALLENGE_TYPE_TAG, "push");
|
||||||
|
|
||||||
rateLimitChallengeManager.answerPushChallenge(auth.getAccount(), pushChallengeRequest.getChallenge());
|
rateLimitChallengeManager.answerPushChallenge(auth.getAccount(), pushChallengeRequest.getChallenge());
|
||||||
} else if (answerRequest instanceof AnswerRecaptchaChallengeRequest) {
|
} else if (answerRequest instanceof AnswerRecaptchaChallengeRequest) {
|
||||||
try {
|
tags = tags.and(CHALLENGE_TYPE_TAG, "recaptcha");
|
||||||
|
|
||||||
|
try {
|
||||||
final AnswerRecaptchaChallengeRequest recaptchaChallengeRequest = (AnswerRecaptchaChallengeRequest) answerRequest;
|
final AnswerRecaptchaChallengeRequest recaptchaChallengeRequest = (AnswerRecaptchaChallengeRequest) answerRequest;
|
||||||
final String mostRecentProxy = ForwardedIpUtil.getMostRecentProxy(forwardedFor).orElseThrow();
|
final String mostRecentProxy = ForwardedIpUtil.getMostRecentProxy(forwardedFor).orElseThrow();
|
||||||
|
|
||||||
|
@ -59,9 +73,13 @@ public class ChallengeController {
|
||||||
} catch (final NoSuchElementException e) {
|
} catch (final NoSuchElementException e) {
|
||||||
return Response.status(400).build();
|
return Response.status(400).build();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
tags = tags.and(CHALLENGE_TYPE_TAG, "unrecognized");
|
||||||
}
|
}
|
||||||
} catch (final RateLimitExceededException e) {
|
} catch (final RateLimitExceededException e) {
|
||||||
throw new RetryLaterException(e);
|
throw new RetryLaterException(e);
|
||||||
|
} finally {
|
||||||
|
Metrics.counter(CHALLENGE_RESPONSE_COUNTER_NAME, tags).increment();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.status(200).build();
|
return Response.status(200).build();
|
||||||
|
|
Loading…
Reference in New Issue