Skip to content

Commit 36235b0

Browse files
Adding more work on salt encryption
1 parent 6885a54 commit 36235b0

File tree

9 files changed

+221
-7
lines changed

9 files changed

+221
-7
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<!-- check micrometer.version vertx-micrometer-metrics consumes before bumping up -->
1717
<micrometer.version>1.12.2</micrometer.version>
1818
<junit-jupiter.version>5.11.2</junit-jupiter.version>
19-
<uid2-shared.version>8.0.6</uid2-shared.version>
19+
<uid2-shared.version>8.0.10-alpha-172-SNAPSHOT</uid2-shared.version>
2020
<okta-jwt.version>0.5.10</okta-jwt.version>
2121
<image.version>${project.version}</image.version>
2222
</properties>

src/main/java/com/uid2/admin/job/EncryptionJob/ClientKeyEncryptionJob.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public String getId() {
3333
public void execute() throws Exception {
3434
PrivateSiteDataMap<LegacyClientKey> desiredPrivateState = PrivateSiteUtil.getClientKeys(globalOperators, globalClientKeys);
3535
multiScopeStoreWriter.uploadPrivateWithEncryption(desiredPrivateState, null);
36-
PrivateSiteDataMap<LegacyClientKey> desiredPublicState = PublicSiteUtil.getPublicClients(globalClientKeys,globalOperators);
36+
PrivateSiteDataMap<LegacyClientKey> desiredPublicState = PublicSiteUtil.getPublicClients(globalClientKeys, globalOperators);
3737
multiScopeStoreWriter.uploadPublicWithEncryption(desiredPublicState, null);
3838
}
3939
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.uid2.admin.job.EncryptionJob;
2+
3+
import com.uid2.admin.job.model.Job;
4+
import com.uid2.admin.model.PrivateSiteDataMap;
5+
import com.uid2.admin.store.MultiScopeStoreWriter;
6+
import com.uid2.admin.util.PrivateSiteUtil;
7+
import com.uid2.admin.util.PublicSiteUtil;
8+
import com.uid2.shared.auth.OperatorKey;
9+
import com.uid2.shared.model.SaltEntry;
10+
11+
import java.util.Collection;
12+
13+
public class SaltEncryptionJob extends Job {
14+
private final Collection<OperatorKey> globalOperators;
15+
private final Collection<SaltEntry> saltEntries;
16+
private final MultiScopeStoreWriter<Collection<SaltEntry>> multiScopeStoreWriter;
17+
18+
public SaltEncryptionJob(Collection<OperatorKey> globalOperators,
19+
Collection<SaltEntry> saltEntries,
20+
MultiScopeStoreWriter<Collection<SaltEntry>> multiScopeStoreWriter) {
21+
this.globalOperators = globalOperators;
22+
this.saltEntries = saltEntries;
23+
this.multiScopeStoreWriter = multiScopeStoreWriter;
24+
}
25+
26+
27+
@Override
28+
public String getId() {
29+
return "cloud-encryption-sync-salts";
30+
}
31+
32+
@Override
33+
public void execute() throws Exception {
34+
PrivateSiteDataMap<SaltEntry> desiredPrivateState = PrivateSiteUtil.getPrivateSaltEntries(saltEntries, globalOperators);
35+
multiScopeStoreWriter.uploadPrivateWithEncryption(desiredPrivateState, null);
36+
PrivateSiteDataMap<SaltEntry> desiredPublicState = PublicSiteUtil.getPublicSaltEntries(saltEntries, globalOperators);
37+
multiScopeStoreWriter.uploadPublicWithEncryption(desiredPublicState, null);
38+
}
39+
}

src/main/java/com/uid2/admin/job/jobsync/EncryptedFilesSyncJob.java

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

33
import com.fasterxml.jackson.databind.ObjectWriter;
44
import com.uid2.admin.job.EncryptionJob.*;
5-
import com.uid2.admin.job.EncryptionJob.ClientKeyEncryptionJob;
65
import com.uid2.admin.job.model.Job;
76
import com.uid2.admin.store.*;
87
import com.uid2.admin.store.factory.*;
@@ -23,7 +22,6 @@
2322
import com.uid2.shared.store.CloudPath;
2423
import com.uid2.admin.legacy.LegacyClientKey;
2524
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
26-
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
2725
import com.uid2.shared.store.scope.GlobalScope;
2826
import io.vertx.core.json.JsonObject;
2927

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.uid2.admin.store.factory;
2+
3+
import com.uid2.admin.store.FileManager;
4+
import com.uid2.admin.store.version.VersionGenerator;
5+
import com.uid2.admin.store.writer.EncyptedSaltStoreWriter;
6+
import com.uid2.admin.store.writer.StoreWriter;
7+
import com.uid2.shared.cloud.TaggableCloudStorage;
8+
import com.uid2.shared.store.CloudPath;
9+
import com.uid2.shared.store.RotatingEncryptedSaltProvider;
10+
import com.uid2.shared.store.RotatingSaltProvider;
11+
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
12+
import com.uid2.shared.store.reader.StoreReader;
13+
import com.uid2.shared.store.scope.EncryptedScope;
14+
import io.vertx.core.json.JsonObject;
15+
16+
import java.util.Collection;
17+
18+
public class SaltStoreFactory implements EncryptedStoreFactory<Collection<RotatingSaltProvider.SaltSnapshot>> {
19+
JsonObject config;
20+
CloudPath rootMetadatapath;
21+
RotatingSaltProvider saltProvider;
22+
FileManager fileManager;
23+
TaggableCloudStorage taggableCloudStorage;
24+
VersionGenerator versionGenerator;
25+
RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider;
26+
27+
public SaltStoreFactory(JsonObject config, CloudPath rootMetadataPath, RotatingSaltProvider saltProvider, FileManager fileManager,
28+
TaggableCloudStorage taggableCloudStorage, VersionGenerator versionGenerator,
29+
RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider) {
30+
this.config = config;
31+
this.rootMetadatapath = rootMetadataPath;
32+
this.saltProvider = saltProvider;
33+
this.fileManager = fileManager;
34+
this.taggableCloudStorage = taggableCloudStorage;
35+
this.versionGenerator = versionGenerator;
36+
this.cloudEncryptionKeyProvider = cloudEncryptionKeyProvider;
37+
}
38+
39+
@Override
40+
public StoreWriter<Collection<RotatingSaltProvider.SaltSnapshot>> getEncryptedWriter(Integer siteId, boolean isPublic) {
41+
return new EncyptedSaltStoreWriter(config, saltProvider, fileManager, taggableCloudStorage, versionGenerator,
42+
new EncryptedScope(rootMetadatapath, siteId, isPublic), cloudEncryptionKeyProvider, siteId);
43+
}
44+
45+
@Override
46+
public StoreReader<Collection<RotatingSaltProvider.SaltSnapshot>> getEncryptedReader(Integer siteId, boolean isPublic) {
47+
return new RotatingEncryptedSaltProvider(taggableCloudStorage,
48+
new EncryptedScope(rootMetadatapath, siteId, isPublic).getMetadataPath().toString(),
49+
cloudEncryptionKeyProvider);
50+
}
51+
52+
@Override
53+
public RotatingCloudEncryptionKeyProvider getCloudEncryptionProvider() {
54+
return cloudEncryptionKeyProvider;
55+
}
56+
57+
@Override
58+
public StoreReader<Collection<RotatingSaltProvider.SaltSnapshot>> getReader(Integer siteId) {
59+
return null;
60+
}
61+
62+
@Override
63+
public StoreWriter<Collection<RotatingSaltProvider.SaltSnapshot>> getWriter(Integer siteId) {
64+
return null;
65+
}
66+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.uid2.admin.store.writer;
2+
3+
import com.uid2.admin.store.FileManager;
4+
import com.uid2.admin.store.version.VersionGenerator;
5+
import com.uid2.shared.cloud.TaggableCloudStorage;
6+
import com.uid2.shared.encryption.AesGcm;
7+
import com.uid2.shared.model.CloudEncryptionKey;
8+
import com.uid2.shared.store.CloudPath;
9+
import com.uid2.shared.store.RotatingSaltProvider;
10+
import com.uid2.shared.store.reader.RotatingCloudEncryptionKeyProvider;
11+
import com.uid2.shared.store.scope.StoreScope;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
import io.vertx.core.json.JsonObject;
15+
16+
import java.nio.charset.StandardCharsets;
17+
import java.util.Base64;
18+
19+
public class EncyptedSaltStoreWriter extends SaltStoreWriter implements StoreWriter {
20+
private StoreScope scope;
21+
private RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider;
22+
private Integer siteId;
23+
24+
private static final Logger LOGGER = LoggerFactory.getLogger(EncyptedSaltStoreWriter.class);
25+
public EncyptedSaltStoreWriter(JsonObject config, RotatingSaltProvider provider, FileManager fileManager,
26+
TaggableCloudStorage cloudStorage, VersionGenerator versionGenerator, StoreScope scope,
27+
RotatingCloudEncryptionKeyProvider cloudEncryptionKeyProvider, Integer siteId) {
28+
super(config, provider, fileManager, cloudStorage, versionGenerator);
29+
this.scope = scope;
30+
this.cloudEncryptionKeyProvider = cloudEncryptionKeyProvider;
31+
this.siteId = siteId;
32+
}
33+
34+
@Override
35+
protected java.lang.String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
36+
return scope.resolve(new CloudPath(saltSnapshotLocationPrefix + snapshot.getEffective().toEpochMilli())).toString();
37+
}
38+
39+
@Override
40+
protected void upload(String data, String location) throws Exception {
41+
if (siteId == null) {
42+
throw new IllegalStateException("Site ID is not set.");
43+
}
44+
45+
CloudEncryptionKey encryptionKey = null;
46+
try {
47+
encryptionKey = cloudEncryptionKeyProvider.getEncryptionKeyForSite(siteId);
48+
} catch (IllegalStateException e) {
49+
LOGGER.error("Error: No Cloud Encryption keys available for encryption for site ID: {}", siteId, e);
50+
}
51+
JsonObject encryptedJson = new JsonObject();
52+
if (encryptionKey != null) {
53+
byte[] secret = Base64.getDecoder().decode(encryptionKey.getSecret());
54+
byte[] encryptedPayload = AesGcm.encrypt(data.getBytes(StandardCharsets.UTF_8), secret);
55+
encryptedJson.put("key_id", encryptionKey.getId())
56+
.put("encryption_version", "1.0")
57+
.put("encrypted_payload", Base64.getEncoder().encodeToString(encryptedPayload));
58+
} else {
59+
throw new IllegalStateException("No Cloud Encryption keys available for encryption for site ID: " + siteId);
60+
}
61+
62+
63+
super.upload(encryptedJson.encodePrettily(), location);
64+
}
65+
66+
@Override
67+
public void upload(Object data, JsonObject extraMeta) throws Exception {
68+
super.upload((RotatingSaltProvider.SaltSnapshot) data);
69+
}
70+
71+
@Override
72+
public void rewriteMeta() throws Exception {
73+
74+
}
75+
}

src/main/java/com/uid2/admin/store/writer/SaltStoreWriter.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public class SaltStoreWriter {
2626
private static final Logger LOGGER = LoggerFactory.getLogger(SaltStoreWriter.class);
2727
private final RotatingSaltProvider provider;
2828
private final FileManager fileManager;
29-
private final String saltSnapshotLocationPrefix;
29+
protected final String saltSnapshotLocationPrefix;
3030
private final VersionGenerator versionGenerator;
3131

3232
private final TaggableCloudStorage cloudStorage;
@@ -111,7 +111,7 @@ public void archiveSaltLocations() throws Exception {
111111
});
112112
}
113113

