Skip to content
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

Merged
merged 36 commits into from
Jan 22, 2018

Conversation

holachuy
Copy link
Collaborator

Encrypted Flow related major fixes #3

  • Refactored encryption to support secret, public, and private key encryption and decryption and handle errors
  • Use shared local datastore based on Google store for now, since the encrypted flow runs multiple processes (api and worker) that have to talk to the same DB
  • Add debugging throughout the encrypted flow process
  • Add uncaught exception handlers to catch, display, and exit on error

@holachuy
Copy link
Collaborator Author

holachuy commented Jan 18, 2018

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
Copy link
Member

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.

Copy link
Collaborator Author

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;

Copy link
Member

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 ?

Copy link
Collaborator Author

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;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: class comment

Copy link
Collaborator Author

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stray diff markers

Copy link
Collaborator Author

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

License agreement missing

Copy link
Collaborator Author

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);
Copy link
Member

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?

Copy link
Collaborator Author

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);
Copy link
Member

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?

Copy link
Collaborator Author

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;
Copy link
Member

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.

Copy link
Collaborator Author

@holachuy holachuy left a 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.
Copy link
Contributor

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?

Copy link
Collaborator Author

@holachuy holachuy Jan 19, 2018

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) {
Copy link
Contributor

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?

Copy link
Collaborator Author

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());
Copy link
Contributor

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?

Copy link
Collaborator Author

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);
Copy link
Contributor

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?

Copy link
Collaborator Author

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")
Copy link
Contributor

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?

Copy link
Collaborator Author

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
Copy link
Contributor

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?

Copy link
Collaborator Author

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();
Copy link
Contributor

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

@holachuy holachuy left a 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);
Copy link
Member

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?

Copy link
Collaborator Author

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.

@holachuy holachuy merged commit 6663333 into master Jan 22, 2018
@holachuy holachuy deleted the local-datastore branch January 25, 2018 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Finish Encryption flow
3 participants