Skip to content

Commit 5b81242

Browse files
authored
UID2-1983 ensure first key in a keyset is immediately active (#278)
1 parent 3e59bae commit 5b81242

File tree

3 files changed

+42
-28
lines changed

3 files changed

+42
-28
lines changed

src/main/java/com/uid2/admin/managers/KeysetManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public int getNextKeysetId() {
133133
return KeysetManager.getMaxKeyset(this.keysetProvider.getSnapshot().getAllKeysets()) + 1;
134134
}
135135

136-
public AdminKeyset createAndAddDefaultKeyset(Integer siteId) throws Exception{
136+
private AdminKeyset createAndAddDefaultKeyset(Integer siteId) throws Exception{
137137
if(!enableKeysets) return null;
138138

139139
this.keysetProvider.loadContent();

src/main/java/com/uid2/admin/vertx/service/EncryptionKeyService.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ else if(siteId == Const.Data.AdvertisingTokenSiteId) {
554554
return keyset.getKeysetId();
555555
}
556556

557-
private int getSiteId(int keysetId) throws Exception {
557+
private int getSiteId(int keysetId) {
558558
Map<Integer, AdminKeyset> currentKeysets = keysetProvider.getSnapshot().getAllKeysets();
559559
return currentKeysets.get(keysetId).getSiteId();
560560
}
@@ -563,22 +563,24 @@ private List<KeysetKey> addKeysetKeys(Iterable<Integer> keysetIds, Duration acti
563563
throws Exception {
564564
final Instant now = clock.now();
565565

566-
final List<KeysetKey> keys = this.keysetKeyProvider.getSnapshot().getAllKeysetKeys().stream()
566+
final List<KeysetKey> keysetKeys = this.keysetKeyProvider.getSnapshot().getAllKeysetKeys();
567+
final List<KeysetKey> keys = keysetKeys.stream()
567568
.sorted(Comparator.comparingInt(KeysetKey::getId))
568569
.filter(k -> isWithinCutOffTime(k, now, isDuringRotation))
569570
.collect(Collectors.toList());
570571

571-
572-
int maxKeyId = MaxKeyUtil.getMaxKeysetKeyId(this.keysetKeyProvider.getSnapshot().getAllKeysetKeys(),
573-
this.keysetKeyProvider.getMetadata().getInteger("max_key_id"));
572+
int maxKeyId = MaxKeyUtil.getMaxKeysetKeyId(keysetKeys, this.keysetKeyProvider.getMetadata().getInteger("max_key_id"));
574573

575574
final List<KeysetKey> addedKeys = new ArrayList<>();
576575

577576
for (Integer keysetId : keysetIds) {
578577
++maxKeyId;
579578
final byte[] secret = keyGenerator.generateRandomKey(32);
580579
final Instant created = now;
581-
final Instant activates = created.plusSeconds(activatesIn.getSeconds());
580+
581+
final boolean isAddingFirstKeyForKeyset = (!isDuringRotation && keysetKeys.stream().noneMatch(key -> key.getKeysetId() == keysetId));
582+
583+
final Instant activates = isAddingFirstKeyForKeyset ? created : created.plusSeconds(activatesIn.getSeconds());
582584
final Instant expires = activates.plusSeconds(expiresAfter.getSeconds());
583585
final KeysetKey key = new KeysetKey(maxKeyId, secret, created, activates, expires, keysetId);
584586
keys.add(key);
@@ -655,8 +657,7 @@ private boolean isWithinCutOffTime(KeysetKey key, Instant now, boolean duringRot
655657
if (!(filterKeyOverCutOffTime && duringRotation)) {
656658
return true;
657659
}
658-
Duration cutoffTime = siteKeyRotationCutOffTime;
659-
return now.compareTo(key.getExpires().plus(cutoffTime.toDays(), ChronoUnit.DAYS)) < 0;
660+
return now.compareTo(key.getExpires().plus(siteKeyRotationCutOffTime.toDays(), ChronoUnit.DAYS)) < 0;
660661
}
661662

662663
private void loadAllContent() throws Exception {

src/test/java/com/uid2/admin/vertx/EncryptionKeyServiceTest.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class EncryptionKeyServiceTest extends ServiceTestBase {
4040
private static final long A_HUNDRED_DAYS_IN_SECONDS = 8640000L;
4141
private static final int MAX_KEY_ID = 777;
4242
private static final boolean FILTER_KEY_OVER_CUT_OFF_DAYS = true;
43-
private Clock clock = mock(Clock.class);
43+
private final Clock clock = mock(Clock.class);
4444
private EncryptionKeyService keyService = null;
4545

4646
@BeforeEach
@@ -80,11 +80,6 @@ private void assertSiteKeyActivation(EncryptionKey key, Instant generatedTime) {
8080
key.getCreated(), key.getActivates(), key.getExpires());
8181
}
8282

83-
private void assertSiteKeyActivation(KeysetKey key, Instant generatedTime) {
84-
assertKeyActivation(generatedTime, SITE_KEY_ACTIVATES_IN_SECONDS, SITE_KEY_EXPIRES_AFTER_SECONDS,
85-
key.getCreated(), key.getActivates(), key.getExpires());
86-
}
87-
8883
private void checkEncryptionKeyResponse(EncryptionKey[] expectedKeys, Object[] actualKeys) {
8984
assertEquals(expectedKeys.length, actualKeys.length);
9085
for (int i = 0; i < expectedKeys.length; ++i) {
@@ -147,7 +142,7 @@ void addSiteKey() throws Exception {
147142

148143
@Test
149144
void addSiteKeyAddsKeysetAndKey() throws Exception {
150-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
145+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
151146
put(1, new AdminKeyset(1, 2, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
152147
}};
153148
setAdminKeysets(keysets);
@@ -157,13 +152,13 @@ void addSiteKeyAddsKeysetAndKey() throws Exception {
157152

158153
AdminKeyset expected = new AdminKeyset(4, 5, "", null, Instant.now().getEpochSecond(), true, true, new HashSet<>());
159154
assertNotNull(keysets.get(4));
160-
assertTrue(keysets.get(4).equals(expected));
155+
assertEquals(expected, keysets.get(4));
161156
verify(keysetKeyStoreWriter).upload(collectionOfSize(1), eq(124));
162157
}
163158

164159
@Test
165160
void addSiteKeyUsesKeysetAndAddsKey() throws Exception {
166-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
161+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
167162
put(1, new AdminKeyset(1, 5, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
168163
}};
169164
setAdminKeysets(keysets);
@@ -177,21 +172,41 @@ void addSiteKeyUsesKeysetAndAddsKey() throws Exception {
177172
}
178173

179174
@Test
180-
void addKeysetKey() throws Exception {
175+
void whenAddFirstKeyForKeysetItIsImmediatelyActiveAndUploaded() throws Exception {
181176
setKeysetKeys(123);
182-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
177+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
183178
put(1, new AdminKeyset(1, 5, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
184179
}};
185180
setAdminKeysets(keysets);
186181
final KeysetKey key = keyService.addKeysetKey(1);
187182
verify(keysetKeyStoreWriter).upload(collectionOfSize(1), eq(124));
188-
assertSiteKeyActivation(key, clock.now());
183+
184+
final int siteKeyActivatesInSeconds = 0; //since this is the first key for a keyset, test that it is immediately active
185+
assertKeyActivation(clock.now(), siteKeyActivatesInSeconds, SITE_KEY_EXPIRES_AFTER_SECONDS, key.getCreated(), key.getActivates(), key.getExpires());
189186
}
190187

188+
@Test
189+
void whenAddSecondKeyForKeysetItIsNotImmediatelyActive() throws Exception {
190+
final int keysetId = 567;
191+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
192+
put(keysetId, new AdminKeyset(keysetId, 5, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
193+
}};
194+
setAdminKeysets(keysets);
195+
196+
final KeysetKey[] keys = {
197+
new KeysetKey(11, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI), keysetId),
198+
};
199+
setKeysetKeys(MAX_KEY_ID, keys);
200+
201+
final KeysetKey key = keyService.addKeysetKey(keysetId);
202+
assertKeyActivation(clock.now(), SITE_KEY_ACTIVATES_IN_SECONDS, SITE_KEY_EXPIRES_AFTER_SECONDS, key.getCreated(), key.getActivates(), key.getExpires());
203+
}
204+
205+
191206
@Test
192207
void addKeysetKeyAddsSiteKey() throws Exception {
193208
setKeysetKeys(123);
194-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
209+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
195210
put(1, new AdminKeyset(1, 5, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
196211
}};
197212
setAdminKeysets(keysets);
@@ -406,7 +421,7 @@ void rotateKeysetKey(Vertx vertx, VertxTestContext testContext) throws Exception
406421
new KeysetKey(12, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI+1), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI+1), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI+1), 5)
407422
};
408423
setKeysetKeys(MAX_KEY_ID, keys);
409-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
424+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
410425
put(4, new AdminKeyset(4, 2, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
411426
put(5, new AdminKeyset(5, 3, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
412427
}};
@@ -673,8 +688,7 @@ void createKeysetKeysFirstRun() throws Exception {
673688
new EncryptionKey(17, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI), 2),
674689
};
675690
setEncryptionKeys(MAX_KEY_ID, keys);
676-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
677-
}};
691+
Map<Integer, AdminKeyset> keysets = new HashMap<>();
678692
setAdminKeysets(keysets);
679693
final KeysetKey[] keysetKeys = {};
680694
setKeysetKeys(0, keysetKeys);
@@ -704,8 +718,7 @@ void createKeysetKeysNoKeysNeed() throws Exception {
704718
new EncryptionKey(14, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI), 7),
705719
};
706720
setEncryptionKeys(MAX_KEY_ID, keys);
707-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
708-
}};
721+
Map<Integer, AdminKeyset> keysets = new HashMap<>();
709722
setAdminKeysets(keysets);
710723
final KeysetKey[] keysetKeys = {
711724
new KeysetKey(11, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI), 1),
@@ -731,7 +744,7 @@ void createKeysetKeysMissingKey() throws Exception {
731744
new EncryptionKey(16, null, Instant.ofEpochMilli(KEY_CREATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_ACTIVATE_TIME_IN_MILLI), Instant.ofEpochMilli(KEY_EXPIRE_TIME_IN_MILLI), 8),
732745
};
733746
setEncryptionKeys(MAX_KEY_ID, keys);
734-
Map<Integer, AdminKeyset> keysets = new HashMap<Integer, AdminKeyset>() {{
747+
Map<Integer, AdminKeyset> keysets = new HashMap<>() {{
735748
put(1, new AdminKeyset(1, 7, "test", Set.of(4,6,7), Instant.now().getEpochSecond(),true, true, new HashSet<>()));
736749
}};
737750
setAdminKeysets(keysets);

0 commit comments

Comments
 (0)