diff --git a/pom.xml b/pom.xml
index 479eb475..d8e2d5f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
1.12.2
5.11.2
- 8.0.6
+ 8.0.10-alpha-172-SNAPSHOT
0.5.10
${project.version}
diff --git a/src/main/java/com/uid2/admin/job/EncryptionJob/ClientKeyEncryptionJob.java b/src/main/java/com/uid2/admin/job/EncryptionJob/ClientKeyEncryptionJob.java
index 9febe5f7..8e81705c 100644
--- a/src/main/java/com/uid2/admin/job/EncryptionJob/ClientKeyEncryptionJob.java
+++ b/src/main/java/com/uid2/admin/job/EncryptionJob/ClientKeyEncryptionJob.java
@@ -33,7 +33,7 @@ public String getId() {
public void execute() throws Exception {
PrivateSiteDataMap desiredPrivateState = PrivateSiteUtil.getClientKeys(globalOperators, globalClientKeys);
multiScopeStoreWriter.uploadPrivateWithEncryption(desiredPrivateState, null);
- PrivateSiteDataMap desiredPublicState = PublicSiteUtil.getPublicClients(globalClientKeys,globalOperators);
+ PrivateSiteDataMap desiredPublicState = PublicSiteUtil.getPublicClients(globalClientKeys, globalOperators);
multiScopeStoreWriter.uploadPublicWithEncryption(desiredPublicState, null);
}
}
diff --git a/src/main/java/com/uid2/admin/job/EncryptionJob/SaltEncryptionJob.java b/src/main/java/com/uid2/admin/job/EncryptionJob/SaltEncryptionJob.java
new file mode 100644
index 00000000..988b17da
--- /dev/null
+++ b/src/main/java/com/uid2/admin/job/EncryptionJob/SaltEncryptionJob.java
@@ -0,0 +1,39 @@
+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.PrivateSiteUtil;
+import com.uid2.admin.util.PublicSiteUtil;
+import com.uid2.shared.auth.OperatorKey;
+import com.uid2.shared.model.SaltEntry;
+
+import java.util.Collection;
+
+public class SaltEncryptionJob extends Job {
+ private final Collection globalOperators;
+ private final Collection saltEntries;
+ private final MultiScopeStoreWriter> multiScopeStoreWriter;
+
+ public SaltEncryptionJob(Collection globalOperators,
+ Collection saltEntries,
+ MultiScopeStoreWriter> multiScopeStoreWriter) {
+ this.globalOperators = globalOperators;
+ this.saltEntries = saltEntries;
+ this.multiScopeStoreWriter = multiScopeStoreWriter;
+ }
+
+
+ @Override
+ public String getId() {
+ return "cloud-encryption-sync-salts";
+ }
+
+ @Override
+ public void execute() throws Exception {
+ PrivateSiteDataMap desiredPrivateState = PrivateSiteUtil.getPrivateSaltEntries(saltEntries, globalOperators);
+ multiScopeStoreWriter.uploadPrivateWithEncryption(desiredPrivateState, null);
+ PrivateSiteDataMap desiredPublicState = PublicSiteUtil.getPublicSaltEntries(saltEntries, globalOperators);
+ multiScopeStoreWriter.uploadPublicWithEncryption(desiredPublicState, null);
+ }
+}
diff --git a/src/main/java/com/uid2/admin/job/jobsync/EncryptedFilesSyncJob.java b/src/main/java/com/uid2/admin/job/jobsync/EncryptedFilesSyncJob.java
index 14077ac3..31c87b3e 100644
--- a/src/main/java/com/uid2/admin/job/jobsync/EncryptedFilesSyncJob.java
+++ b/src/main/java/com/uid2/admin/job/jobsync/EncryptedFilesSyncJob.java
@@ -2,7 +2,6 @@
import com.fasterxml.jackson.databind.ObjectWriter;
import com.uid2.admin.job.EncryptionJob.*;
-import com.uid2.admin.job.EncryptionJob.ClientKeyEncryptionJob;
import com.uid2.admin.job.model.Job;
import com.uid2.admin.store.*;
import com.uid2.admin.store.factory.*;
@@ -23,7 +22,6 @@
import com.uid2.shared.store.CloudPath;
import com.uid2.admin.legacy.LegacyClientKey;
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
-import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
import com.uid2.shared.store.scope.GlobalScope;
import io.vertx.core.json.JsonObject;
diff --git a/src/main/java/com/uid2/admin/store/factory/SaltStoreFactory.java b/src/main/java/com/uid2/admin/store/factory/SaltStoreFactory.java
new file mode 100644
index 00000000..21f31a1e
--- /dev/null
+++ b/src/main/java/com/uid2/admin/store/factory/SaltStoreFactory.java
@@ -0,0 +1,66 @@
+package com.uid2.admin.store.factory;
+
+import com.uid2.admin.store.FileManager;
+import com.uid2.admin.store.version.VersionGenerator;
+import com.uid2.admin.store.writer.EncyptedSaltStoreWriter;
+import com.uid2.admin.store.writer.StoreWriter;
+import com.uid2.shared.cloud.TaggableCloudStorage;
+import com.uid2.shared.store.CloudPath;
+import com.uid2.shared.store.RotatingEncryptedSaltProvider;
+import com.uid2.shared.store.RotatingSaltProvider;
+import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
+import com.uid2.shared.store.reader.StoreReader;
+import com.uid2.shared.store.scope.EncryptedScope;
+import io.vertx.core.json.JsonObject;
+
+import java.util.Collection;
+
+public class SaltStoreFactory implements EncryptedStoreFactory> {
+ JsonObject config;
+ CloudPath rootMetadatapath;
+ RotatingSaltProvider saltProvider;
+ FileManager fileManager;
+ TaggableCloudStorage taggableCloudStorage;
+ VersionGenerator versionGenerator;
+ RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider;
+
+ public SaltStoreFactory(JsonObject config, CloudPath rootMetadataPath, RotatingSaltProvider saltProvider, FileManager fileManager,
+ TaggableCloudStorage taggableCloudStorage, VersionGenerator versionGenerator,
+ RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider) {
+ this.config = config;
+ this.rootMetadatapath = rootMetadataPath;
+ this.saltProvider = saltProvider;
+ this.fileManager = fileManager;
+ this.taggableCloudStorage = taggableCloudStorage;
+ this.versionGenerator = versionGenerator;
+ this.cloudEncryptionKeyProvider = cloudEncryptionKeyProvider;
+ }
+
+ @Override
+ public StoreWriter> getEncryptedWriter(Integer siteId, boolean isPublic) {
+ return new EncyptedSaltStoreWriter(config, saltProvider, fileManager, taggableCloudStorage, versionGenerator,
+ new EncryptedScope(rootMetadatapath, siteId, isPublic), cloudEncryptionKeyProvider, siteId);
+ }
+
+ @Override
+ public StoreReader> getEncryptedReader(Integer siteId, boolean isPublic) {
+ return new RotatingEncryptedSaltProvider(taggableCloudStorage,
+ new EncryptedScope(rootMetadatapath, siteId, isPublic).getMetadataPath().toString(),
+ cloudEncryptionKeyProvider);
+ }
+
+ @Override
+ public RotatingCloudEncryptionKeyProvider getCloudEncryptionProvider() {
+ return cloudEncryptionKeyProvider;
+ }
+
+ @Override
+ public StoreReader> getReader(Integer siteId) {
+ return null;
+ }
+
+ @Override
+ public StoreWriter> getWriter(Integer siteId) {
+ return null;
+ }
+}
diff --git a/src/main/java/com/uid2/admin/store/writer/EncyptedSaltStoreWriter.java b/src/main/java/com/uid2/admin/store/writer/EncyptedSaltStoreWriter.java
new file mode 100644
index 00000000..d29f8a29
--- /dev/null
+++ b/src/main/java/com/uid2/admin/store/writer/EncyptedSaltStoreWriter.java
@@ -0,0 +1,75 @@
+package com.uid2.admin.store.writer;
+
+import com.uid2.admin.store.FileManager;
+import com.uid2.admin.store.version.VersionGenerator;
+import com.uid2.shared.cloud.TaggableCloudStorage;
+import com.uid2.shared.encryption.AesGcm;
+import com.uid2.shared.model.CloudEncryptionKey;
+import com.uid2.shared.store.CloudPath;
+import com.uid2.shared.store.RotatingSaltProvider;
+import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
+import com.uid2.shared.store.scope.StoreScope;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import io.vertx.core.json.JsonObject;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+public class EncyptedSaltStoreWriter extends SaltStoreWriter implements StoreWriter {
+ private StoreScope scope;
+ private RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider;
+ private Integer siteId;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(EncyptedSaltStoreWriter.class);
+ public EncyptedSaltStoreWriter(JsonObject config, RotatingSaltProvider provider, FileManager fileManager,
+ TaggableCloudStorage cloudStorage, VersionGenerator versionGenerator, StoreScope scope,
+ RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider, Integer siteId) {
+ super(config, provider, fileManager, cloudStorage, versionGenerator);
+ this.scope = scope;
+ this.cloudEncryptionKeyProvider = cloudEncryptionKeyProvider;
+ this.siteId = siteId;
+ }
+
+ @Override
+ protected java.lang.String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
+ return scope.resolve(new CloudPath(saltSnapshotLocationPrefix + snapshot.getEffective().toEpochMilli())).toString();
+ }
+
+ @Override
+ protected void upload(String data, String location) throws Exception {
+ if (siteId == null) {
+ throw new IllegalStateException("Site ID is not set.");
+ }
+
+ CloudEncryptionKey encryptionKey = null;
+ try {
+ encryptionKey = cloudEncryptionKeyProvider.getEncryptionKeyForSite(siteId);
+ } catch (IllegalStateException e) {
+ LOGGER.error("Error: No Cloud Encryption keys available for encryption for site ID: {}", siteId, e);
+ }
+ JsonObject encryptedJson = new JsonObject();
+ if (encryptionKey != null) {
+ byte[] secret = Base64.getDecoder().decode(encryptionKey.getSecret());
+ byte[] encryptedPayload = AesGcm.encrypt(data.getBytes(StandardCharsets.UTF_8), secret);
+ encryptedJson.put("key_id", encryptionKey.getId())
+ .put("encryption_version", "1.0")
+ .put("encrypted_payload", Base64.getEncoder().encodeToString(encryptedPayload));
+ } else {
+ throw new IllegalStateException("No Cloud Encryption keys available for encryption for site ID: " + siteId);
+ }
+
+
+ super.upload(encryptedJson.encodePrettily(), location);
+ }
+
+ @Override
+ public void upload(Object data, JsonObject extraMeta) throws Exception {
+ super.upload((RotatingSaltProvider.SaltSnapshot) data);
+ }
+
+ @Override
+ public void rewriteMeta() throws Exception {
+
+ }
+}
diff --git a/src/main/java/com/uid2/admin/store/writer/SaltStoreWriter.java b/src/main/java/com/uid2/admin/store/writer/SaltStoreWriter.java
index 76626539..6d350527 100644
--- a/src/main/java/com/uid2/admin/store/writer/SaltStoreWriter.java
+++ b/src/main/java/com/uid2/admin/store/writer/SaltStoreWriter.java
@@ -26,7 +26,7 @@ public class SaltStoreWriter {
private static final Logger LOGGER = LoggerFactory.getLogger(SaltStoreWriter.class);
private final RotatingSaltProvider provider;
private final FileManager fileManager;
- private final String saltSnapshotLocationPrefix;
+ protected final String saltSnapshotLocationPrefix;
private final VersionGenerator versionGenerator;
private final TaggableCloudStorage cloudStorage;
@@ -111,7 +111,7 @@ public void archiveSaltLocations() throws Exception {
});
}
- private String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
+ protected String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
return saltSnapshotLocationPrefix + snapshot.getEffective().toEpochMilli();
}
@@ -130,7 +130,13 @@ private void uploadSaltsSnapshot(RotatingSaltProvider.SaltSnapshot snapshot, Str
}
}
- cloudStorage.upload(newSaltsFile.toString(), location, this.currentTags);
+ //cloudStorage.upload(newSaltsFile.toString(), location, this.currentTags);
+ this.upload(newSaltsFile.toString(), location);
+ }
+
+ protected void upload(String data, String location) throws Exception {
+ cloudStorage.upload(data, location, this.currentTags);
+
}
private void setStatusTagToCurrent(String location) throws CloudStorageException {
diff --git a/src/main/java/com/uid2/admin/util/PrivateSiteUtil.java b/src/main/java/com/uid2/admin/util/PrivateSiteUtil.java
index f73541a9..dd81e397 100644
--- a/src/main/java/com/uid2/admin/util/PrivateSiteUtil.java
+++ b/src/main/java/com/uid2/admin/util/PrivateSiteUtil.java
@@ -6,6 +6,7 @@
import com.uid2.shared.auth.*;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -310,4 +311,18 @@ public static PrivateSiteDataMap getKeysetKeys(Collection getPrivateSaltEntries(
+ Collection globalSaltEntries,
+ Collection operators) {
+ final PrivateSiteDataMap result = getPrivateSites(operators);
+
+ globalSaltEntries.forEach(saltEntry -> {
+ result.forEach((publicSiteId, publicSiteData) -> {
+ publicSiteData.add(saltEntry);
+ });
+ });
+
+ return result;
+ }
}
diff --git a/src/main/java/com/uid2/admin/util/PublicSiteUtil.java b/src/main/java/com/uid2/admin/util/PublicSiteUtil.java
index bc55bc14..7470c5c2 100644
--- a/src/main/java/com/uid2/admin/util/PublicSiteUtil.java
+++ b/src/main/java/com/uid2/admin/util/PublicSiteUtil.java
@@ -8,6 +8,7 @@
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -128,4 +129,18 @@ public static PrivateSiteDataMap getPublicKeysetKeys(
return result;
}
+
+ public static PrivateSiteDataMap getPublicSaltEntries(
+ Collection globalSaltEntries,
+ Collection operators) {
+ final PrivateSiteDataMap result = getPublicSitesMap(operators);
+
+ globalSaltEntries.forEach(saltEntry -> {
+ result.forEach((publicSiteId, publicSiteData) -> {
+ publicSiteData.add(saltEntry);
+ });
+ });
+
+ return result;
+ }
}