Skip to content

Commit 2f59930

Browse files
committed
fail fast keysetkey out of sync. Currently still using fixed interval
1 parent bb20946 commit 2f59930

4 files changed

Lines changed: 39 additions & 5 deletions

File tree

conf/default-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"optout_inmem_cache": false,
3838
"enclave_platform": null,
3939
"failure_shutdown_wait_hours": 120,
40+
"keyset_key_shutdown_hours": 2,
4041
"sharing_token_expiry_seconds": 2592000,
4142
"operator_type": "public",
4243
"enable_remote_config": true,

src/main/java/com/uid2/operator/Main.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public Main(Vertx vertx, JsonObject config) throws Exception {
114114
this.clientSideTokenGenerate = config.getBoolean(Const.Config.EnableClientSideTokenGenerate, false);
115115
this.validateServiceLinks = config.getBoolean(Const.Config.ValidateServiceLinks, false);
116116
this.encryptedCloudFilesEnabled = config.getBoolean(Const.Config.EncryptedFiles, false);
117-
this.shutdownHandler = new OperatorShutdownHandler(Duration.ofHours(12), Duration.ofHours(config.getInteger(Const.Config.SaltsExpiredShutdownHours, 12)), Clock.systemUTC(), new ShutdownService());
117+
this.shutdownHandler = new OperatorShutdownHandler(Duration.ofHours(12), Duration.ofHours(config.getInteger(Const.Config.SaltsExpiredShutdownHours, 12)), Duration.ofHours(config.getInteger(Const.Config.KeysetKeyShutdownHours, 2)), Clock.systemUTC(), new ShutdownService());
118118
this.uidInstanceIdProvider = new UidInstanceIdProvider(config);
119119

120120
String coreAttestUrl = this.config.getString(Const.Config.CoreAttestUrlProp);
@@ -243,7 +243,8 @@ public Main(Vertx vertx, JsonObject config) throws Exception {
243243
}
244244

245245
private KeyManager getKeyManager() {
246-
return new KeyManager(this.keysetKeyStore, this.keysetProvider);
246+
return new KeyManager(this.keysetKeyStore, this.keysetProvider,
247+
hasKeys -> shutdownHandler.handleKeysetKeyRefreshResponse(hasKeys));
247248
}
248249

249250
public static void recordStartupComplete() {

src/main/java/com/uid2/operator/model/KeyManager.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313
import java.util.Comparator;
1414
import java.util.List;
1515
import java.util.Map;
16+
import java.util.function.Consumer;
1617
import java.util.stream.Collectors;
1718

1819
public class KeyManager {
1920
private static final Logger LOGGER = LoggerFactory.getLogger(UIDOperatorVerticle.class);
2021
private final IKeysetKeyStore keysetKeyStore;
2122
private final RotatingKeysetProvider keysetProvider;
23+
private final Consumer<Boolean> keyAvailabilityHandler;
2224

23-
public KeyManager(IKeysetKeyStore keysetKeyStore, RotatingKeysetProvider keysetProvider) {
25+
public KeyManager(IKeysetKeyStore keysetKeyStore, RotatingKeysetProvider keysetProvider, Consumer<Boolean> keyAvailabilityHandler) {
2426
this.keysetKeyStore = keysetKeyStore;
2527
this.keysetProvider = keysetProvider;
28+
this.keyAvailabilityHandler = keyAvailabilityHandler;
2629
}
2730

2831
public KeyManagerSnapshot getKeyManagerSnapshot(int siteId) {
@@ -107,6 +110,7 @@ public KeysetKey getMasterKey() {
107110
public KeysetKey getMasterKey(Instant asOf) {
108111
KeysetKey key = this.keysetKeyStore.getSnapshot().getActiveKey(Const.Data.MasterKeysetId, asOf);
109112
if (key == null) {
113+
if (keyAvailabilityHandler != null) keyAvailabilityHandler.accept(false);
110114
throw new NoActiveKeyException(String.format("Cannot get a master key with keyset ID %d.", Const.Data.MasterKeysetId));
111115
}
112116
return key;
@@ -119,6 +123,7 @@ public KeysetKey getRefreshKey() {
119123
public KeysetKey getRefreshKey(Instant asOf) {
120124
KeysetKey key = this.keysetKeyStore.getSnapshot().getActiveKey(Const.Data.RefreshKeysetId, asOf);
121125
if (key == null) {
126+
if (keyAvailabilityHandler != null) keyAvailabilityHandler.accept(false);
122127
throw new NoActiveKeyException(String.format("Cannot get a refresh key with keyset ID %d.", Const.Data.RefreshKeysetId));
123128
}
124129
return key;

src/main/java/com/uid2/operator/vertx/OperatorShutdownHandler.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.uid2.operator.service.ShutdownService;
44
import com.uid2.shared.attest.AttestationResponseCode;
5-
import lombok.extern.java.Log;
65
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
87
import software.amazon.awssdk.utils.Pair;
@@ -16,17 +15,22 @@
1615
public class OperatorShutdownHandler {
1716
private static final Logger LOGGER = LoggerFactory.getLogger(OperatorShutdownHandler.class);
1817
private static final int SALT_FAILURE_LOG_INTERVAL_MINUTES = 10;
18+
private static final int KEYSET_KEY_FAILURE_LOG_INTERVAL_MINUTES = 10;
1919
private final Duration attestShutdownWaitTime;
2020
private final Duration saltShutdownWaitTime;
21+
private final Duration keysetKeyShutdownWaitTime;
2122
private final AtomicReference<Instant> attestFailureStartTime = new AtomicReference<>(null);
2223
private final AtomicReference<Instant> saltFailureStartTime = new AtomicReference<>(null);
24+
private final AtomicReference<Instant> keysetKeyFailureStartTime = new AtomicReference<>(null);
2325
private final AtomicReference<Instant> lastSaltFailureLogTime = new AtomicReference<>(null);
26+
private final AtomicReference<Instant> lastKeysetKeyFailureLogTime = new AtomicReference<>(null);
2427
private final Clock clock;
2528
private final ShutdownService shutdownService;
2629

27-
public OperatorShutdownHandler(Duration attestShutdownWaitTime, Duration saltShutdownWaitTime, Clock clock, ShutdownService shutdownService) {
30+
public OperatorShutdownHandler(Duration attestShutdownWaitTime, Duration saltShutdownWaitTime, Duration keysetKeyShutdownWaitTime, Clock clock, ShutdownService shutdownService) {
2831
this.attestShutdownWaitTime = attestShutdownWaitTime;
2932
this.saltShutdownWaitTime = saltShutdownWaitTime;
33+
this.keysetKeyShutdownWaitTime = keysetKeyShutdownWaitTime;
3034
this.clock = clock;
3135
this.shutdownService = shutdownService;
3236
}
@@ -54,6 +58,29 @@ public void logSaltFailureAtInterval() {
5458
}
5559
}
5660

61+
public void handleKeysetKeyRefreshResponse(Boolean success) {
62+
if (success) {
63+
keysetKeyFailureStartTime.set(null);
64+
} else {
65+
logKeysetKeyFailureAtInterval();
66+
Instant t = keysetKeyFailureStartTime.get();
67+
if (t == null) {
68+
keysetKeyFailureStartTime.set(clock.instant());
69+
} else if (Duration.between(t, clock.instant()).compareTo(this.keysetKeyShutdownWaitTime) > 0) {
70+
LOGGER.error("keyset keys have been failing to sync for too long. shutting down operator");
71+
this.shutdownService.Shutdown(1);
72+
}
73+
}
74+
}
75+
76+
public void logKeysetKeyFailureAtInterval() {
77+
Instant t = lastKeysetKeyFailureLogTime.get();
78+
if (t == null || clock.instant().isAfter(t.plus(KEYSET_KEY_FAILURE_LOG_INTERVAL_MINUTES, ChronoUnit.MINUTES))) {
79+
LOGGER.error("keyset keys sync failing");
80+
lastKeysetKeyFailureLogTime.set(Instant.now());
81+
}
82+
}
83+
5784
public void handleAttestResponse(Pair<AttestationResponseCode, String> response) {
5885
if (response.left() == AttestationResponseCode.AttestationFailure) {
5986
LOGGER.error("core attestation failed with AttestationFailure, shutting down operator, core response: {}", response.right());

0 commit comments

Comments
 (0)