Add a "critical" warning tier for primary devices missing PQ keys

This commit is contained in:
Jon Chambers
2025-03-05 08:51:10 -05:00
committed by GitHub
parent 8955e31a1e
commit 8517eef3fe
3 changed files with 114 additions and 22 deletions

View File

@@ -982,7 +982,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
webSocketEnvironment.jersey().register(new VirtualExecutorServiceProvider("managed-async-websocket-virtual-thread-"));
webSocketEnvironment.setAuthenticator(new WebSocketAccountAuthenticator(accountAuthenticator, new AccountPrincipalSupplier(accountsManager)));
webSocketEnvironment.setAuthenticatedWebSocketUpgradeFilter(new IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter(
config.idlePrimaryDeviceReminderConfiguration().minIdleDuration(), Clock.systemUTC()));
keysManager, config.idlePrimaryDeviceReminderConfiguration().minIdleDuration(), Clock.systemUTC()));
webSocketEnvironment.setConnectListener(
new AuthenticatedConnectListener(receiptSender, messagesManager, messageMetrics, pushNotificationManager,
pushNotificationScheduler, webSocketConnectionEventManager, websocketScheduledExecutor,

View File

@@ -6,8 +6,14 @@
package org.whispersystems.textsecuregcm.auth;
import com.google.common.annotations.VisibleForTesting;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeRequest;
import org.eclipse.jetty.websocket.server.JettyServerUpgradeResponse;
import org.whispersystems.textsecuregcm.identity.IdentityType;
import org.whispersystems.textsecuregcm.metrics.MetricsUtil;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.KeysManager;
import org.whispersystems.websocket.ReusableAuth;
import org.whispersystems.websocket.auth.AuthenticatedWebSocketUpgradeFilter;
import java.time.Clock;
@@ -17,6 +23,8 @@ import java.time.Instant;
public class IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter implements
AuthenticatedWebSocketUpgradeFilter<AuthenticatedDevice> {
private final KeysManager keysManager;
private final Duration minIdleDuration;
private final Clock clock;
@@ -26,7 +34,25 @@ public class IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter implements
@VisibleForTesting
static final String IDLE_PRIMARY_DEVICE_ALERT = "idle-primary-device";
public IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter(final Duration minIdleDuration, final Clock clock) {
@VisibleForTesting
static final String CRITICAL_IDLE_PRIMARY_DEVICE_ALERT = "critical-idle-primary-device";
@VisibleForTesting
static final Duration PQ_KEY_CHECK_THRESHOLD = Duration.ofDays(120);
private static final Counter IDLE_PRIMARY_WARNING_COUNTER = Metrics.counter(
MetricsUtil.name(IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter.class, "idlePrimaryDeviceWarning"),
"critical", "false");
private static final Counter CRITICAL_IDLE_PRIMARY_WARNING_COUNTER = Metrics.counter(
MetricsUtil.name(IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter.class, "idlePrimaryDeviceWarning"),
"critical", "true");
public IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter(final KeysManager keysManager,
final Duration minIdleDuration,
final Clock clock) {
this.keysManager = keysManager;
this.minIdleDuration = minIdleDuration;
this.clock = clock;
}
@@ -44,8 +70,15 @@ public class IdlePrimaryDeviceAuthenticatedWebSocketUpgradeFilter implements
final Instant primaryDeviceLastSeen =
Instant.ofEpochMilli(authenticatedDevice.getAccount().getPrimaryDevice().getLastSeen());
if (primaryDeviceLastSeen.isBefore(clock.instant().minus(minIdleDuration))) {
if (primaryDeviceLastSeen.isBefore(clock.instant().minus(PQ_KEY_CHECK_THRESHOLD)) &&
keysManager.getLastResort(authenticatedDevice.getAccount().getIdentifier(IdentityType.ACI), Device.PRIMARY_ID)
.join().isEmpty()) {
response.addHeader(ALERT_HEADER, CRITICAL_IDLE_PRIMARY_DEVICE_ALERT);
CRITICAL_IDLE_PRIMARY_WARNING_COUNTER.increment();
} else if (primaryDeviceLastSeen.isBefore(clock.instant().minus(minIdleDuration))) {
response.addHeader(ALERT_HEADER, IDLE_PRIMARY_DEVICE_ALERT);
IDLE_PRIMARY_WARNING_COUNTER.increment();
}
});
}