{"action":"created","comment":{"url":"https://api.github.com/repos/codice/ddf/pulls/comments/150539326","pull_request_review_id":76101151,"id":150539326,"diff_hunk":"@@ -0,0 +1,284 @@\n+/**\n+ * Copyright (c) Codice Foundation\n+ *\n+ * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU\n+ * Lesser General Public License as published by the Free Software Foundation, either version 3 of\n+ * the License, or any later version.\n+ *\n+ * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\n+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+ * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public\n+ * License is distributed along with this program and can be found at\n+ * <http://www.gnu.org/licenses/lgpl.html>.\n+ */\n+package org.codice.ddf.configuration.migration;\n+\n+import static org.apache.commons.codec.binary.Hex.decodeHex;\n+import static org.apache.commons.codec.binary.Hex.encodeHex;\n+import static org.apache.commons.io.FileUtils.readFileToString;\n+import static org.apache.commons.io.FileUtils.writeStringToFile;\n+\n+import com.google.common.annotations.VisibleForTesting;\n+import com.google.common.base.Charsets;\n+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;\n+import java.io.BufferedInputStream;\n+import java.io.BufferedOutputStream;\n+import java.io.FileInputStream;\n+import java.io.FileNotFoundException;\n+import java.io.FileOutputStream;\n+import java.io.IOException;\n+import java.nio.file.Path;\n+import java.nio.file.Paths;\n+import java.security.InvalidKeyException;\n+import java.security.MessageDigest;\n+import java.security.NoSuchAlgorithmException;\n+import java.util.HashMap;\n+import java.util.Map;\n+import java.util.zip.ZipEntry;\n+import java.util.zip.ZipInputStream;\n+import java.util.zip.ZipOutputStream;\n+import javax.crypto.Cipher;\n+import javax.crypto.CipherInputStream;\n+import javax.crypto.CipherOutputStream;\n+import javax.crypto.KeyGenerator;\n+import javax.crypto.NoSuchPaddingException;\n+import javax.crypto.SecretKey;\n+import javax.crypto.spec.SecretKeySpec;\n+import org.apache.commons.codec.DecoderException;\n+import org.apache.commons.io.IOUtils;\n+import org.codice.ddf.migration.MigrationException;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+public class ZipUtils {\n+\n+  private static final Logger LOGGER = LoggerFactory.getLogger(ZipUtils.class);\n+\n+  private static final String IMPORT_KEY_PADDING_ERROR =\n+      \"Import error: invalid padding used for import key {}.\";\n+\n+  private static final String IMPORT_KEY_ALGORITHM_ERROR =\n+      \"Import error: invalid algorithm used for import key {}.\";\n+\n+  private static final String EXPORT_KEY_PADDING_ERROR =\n+      \"Export error: invalid padding used for export key\";\n+\n+  private static final String EXPORT_KEY_ALGORITHM_ERROR =\n+      \"Export error: invalid algorithm used for export key\";\n+\n+  @VisibleForTesting static final String KEY_ALGORITHM = \"AES\";\n+\n+  @VisibleForTesting static final String CIPHER_ALGORITHM = \"AES/ECB/PKCS5Padding\";\n+\n+  @VisibleForTesting static final String DECRYPTION_KEY_FILE_NAME = \"export.key\";\n+\n+  @VisibleForTesting static final String CHECKSUM_FILE_EXTENSION = \".sha256\";\n+\n+  @VisibleForTesting static final String CHECKSUM_DIGEST_ALGORITHM = \"SHA-256\";\n+\n+  /**\n+   * Streams the contents of a {@link ZipInputStream} as a {@link Map} where the content of each\n+   * {@link ZipEntry} is stored inside a key corresponding to each {@link ZipEntry}'s name\n+   *\n+   * @param in the {@link ZipInputStream} to retrieve the entries from\n+   * @return the stream of entries\n+   */\n+  public static Map<ZipEntry, byte[]> entriesFrom(ZipInputStream in) {\n+    ZipEntry entry;\n+    Map<ZipEntry, byte[]> entries = new HashMap<>();\n+    try {\n+      while ((entry = in.getNextEntry()) != null) {\n+        if (!entry.isDirectory()) {\n+          byte[] content = IOUtils.toByteArray(in);\n+          entries.put(entry, content);\n+        }\n+      }\n+    } catch (IOException e) {","path":"platform/migration/platform-migration/src/main/java/org/codice/ddf/configuration/migration/ZipUtils.java","position":96,"original_position":96,"commit_id":"e07a0300a43d4e5a86699daa42d0ea970b2a6446","original_commit_id":"c4b2b4376446e2032f77409bb42583266482e961","user":{"login":"oconnormi","id":3409759,"avatar_url":"https://avatars3.githubusercontent.com/u/3409759?v=4","gravatar_id":"","url":"https://api.github.com/users/oconnormi","html_url":"https://github.com/oconnormi","followers_url":"https://api.github.com/users/oconnormi/followers","following_url":"https://api.github.com/users/oconnormi/following{/other_user}","gists_url":"https://api.github.com/users/oconnormi/gists{/gist_id}","starred_url":"https://api.github.com/users/oconnormi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oconnormi/subscriptions","organizations_url":"https://api.github.com/users/oconnormi/orgs","repos_url":"https://api.github.com/users/oconnormi/repos","events_url":"https://api.github.com/users/oconnormi/events{/privacy}","received_events_url":"https://api.github.com/users/oconnormi/received_events","type":"User","site_admin":false},"body":"@paouelle at the moment I'm kinda torn on this one. Part of me feels that it might be better to handle the IOExceptions from reading the next ZipEntry up front. I can also see the benefit of deferring it though. Im curious would you be alright if the deferral of the error handling could be implemented in a follow-on PR so that we can get the first iteration of the encrypted migration into the baseline first? \r\nIf you feel this behavior is essential for this pr however I will work on finishing my implementation of a ZipFile-like class that will wrap the CipherInputStream for each entry instead of creating a ticket to iterate further on this approach","created_at":"2017-11-13T13:36:08Z","updated_at":"2017-11-13T13:36:09Z","html_url":"https://github.com/codice/ddf/pull/2486#discussion_r150539326","pull_request_url":"https://api.github.com/repos/codice/ddf/pulls/2486","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments/150539326"},"html":{"href":"https://github.com/codice/ddf/pull/2486#discussion_r150539326"},"pull_request":{"href":"https://api.github.com/repos/codice/ddf/pulls/2486"}},"in_reply_to_id":145592379},"pull_request":{"url":"https://api.github.com/repos/codice/ddf/pulls/2486","id":146302286,"html_url":"https://github.com/codice/ddf/pull/2486","diff_url":"https://github.com/codice/ddf/pull/2486.diff","patch_url":"https://github.com/codice/ddf/pull/2486.patch","issue_url":"https://api.github.com/repos/codice/ddf/issues/2486","number":2486,"state":"open","locked":false,"title":"DDF-3376 Add encryption support to the migration framework","user":{"login":"oconnormi","id":3409759,"avatar_url":"https://avatars3.githubusercontent.com/u/3409759?v=4","gravatar_id":"","url":"https://api.github.com/users/oconnormi","html_url":"https://github.com/oconnormi","followers_url":"https://api.github.com/users/oconnormi/followers","following_url":"https://api.github.com/users/oconnormi/following{/other_user}","gists_url":"https://api.github.com/users/oconnormi/gists{/gist_id}","starred_url":"https://api.github.com/users/oconnormi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oconnormi/subscriptions","organizations_url":"https://api.github.com/users/oconnormi/orgs","repos_url":"https://api.github.com/users/oconnormi/repos","events_url":"https://api.github.com/users/oconnormi/events{/privacy}","received_events_url":"https://api.github.com/users/oconnormi/received_events","type":"User","site_admin":false},"body":"#### What does this PR do?\r\n\r\nEncrypts/Decrypts the export created by the migration framework\r\n\r\n#### Who is reviewing it? \r\n\r\n@paouelle @peterhuffer @emmberk @AzGoalie  \r\n\r\n#### Choose 2 committers to review/merge the PR. \r\n\r\n@clockard @coyotesqrl \r\n\r\n#### How should this be tested? (List steps with links to updated documentation)\r\n\r\n1. Install DDF\r\n2. run `migration:export`\r\n3. confirm that `<ddf_home>/exported/exported.enc` and `<ddf_home>/exported/export.key` exist\r\n4. confirm that the `exported.zip` file is encrypted\r\n5. copy the zip and the key to a new system\r\n6. run `migration:import` and confirm success\r\n\r\n#### Any background context you want to provide?\r\n\r\nThe export zip is encrypted/decrypted transparently to all migratables. \r\nThe decryption process happens before any data is passed to the various migratables.\r\nZipFile is no longer used on the import side, instead each ZipEntry is mapped to a byte array corresponding to it's content\r\n\r\n#### What are the relevant tickets?\r\n\r\n[DDF-3376](https://codice.atlassian.net/browse/DDF-3376)\r\n\r\n#### Checklist:\r\n\r\n- [x] Add checksum for export.zip\r\n- [x] Delete key after import process (both success and failure)\r\n- [x] Suppress Sonar warnings\r\n- [x] Log algorithm errors instead of throwing `MigrationException`\r\n- [x] Move filtering of directories to `ZipUtils` instead of in `ImportMigrationContextImpl`\r\n- [ ] Update `ImportMigrationEntryImpl` to take in the content byte array instead of the `ZipEntry`\r\n\r\n#### Review Comment Legend:\r\n- ✏️ (Pencil) This comment is a nitpick or style suggestion, no action required for approval. This comment should provide a suggestion either as an in line code snippet or a gist. \r\n- ❓ (Question Mark) This comment is to gain a clearer understanding of design or code choices, clarification is required but action may not be necessary for approval.\r\n- ❗ (Exclamation Mark) This comment is critical and requires clarification or action before approval.\r\n","created_at":"2017-10-12T20:08:20Z","updated_at":"2017-11-13T13:36:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"019e5e7f1536a287630acb54aa02265dbdfddaeb","assignee":{"login":"coyotesqrl","id":1469860,"avatar_url":"https://avatars2.githubusercontent.com/u/1469860?v=4","gravatar_id":"","url":"https://api.github.com/users/coyotesqrl","html_url":"https://github.com/coyotesqrl","followers_url":"https://api.github.com/users/coyotesqrl/followers","following_url":"https://api.github.com/users/coyotesqrl/following{/other_user}","gists_url":"https://api.github.com/users/coyotesqrl/gists{/gist_id}","starred_url":"https://api.github.com/users/coyotesqrl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coyotesqrl/subscriptions","organizations_url":"https://api.github.com/users/coyotesqrl/orgs","repos_url":"https://api.github.com/users/coyotesqrl/repos","events_url":"https://api.github.com/users/coyotesqrl/events{/privacy}","received_events_url":"https://api.github.com/users/coyotesqrl/received_events","type":"User","site_admin":false},"assignees":[{"login":"coyotesqrl","id":1469860,"avatar_url":"https://avatars2.githubusercontent.com/u/1469860?v=4","gravatar_id":"","url":"https://api.github.com/users/coyotesqrl","html_url":"https://github.com/coyotesqrl","followers_url":"https://api.github.com/users/coyotesqrl/followers","following_url":"https://api.github.com/users/coyotesqrl/following{/other_user}","gists_url":"https://api.github.com/users/coyotesqrl/gists{/gist_id}","starred_url":"https://api.github.com/users/coyotesqrl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coyotesqrl/subscriptions","organizations_url":"https://api.github.com/users/coyotesqrl/orgs","repos_url":"https://api.github.com/users/coyotesqrl/repos","events_url":"https://api.github.com/users/coyotesqrl/events{/privacy}","received_events_url":"https://api.github.com/users/coyotesqrl/received_events","type":"User","site_admin":false},{"login":"clockard","id":5248090,"avatar_url":"https://avatars1.githubusercontent.com/u/5248090?v=4","gravatar_id":"","url":"https://api.github.com/users/clockard","html_url":"https://github.com/clockard","followers_url":"https://api.github.com/users/clockard/followers","following_url":"https://api.github.com/users/clockard/following{/other_user}","gists_url":"https://api.github.com/users/clockard/gists{/gist_id}","starred_url":"https://api.github.com/users/clockard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clockard/subscriptions","organizations_url":"https://api.github.com/users/clockard/orgs","repos_url":"https://api.github.com/users/clockard/repos","events_url":"https://api.github.com/users/clockard/events{/privacy}","received_events_url":"https://api.github.com/users/clockard/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/codice/ddf/pulls/2486/commits","review_comments_url":"https://api.github.com/repos/codice/ddf/pulls/2486/comments","review_comment_url":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}","comments_url":"https://api.github.com/repos/codice/ddf/issues/2486/comments","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/e07a0300a43d4e5a86699daa42d0ea970b2a6446","head":{"label":"oconnormi:DDF-3376","ref":"DDF-3376","sha":"e07a0300a43d4e5a86699daa42d0ea970b2a6446","user":{"login":"oconnormi","id":3409759,"avatar_url":"https://avatars3.githubusercontent.com/u/3409759?v=4","gravatar_id":"","url":"https://api.github.com/users/oconnormi","html_url":"https://github.com/oconnormi","followers_url":"https://api.github.com/users/oconnormi/followers","following_url":"https://api.github.com/users/oconnormi/following{/other_user}","gists_url":"https://api.github.com/users/oconnormi/gists{/gist_id}","starred_url":"https://api.github.com/users/oconnormi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oconnormi/subscriptions","organizations_url":"https://api.github.com/users/oconnormi/orgs","repos_url":"https://api.github.com/users/oconnormi/repos","events_url":"https://api.github.com/users/oconnormi/events{/privacy}","received_events_url":"https://api.github.com/users/oconnormi/received_events","type":"User","site_admin":false},"repo":{"id":40485585,"name":"ddf","full_name":"oconnormi/ddf","owner":{"login":"oconnormi","id":3409759,"avatar_url":"https://avatars3.githubusercontent.com/u/3409759?v=4","gravatar_id":"","url":"https://api.github.com/users/oconnormi","html_url":"https://github.com/oconnormi","followers_url":"https://api.github.com/users/oconnormi/followers","following_url":"https://api.github.com/users/oconnormi/following{/other_user}","gists_url":"https://api.github.com/users/oconnormi/gists{/gist_id}","starred_url":"https://api.github.com/users/oconnormi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oconnormi/subscriptions","organizations_url":"https://api.github.com/users/oconnormi/orgs","repos_url":"https://api.github.com/users/oconnormi/repos","events_url":"https://api.github.com/users/oconnormi/events{/privacy}","received_events_url":"https://api.github.com/users/oconnormi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/oconnormi/ddf","description":"The Distributed Data Framework - Distribution, SDK, and Test","fork":true,"url":"https://api.github.com/repos/oconnormi/ddf","forks_url":"https://api.github.com/repos/oconnormi/ddf/forks","keys_url":"https://api.github.com/repos/oconnormi/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/oconnormi/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/oconnormi/ddf/teams","hooks_url":"https://api.github.com/repos/oconnormi/ddf/hooks","issue_events_url":"https://api.github.com/repos/oconnormi/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/oconnormi/ddf/events","assignees_url":"https://api.github.com/repos/oconnormi/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/oconnormi/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/oconnormi/ddf/tags","blobs_url":"https://api.github.com/repos/oconnormi/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/oconnormi/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/oconnormi/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/oconnormi/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/oconnormi/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/oconnormi/ddf/languages","stargazers_url":"https://api.github.com/repos/oconnormi/ddf/stargazers","contributors_url":"https://api.github.com/repos/oconnormi/ddf/contributors","subscribers_url":"https://api.github.com/repos/oconnormi/ddf/subscribers","subscription_url":"https://api.github.com/repos/oconnormi/ddf/subscription","commits_url":"https://api.github.com/repos/oconnormi/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/oconnormi/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/oconnormi/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/oconnormi/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/oconnormi/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/oconnormi/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/oconnormi/ddf/merges","archive_url":"https://api.github.com/repos/oconnormi/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/oconnormi/ddf/downloads","issues_url":"https://api.github.com/repos/oconnormi/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/oconnormi/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/oconnormi/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/oconnormi/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/oconnormi/ddf/labels{/name}","releases_url":"https://api.github.com/repos/oconnormi/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/oconnormi/ddf/deployments","created_at":"2015-08-10T14:00:20Z","updated_at":"2016-01-12T15:07:08Z","pushed_at":"2017-11-13T13:22:18Z","git_url":"git://github.com/oconnormi/ddf.git","ssh_url":"git@github.com:oconnormi/ddf.git","clone_url":"https://github.com/oconnormi/ddf.git","svn_url":"https://github.com/oconnormi/ddf","homepage":"","size":191734,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"codice:master","ref":"master","sha":"d11b54ffb67f1d7047236afad3bea994ec9e7b87","user":{"login":"codice","id":2386734,"avatar_url":"https://avatars2.githubusercontent.com/u/2386734?v=4","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"repo":{"id":15173563,"name":"ddf","full_name":"codice/ddf","owner":{"login":"codice","id":2386734,"avatar_url":"https://avatars2.githubusercontent.com/u/2386734?v=4","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codice/ddf","description":"DDF Distributed Data Framework - an open source, modular integration framework.","fork":false,"url":"https://api.github.com/repos/codice/ddf","forks_url":"https://api.github.com/repos/codice/ddf/forks","keys_url":"https://api.github.com/repos/codice/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codice/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codice/ddf/teams","hooks_url":"https://api.github.com/repos/codice/ddf/hooks","issue_events_url":"https://api.github.com/repos/codice/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/codice/ddf/events","assignees_url":"https://api.github.com/repos/codice/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/codice/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/codice/ddf/tags","blobs_url":"https://api.github.com/repos/codice/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codice/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codice/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/codice/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/codice/ddf/languages","stargazers_url":"https://api.github.com/repos/codice/ddf/stargazers","contributors_url":"https://api.github.com/repos/codice/ddf/contributors","subscribers_url":"https://api.github.com/repos/codice/ddf/subscribers","subscription_url":"https://api.github.com/repos/codice/ddf/subscription","commits_url":"https://api.github.com/repos/codice/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/codice/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/codice/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/codice/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/codice/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/codice/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codice/ddf/merges","archive_url":"https://api.github.com/repos/codice/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codice/ddf/downloads","issues_url":"https://api.github.com/repos/codice/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/codice/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/codice/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/codice/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codice/ddf/labels{/name}","releases_url":"https://api.github.com/repos/codice/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/codice/ddf/deployments","created_at":"2013-12-13T20:38:28Z","updated_at":"2017-10-24T19:29:40Z","pushed_at":"2017-11-13T13:22:20Z","git_url":"git://github.com/codice/ddf.git","ssh_url":"git@github.com:codice/ddf.git","clone_url":"https://github.com/codice/ddf.git","svn_url":"https://github.com/codice/ddf","homepage":"http://ddf.codice.org","size":360252,"stargazers_count":67,"watchers_count":67,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":121,"mirror_url":null,"archived":false,"open_issues_count":48,"forks":121,"open_issues":48,"watchers":67,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/2486"},"html":{"href":"https://github.com/codice/ddf/pull/2486"},"issue":{"href":"https://api.github.com/repos/codice/ddf/issues/2486"},"comments":{"href":"https://api.github.com/repos/codice/ddf/issues/2486/comments"},"review_comments":{"href":"https://api.github.com/repos/codice/ddf/pulls/2486/comments"},"review_comment":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/codice/ddf/pulls/2486/commits"},"statuses":{"href":"https://api.github.com/repos/codice/ddf/statuses/e07a0300a43d4e5a86699daa42d0ea970b2a6446"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"oconnormi"}}