Skip to content

Commit

Permalink
Adding in client side keypair encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
cody-constine-ttd committed Dec 10, 2024
1 parent fc62e0e commit 249fdd0
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 10 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<!-- check micrometer.version vertx-micrometer-metrics consumes before bumping up -->
<micrometer.version>1.12.2</micrometer.version>
<junit-jupiter.version>5.11.2</junit-jupiter.version>
<uid2-shared.version>8.0.10-alpha-172-SNAPSHOT</uid2-shared.version>
<uid2-shared.version>8.0.11-alpha-173-SNAPSHOT</uid2-shared.version>
<okta-jwt.version>0.5.10</okta-jwt.version>
<image.version>${project.version}</image.version>
</properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.uid2.admin.job.EncryptionJob;

import com.uid2.admin.job.model.Job;
import com.uid2.admin.model.PrivateSiteDataMap;
import com.uid2.admin.store.MultiScopeStoreWriter;
import com.uid2.admin.util.PublicSiteUtil;
import com.uid2.shared.auth.OperatorKey;
import com.uid2.shared.model.ClientSideKeypair;

import java.util.Collection;

public class ClientSideKeypairEncryptionJob extends Job {
private final Collection<OperatorKey> globalOperators;
private final Collection<ClientSideKeypair> globalClientSideKeypairs;

private final MultiScopeStoreWriter<Collection<ClientSideKeypair>> multiScopeStoreWriter;

public ClientSideKeypairEncryptionJob(Collection<OperatorKey> globalOperators, Collection<ClientSideKeypair> globalClientSideKeypairs,
MultiScopeStoreWriter<Collection<ClientSideKeypair>> multiScopeStoreWriter) {
this.globalOperators = globalOperators;
this.globalClientSideKeypairs = globalClientSideKeypairs;
this.multiScopeStoreWriter = multiScopeStoreWriter;
}

@Override
public String getId() {
return "cloud-encryption-sync-clientside-keypair";
}

@Override
public void execute() throws Exception {
// Only public operators support clientside keypair
PrivateSiteDataMap<ClientSideKeypair> desiredPublicState = PublicSiteUtil.getPublicClientKeypairs(globalClientSideKeypairs, globalOperators);
multiScopeStoreWriter.uploadPublicWithEncryption(desiredPublicState, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
import com.uid2.shared.cloud.CloudUtils;
import com.uid2.shared.cloud.ICloudStorage;
import com.uid2.shared.cloud.TaggableCloudStorage;
import com.uid2.shared.model.ClientSideKeypair;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import com.uid2.shared.model.Site;
import com.uid2.shared.store.CloudPath;
import com.uid2.admin.legacy.LegacyClientKey;
import com.uid2.shared.store.RotatingEncryptedSaltProvider;
import com.uid2.shared.store.EncryptedRotatingSaltProvider;
import com.uid2.shared.store.RotatingSaltProvider;
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
import com.uid2.shared.store.scope.GlobalScope;
Expand Down Expand Up @@ -122,6 +123,15 @@ public void execute() throws Exception {
rotatingCloudEncryptionKeyProvider
);

ClientSideKeypairStoreFactory clientSideKeypairStoreFactory = new ClientSideKeypairStoreFactory(
cloudStorage,
new CloudPath(config.getString(Const.Config.ClientSideKeypairsMetadataPathProp)),
versionGenerator,
clock,
rotatingCloudEncryptionKeyProvider,
fileManager
);

CloudPath operatorMetadataPath = new CloudPath(config.getString(Const.Config.OperatorsMetadataPathProp));
GlobalScope operatorScope = new GlobalScope(operatorMetadataPath);
RotatingOperatorKeyProvider operatorKeyProvider = new RotatingOperatorKeyProvider(cloudStorage, cloudStorage, operatorScope);
Expand All @@ -138,6 +148,7 @@ public void execute() throws Exception {
keysetKeyStoreFactory.getGlobalReader().loadContent();
}
saltProvider.loadContent();
clientSideKeypairStoreFactory.getGlobalReader().loadContent();
}

Collection<OperatorKey> globalOperators = operatorKeyProvider.getAll();
Expand All @@ -146,6 +157,8 @@ public void execute() throws Exception {
Collection<EncryptionKey> globalEncryptionKeys = encryptionKeyStoreFactory.getGlobalReader().getSnapshot().getActiveKeySet();
Integer globalMaxKeyId = encryptionKeyStoreFactory.getGlobalReader().getMetadata().getInteger("max_key_id");
Map<Integer, EncryptionKeyAcl> globalKeyAcls = keyAclStoreFactory.getGlobalReader().getSnapshot().getAllAcls();
Collection<ClientSideKeypair> globalClientSideKeypair = clientSideKeypairStoreFactory.getGlobalReader().getAll();

MultiScopeStoreWriter<Collection<Site>> siteWriter = new MultiScopeStoreWriter<>(
fileManager,
siteStoreFactory,
Expand All @@ -166,6 +179,10 @@ public void execute() throws Exception {
fileManager,
saltStoreFactory,
MultiScopeStoreWriter::areCollectionsEqual);
MultiScopeStoreWriter<Collection<ClientSideKeypair>> clientSideKeypairWriter = new MultiScopeStoreWriter<>(
fileManager,
clientSideKeypairStoreFactory,
MultiScopeStoreWriter::areCollectionsEqual);

SiteEncryptionJob siteEncryptionSyncJob = new SiteEncryptionJob(siteWriter, globalSites, globalOperators);
ClientKeyEncryptionJob clientEncryptionSyncJob = new ClientKeyEncryptionJob(clientWriter, globalClients, globalOperators);
Expand All @@ -179,12 +196,14 @@ public void execute() throws Exception {
);
KeyAclEncryptionJob keyAclEncryptionSyncJob = new KeyAclEncryptionJob(keyAclWriter, globalOperators, globalKeyAcls);
SaltEncryptionJob saltEncryptionJob = new SaltEncryptionJob(globalOperators, saltProvider.getSnapshots(), saltWriter);
ClientSideKeypairEncryptionJob clientSideKeypairEncryptionJob = new ClientSideKeypairEncryptionJob(globalOperators, globalClientSideKeypair, clientSideKeypairWriter);

siteEncryptionSyncJob.execute();
clientEncryptionSyncJob.execute();
encryptionKeyEncryptionSyncJob.execute();
keyAclEncryptionSyncJob.execute();
saltEncryptionJob.execute();
clientSideKeypairEncryptionJob.execute();

if(config.getBoolean(enableKeysetConfigProp)) {
Map<Integer, Keyset> globalKeysets = keysetStoreFactory.getGlobalReader().getSnapshot().getAllKeysets();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.uid2.admin.store.factory;

import com.uid2.admin.store.writer.ClientSideKeypairStoreWriter;
import com.uid2.admin.store.writer.StoreWriter;
import com.uid2.shared.model.ClientSideKeypair;
import com.uid2.shared.store.reader.RotatingClientSideKeypairStore;
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
import com.uid2.shared.store.reader.StoreReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.uid2.admin.store.Clock;
import com.uid2.admin.store.FileManager;
import com.uid2.admin.store.version.VersionGenerator;
import com.uid2.shared.cloud.ICloudStorage;
import com.uid2.shared.store.CloudPath;
import com.uid2.shared.store.scope.EncryptedScope;
import com.uid2.shared.store.scope.GlobalScope;
import com.uid2.shared.store.scope.SiteScope;

import java.util.Collection;

public class ClientSideKeypairStoreFactory implements EncryptedStoreFactory<Collection<ClientSideKeypair>> {
private final ICloudStorage fileStreamProvider;
private final CloudPath rootMetadataPath;
private final VersionGenerator versionGenerator;
private final Clock clock;
private final FileManager fileManager;
private final RotatingClientSideKeypairStore globalReader;
private final RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider;

public ClientSideKeypairStoreFactory(
ICloudStorage fileStreamProvider,
CloudPath rootMetadataPath,
VersionGenerator versionGenerator,
Clock clock,
RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider,
FileManager fileManager) {
this.fileStreamProvider = fileStreamProvider;
this.rootMetadataPath = rootMetadataPath;
this.versionGenerator = versionGenerator;
this.clock = clock;
this.cloudEncryptionKeyProvider = cloudEncryptionKeyProvider;
this.fileManager = fileManager;
GlobalScope globalScope = new GlobalScope(rootMetadataPath);
globalReader = new RotatingClientSideKeypairStore(fileStreamProvider, globalScope);
}

public RotatingClientSideKeypairStore getGlobalReader() {
return globalReader;
}

@Override
public StoreWriter<Collection<ClientSideKeypair>> getEncryptedWriter(Integer siteId, boolean isPublic) {
return new ClientSideKeypairStoreWriter(getEncryptedReader(siteId, isPublic),
fileManager,
versionGenerator,
clock,
new EncryptedScope(rootMetadataPath, siteId, isPublic));
}

@Override
public StoreReader<Collection<ClientSideKeypair>> getEncryptedReader(Integer siteId, boolean isPublic) {
return new RotatingClientSideKeypairStore(fileStreamProvider, new EncryptedScope(rootMetadataPath, siteId, isPublic));
}

@Override
public RotatingCloudEncryptionKeyProvider getCloudEncryptionProvider() {
return cloudEncryptionKeyProvider;
}

@Override
public StoreReader<Collection<ClientSideKeypair>> getReader(Integer siteId) {
return new RotatingClientSideKeypairStore(fileStreamProvider, new SiteScope(rootMetadataPath, siteId));
}

@Override
public StoreWriter<Collection<ClientSideKeypair>> getWriter(Integer siteId) {
return new ClientSideKeypairStoreWriter(getReader(siteId), fileManager, versionGenerator, clock, new SiteScope(rootMetadataPath, siteId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.uid2.shared.Const;
import com.uid2.shared.cloud.TaggableCloudStorage;
import com.uid2.shared.store.CloudPath;
import com.uid2.shared.store.RotatingEncryptedSaltProvider;
import com.uid2.shared.store.EncryptedRotatingSaltProvider;
import com.uid2.shared.store.RotatingSaltProvider;
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
import com.uid2.shared.store.reader.StoreReader;
Expand Down Expand Up @@ -38,7 +38,7 @@ public SaltStoreFactory(JsonObject config, CloudPath rootMetadataPath, FileManag
@Override
public StoreWriter<Collection<RotatingSaltProvider.SaltSnapshot>> getEncryptedWriter(Integer siteId, boolean isPublic) {
EncryptedScope scope = new EncryptedScope(rootMetadatapath, siteId, isPublic);
RotatingEncryptedSaltProvider saltProvider = new RotatingEncryptedSaltProvider(taggableCloudStorage,
EncryptedRotatingSaltProvider saltProvider = new EncryptedRotatingSaltProvider(taggableCloudStorage,
scope.resolve(new CloudPath(config.getString(Const.Config.SaltsMetadataPathProp))).toString(), cloudEncryptionKeyProvider );
return new EncyptedSaltStoreWriter(config, saltProvider, fileManager, taggableCloudStorage, versionGenerator, scope, cloudEncryptionKeyProvider, siteId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.uid2.admin.store.version.VersionGenerator;
import com.uid2.shared.model.ClientSideKeypair;
import com.uid2.shared.store.reader.RotatingClientSideKeypairStore;
import com.uid2.shared.store.reader.StoreReader;
import com.uid2.shared.store.scope.StoreScope;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
Expand All @@ -17,7 +18,7 @@ public class ClientSideKeypairStoreWriter implements StoreWriter<Collection<Clie

private final ScopedStoreWriter writer;

public ClientSideKeypairStoreWriter(RotatingClientSideKeypairStore store, FileManager fileManager, VersionGenerator versionGenerator, Clock clock, StoreScope scope) {
public ClientSideKeypairStoreWriter(StoreReader<Collection<ClientSideKeypair>> store, FileManager fileManager, VersionGenerator versionGenerator, Clock clock, StoreScope scope) {
FileName dataFile = new FileName("client_side_keypairs", ".json");
String dataType = "client_side_keypairs";
writer = new ScopedStoreWriter(store, fileManager, versionGenerator, clock, scope, dataFile, dataType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ protected void uploadSaltsSnapshot(RotatingSaltProvider.SaltSnapshot snapshot, S
}
}

//cloudStorage.upload(newSaltsFile.toString(), location, this.currentTags);
this.upload(newSaltsFile.toString(), location);
}

Expand Down
19 changes: 15 additions & 4 deletions src/main/java/com/uid2/admin/util/PublicSiteUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
import com.uid2.shared.auth.Keyset;
import com.uid2.shared.auth.OperatorKey;
import com.uid2.shared.auth.OperatorType;
import com.uid2.shared.model.EncryptionKey;
import com.uid2.shared.model.KeysetKey;
import com.uid2.shared.model.SaltEntry;
import com.uid2.shared.model.Site;
import com.uid2.shared.model.*;
import com.uid2.shared.store.RotatingSaltProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -144,4 +141,18 @@ public static PrivateSiteDataMap<RotatingSaltProvider.SaltSnapshot> getPublicSal

return result;
}

public static PrivateSiteDataMap<ClientSideKeypair> getPublicClientKeypairs(
Collection<ClientSideKeypair> globalClientSideKeypair,
Collection<OperatorKey> operators) {
final PrivateSiteDataMap<ClientSideKeypair> result = getPublicSitesMap(operators);

globalClientSideKeypair.forEach(clientSideKeypair -> {
result.forEach((publicSiteId, publicSiteData) -> {
publicSiteData.add(clientSideKeypair);
});
});

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ public void overwritesExistingDataWhenChanged() throws Exception {
reader.loadContent();
Long oldVersion = reader.getMetadata().getLong("version");

// This test relies on our version generator returning a new timestamp, but the code can execute so fast we don't get a new version
// This small sleep makes this test much more stable
Thread.sleep(100);

Site updatedSite = new Site(scopedSiteId, "site 1 updated", true);
MultiScopeStoreWriter<Collection<Site>> multiStore = new MultiScopeStoreWriter<>(fileManager, siteStoreFactory, MultiScopeStoreWriter::areCollectionsEqual);

Expand Down Expand Up @@ -204,6 +208,7 @@ public void uploadPrivateWithEncryption() throws Exception {
Map<Integer, CloudEncryptionKey> allKeys = new HashMap<>();
allKeys.put(1, encryptionKey);
when(cloudEncryptionKeyProvider.getAll()).thenReturn(allKeys);
when(cloudEncryptionKeyProvider.getKey(1)).thenReturn(encryptionKey);

SiteStoreFactory siteStoreFactory = new SiteStoreFactory(
cloudStorage,
Expand Down Expand Up @@ -241,6 +246,7 @@ public void uploadPublicWithEncryption() throws Exception {
Map<Integer, CloudEncryptionKey> allKeys = new HashMap<>();
allKeys.put(1, encryptionKey);
when(cloudEncryptionKeyProvider.getAll()).thenReturn(allKeys);
when(cloudEncryptionKeyProvider.getKey(1)).thenReturn(encryptionKey);

SiteStoreFactory siteStoreFactory = new SiteStoreFactory(
cloudStorage,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.uid2.admin.store.writer;

public class SaltStoreWriterTest {

}

0 comments on commit 249fdd0

Please sign in to comment.