Skip to content

Commit 7c8cce6

Browse files
committed
only take the jwt_auth_failures writelock if strictly necessary, default to readlock
1 parent 8268572 commit 7c8cce6

1 file changed

Lines changed: 27 additions & 25 deletions

File tree

crates/signer/src/service.rs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -273,38 +273,40 @@ async fn jwt_auth(
273273
/// Checks if the incoming request needs to be rate limited due to previous JWT
274274
/// authentication failures
275275
fn check_jwt_rate_limit(state: &SigningState, client_ip: &IpAddr) -> Result<(), SignerModuleError> {
276-
let mut failures = state.jwt_auth_failures.write();
276+
let failures = state.jwt_auth_failures.read();
277277

278278
// Ignore clients that don't have any failures
279-
if let Some(failure_info) = failures.get(client_ip) {
280-
// If the last failure was more than the timeout ago, remove this entry so it's
281-
// eligible again
282-
let elapsed = failure_info.last_failure.elapsed();
283-
if elapsed > state.jwt_auth_fail_timeout {
284-
debug!("Removing {client_ip} from JWT auth failure list");
285-
failures.remove(client_ip);
286-
return Ok(());
287-
}
279+
let Some(failure_info) = failures.get(client_ip) else {
280+
debug!("Client {client_ip} has no JWT auth failures, no rate limit applied");
281+
return Ok(());
282+
};
288283

289-
// If the failure threshold hasn't been met yet, don't rate limit
290-
if failure_info.failure_count < state.jwt_auth_fail_limit {
291-
debug!(
292-
"Client {client_ip} has {}/{} JWT auth failures, no rate limit applied",
293-
failure_info.failure_count, state.jwt_auth_fail_limit
294-
);
295-
return Ok(());
296-
}
284+
let elapsed = failure_info.last_failure.elapsed();
285+
286+
// If the last failure was more than the timeout ago, remove this entry so it's
287+
// eligible again
288+
if elapsed > state.jwt_auth_fail_timeout {
289+
drop(failures);
290+
debug!("Removing {client_ip} from JWT auth failure list");
291+
state.jwt_auth_failures.write().remove(client_ip);
292+
return Ok(());
293+
}
297294

298-
// Rate limit the request
299-
let remaining = state.jwt_auth_fail_timeout.saturating_sub(elapsed);
300-
warn!(
301-
"Client {client_ip} is rate limited for {remaining:?} more seconds due to JWT auth failures"
295+
// If the failure threshold hasn't been met yet, don't rate limit
296+
if failure_info.failure_count < state.jwt_auth_fail_limit {
297+
debug!(
298+
"Client {client_ip} has {}/{} JWT auth failures, no rate limit applied",
299+
failure_info.failure_count, state.jwt_auth_fail_limit
302300
);
303-
return Err(SignerModuleError::RateLimited(remaining.as_secs_f64()));
301+
return Ok(());
304302
}
305303

306-
debug!("Client {client_ip} has no JWT auth failures, no rate limit applied");
307-
Ok(())
304+
// Rate limit the request
305+
let remaining = state.jwt_auth_fail_timeout.saturating_sub(elapsed);
306+
warn!(
307+
"Client {client_ip} is rate limited for {remaining:?} more seconds due to JWT auth failures"
308+
);
309+
Err(SignerModuleError::RateLimited(remaining.as_secs_f64()))
308310
}
309311

310312
/// Checks if a request can successfully authenticate with the JWT secret

0 commit comments

Comments
 (0)