114-
private String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
114+
protected String getSaltSnapshotLocation(RotatingSaltProvider.SaltSnapshot snapshot) {
115115
return saltSnapshotLocationPrefix + snapshot.getEffective().toEpochMilli();
116116
}
117117

@@ -130,7 +130,13 @@ private void uploadSaltsSnapshot(RotatingSaltProvider.SaltSnapshot snapshot, Str
130130
}
131131
}
132132

133-
cloudStorage.upload(newSaltsFile.toString(), location, this.currentTags);
133+
//cloudStorage.upload(newSaltsFile.toString(), location, this.currentTags);
134+
this.upload(newSaltsFile.toString(), location);
135+
}
136+
137+
protected void upload(String data, String location) throws Exception {
138+
cloudStorage.upload(data, location, this.currentTags);
139+
134140
}
135141

136142
private void setStatusTagToCurrent(String location) throws CloudStorageException {

src/main/java/com/uid2/admin/util/PrivateSiteUtil.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.uid2.shared.auth.*;
77
import com.uid2.shared.model.EncryptionKey;
88
import com.uid2.shared.model.KeysetKey;
9+
import com.uid2.shared.model.SaltEntry;
910
import com.uid2.shared.model.Site;
1011
import org.slf4j.Logger;
1112
import org.slf4j.LoggerFactory;
@@ -310,4 +311,18 @@ public static PrivateSiteDataMap<KeysetKey> getKeysetKeys(Collection<OperatorKey
310311
});
311312
return result;
312313
}
314+
315+
public static PrivateSiteDataMap<SaltEntry> getPrivateSaltEntries(
316+
Collection<SaltEntry> globalSaltEntries,
317+
Collection<OperatorKey> operators) {
318+
final PrivateSiteDataMap<SaltEntry> result = getPrivateSites(operators);
319+
320+
globalSaltEntries.forEach(saltEntry -> {
321+
result.forEach((publicSiteId, publicSiteData) -> {
322+
publicSiteData.add(saltEntry);
323+
});
324+
});
325+
326+
return result;
327+
}
313328
}

src/main/java/com/uid2/admin/util/PublicSiteUtil.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.uid2.shared.auth.OperatorType;
99
import com.uid2.shared.model.EncryptionKey;
1010
import com.uid2.shared.model.KeysetKey;
11+
import com.uid2.shared.model.SaltEntry;
1112
import com.uid2.shared.model.Site;
1213
import org.slf4j.Logger;
1314
import org.slf4j.LoggerFactory;
@@ -128,4 +129,18 @@ public static PrivateSiteDataMap<KeysetKey> getPublicKeysetKeys(
128129

129130
return result;
130131
}
132+
133+
public static PrivateSiteDataMap<SaltEntry> getPublicSaltEntries(
134+
Collection<SaltEntry> globalSaltEntries,
135+
Collection<OperatorKey> operators) {
136+
final PrivateSiteDataMap<SaltEntry> result = getPublicSitesMap(operators);
137+
138+
globalSaltEntries.forEach(saltEntry -> {
139+
result.forEach((publicSiteId, publicSiteData) -> {
140+
publicSiteData.add(saltEntry);
141+
});
142+
});
143+
144+
return result;
145+
}
131146
}

0 commit comments

Comments
 (0)