-
Notifications
You must be signed in to change notification settings - Fork 481
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Encrypted Flow - refactor encryption, use shared local datastore based on Google store, add debugging #61
Conversation
… and api are running in different process
… and api are running in different process
… and api are running in different process
…into local-datastore
This is ready for review. I did a pull with a rebase to merge the latest and it forced me to do several merges. Sorry for the noise. |
@@ -1,10 +1,11 @@ | |||
env: LOCAL | |||
cloud: LOCAL | |||
encryptedFlow: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to turn this on by default for local dev? If so, we should update the documentation on how run locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverting. Yes, I thought in a follow up I'll enable and do the documentation, maybe once ported, unsure yet.
@@ -35,7 +35,7 @@ | |||
import java.util.concurrent.TimeUnit; | |||
import org.dataportabilityproject.cloud.interfaces.JobDataCache; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: while we're in here, can we add a class comment ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -35,18 +37,13 @@ | |||
import java.util.Map.Entry; | |||
import org.dataportabilityproject.cloud.interfaces.PersistentKeyValueStore; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: class comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
import com.google.common.base.Supplier; | ||
import com.google.common.base.Suppliers; | ||
import com.google.common.cache.CacheBuilder; | ||
import com.google.common.cache.CacheLoader; | ||
import com.google.common.cache.LoadingCache; | ||
<<<<<<< HEAD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stray diff markers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -0,0 +1,38 @@ | |||
package org.dataportabilityproject.job; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
License agreement missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -35,14 +36,19 @@ public String encrypt(String data) { | |||
byte[] encrypted = cipher.doFinal(data.getBytes(Charsets.UTF_8)); | |||
return BaseEncoding.base64Url().encode(encrypted); | |||
} catch (BadPaddingException e) { | |||
logger.error("BadPaddingException for data, length: {}", data.length(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, since we don't do anything different for these, (aside from the name of the exception), can we put them all in one catch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Done.
@@ -61,14 +67,19 @@ public String decrypt(String encrypted) { | |||
System.arraycopy(decrypted, 8, data, 0, data.length); | |||
return new String(data, Charsets.UTF_8); | |||
} catch (BadPaddingException e) { | |||
logger.error("BadPaddingException for data, length: {}", encrypted.length(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here - can we put these in one catch?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -19,8 +19,11 @@ | |||
import com.google.api.services.calendar.CalendarScopes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like these changes were introduced from my merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed the latest based on initial feedback, PTAL
@@ -53,15 +52,15 @@ | |||
* Serialize and encrypt the given {@code authData} with the session key. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worker instance public key, not session key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added more documentation and refactored to remove the public key encryption and just have the StartCopyHandler use it directly.
/** Constructs instances of the {@link Crypter} for different key types. */ | ||
public class CrypterFactory { | ||
|
||
public static Crypter createCrypterForSecretKey(SecretKey key) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document that SecretKey is for symmetric keys?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
import com.google.inject.Guice; | ||
import com.google.inject.Injector; | ||
|
||
public class PortabilityApiMain { | ||
public static void main(String args[]) throws Exception { | ||
Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandlers.systemExit()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to do this in prod? won't it disrupt other jobs being handled by this API instance, especially if they are in the API polling stage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I was debugging but in prod, we certainly don't want to exit. Added a warning message instead.
cryptoHelper.encryptAuthData(publicKey, importAuthCookie)); | ||
logger.debug("Found publicKey: {}", publicKey.getEncoded().length); | ||
|
||
String encryptedExportAuthData = cryptoHelper.encryptAuthData(publicKey, exportAuthCookie); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at this point is it the whole cookie or just credential that we're encrypting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I clarified the variable name. It's just the cookie value, not the whole cookie.
Suppliers.memoize(InMemoryPersistentKeyValueStore::new); | ||
// Google DataStore emulator is used for local development | ||
private static final Datastore datastore = DatastoreOptions.newBuilder() | ||
.setHost("http://localhost:8081") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should all ports be moved to yaml so we avoid conflicts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added TODO
@@ -46,21 +61,35 @@ public JobDataCache load(String service) throws Exception { | |||
} | |||
}); | |||
|
|||
private static final Supplier<PersistentKeyValueStore> KEY_VALUE_SUPPLIER = | |||
Suppliers.memoize(InMemoryPersistentKeyValueStore::new); | |||
// Google DataStore emulator is used for local development |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice find on the local data store! Does the code here check if it's running and print an error if not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The database client code gives an error on startup if one isn't running.
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
final class WorkerImpl { | ||
private final Logger logger = LoggerFactory.getLogger(WorkerImpl.class); | ||
private static final Logger logger = LoggerFactory.getLogger(WorkerImpl.class); | ||
private static final Gson GSON = new Gson(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we should switch to Jackson since we are using that elsewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a TODO for now to use the Jackson-based AuthData when it's checked in.
…ion by calling it directly from the StartCopyHandler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PTAL, all comments have been addressed. Thank you for the thorough review!
if(true) { | ||
logger.info("Exiting before copy, job: {}", job); | ||
// TODO: Enable worker-based copying | ||
logger.warn("Exiting before copy, job: {}", job); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if I missed this, could you explain why we cant enable this yet? iiuc, this causes us to skip the use of PortabilityCopier below right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. It was mostly for debugging easily.
Encrypted Flow related major fixes #3