From ac2e7719580b41c8203a1acc9699add025c1f9a7 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Thu, 25 Jul 2019 00:08:03 -0700 Subject: [PATCH 1/2] Add CSEK decryption for storage.get(BlobId,..) --- .../java/com/google/cloud/storage/Blob.java | 2 ++ .../com/google/cloud/storage/Storage.java | 31 +++++++++++++++++++ .../cloud/storage/spi/v1/HttpStorageRpc.java | 7 ++--- .../cloud/storage/it/ITStorageTest.java | 6 +++- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java index da7e27a72851..965f15e89aed 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Blob.java @@ -119,6 +119,8 @@ private Storage.BlobGetOption toGetOption(BlobInfo blobInfo) { return Storage.BlobGetOption.metagenerationNotMatch(blobInfo.getMetageneration()); case USER_PROJECT: return Storage.BlobGetOption.userProject((String) getValue()); + case CUSTOMER_SUPPLIED_KEY: + return Storage.BlobGetOption.decryptionKey((String) getValue()); default: throw new AssertionError("Unexpected enum value"); } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 82dc0775ad32..8a2c56ee9c0b 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -748,6 +748,25 @@ public static BlobGetOption fields(BlobField... fields) { public static BlobGetOption userProject(String userProject) { return new BlobGetOption(StorageRpc.Option.USER_PROJECT, userProject); } + + /** + * Returns an option to set a customer-supplied AES256 key for server-side decryption of the + * blob. + */ + public static BlobGetOption decryptionKey(Key key) { + String base64Key = BaseEncoding.base64().encode(key.getEncoded()); + return new BlobGetOption(StorageRpc.Option.CUSTOMER_SUPPLIED_KEY, base64Key); + } + + /** + * Returns an option to set a customer-supplied AES256 key for server-side decryption of the + * blob. + * + * @param key the AES256 encoded in base64 + */ + public static BlobGetOption decryptionKey(String key) { + return new BlobGetOption(StorageRpc.Option.CUSTOMER_SUPPLIED_KEY, key); + } } /** Class for specifying bucket list options. */ @@ -1612,6 +1631,18 @@ Blob create( * Blob blob = storage.get(blobId, BlobGetOption.metagenerationMatch(blobMetageneration)); * } * + *

Example of getting information on a blob encrypted using Customer Supplied Encryption Keys, only if supplied + * Decrpytion Key decrypts the blob successfully, otherwise a {@link StorageException} is thrown. + * For more information review ttps://cloud.google.com/storage/docs/encryption#customer-supplied_encryption_keys + * + *

{@code
+   * String bucketName = "my_unique_bucket";
+   * String blobName = "my_blob_name";
+   * String blobEncryptionKey = "";
+   * BlobId blobId = BlobId.of(bucketName, blobName);
+   * Blob blob = storage.get(blobId, BlobGetOption.decryptionKey(blobEncryptionKey));
+   * }
+ * * @throws StorageException upon failure */ Blob get(BlobId blob, BlobGetOption... options); diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java index d162b33c5c7f..40a2c44d6d3e 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java @@ -414,10 +414,9 @@ public Bucket get(Bucket bucket, Map options) { private Storage.Objects.Get getCall(StorageObject object, Map options) throws IOException { - return storage - .objects() - .get(object.getBucket(), object.getName()) - .setGeneration(object.getGeneration()) + Storage.Objects.Get get = storage.objects().get(object.getBucket(), object.getName()); + setEncryptionHeaders(get.getRequestHeaders(), ENCRYPTION_KEY_PREFIX, options); + return get.setGeneration(object.getGeneration()) .setProjection(DEFAULT_PROJECTION) .setIfMetagenerationMatch(Option.IF_METAGENERATION_MATCH.getLong(options)) .setIfMetagenerationNotMatch(Option.IF_METAGENERATION_NOT_MATCH.getLong(options)) diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java index 8b2d627b23db..633663a17096 100644 --- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java +++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java @@ -481,7 +481,7 @@ public void testCreateBlobMd5Crc32cFromHexString() { } @Test - public void testCreateBlobWithEncryptionKey() { + public void testCreateGetBlobWithEncryptionKey() { String blobName = "test-create-with-customer-key-blob"; BlobInfo blob = BlobInfo.newBuilder(BUCKET, blobName).build(); Blob remoteBlob = @@ -492,6 +492,10 @@ public void testCreateBlobWithEncryptionKey() { byte[] readBytes = storage.readAllBytes(BUCKET, blobName, Storage.BlobSourceOption.decryptionKey(BASE64_KEY)); assertArrayEquals(BLOB_BYTE_CONTENT, readBytes); + remoteBlob = storage.get(blob.getBlobId(), Storage.BlobGetOption.decryptionKey(BASE64_KEY), + Storage.BlobGetOption.fields(BlobField.CRC32C, BlobField.MD5HASH)); + assertNotNull(remoteBlob.getCrc32c()); + assertNotNull(remoteBlob.getMd5()); } @Test From d5af46fbd77fe16bd852772933652ed5d5eb7199 Mon Sep 17 00:00:00 2001 From: Frank Natividad Date: Thu, 25 Jul 2019 22:42:23 -0700 Subject: [PATCH 2/2] Fix lint issues --- .../main/java/com/google/cloud/storage/Storage.java | 13 ++++++++----- .../com/google/cloud/storage/it/ITStorageTest.java | 5 ++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 8a2c56ee9c0b..e55bdde0607f 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -1631,11 +1631,14 @@ Blob create( * Blob blob = storage.get(blobId, BlobGetOption.metagenerationMatch(blobMetageneration)); * } * - *

Example of getting information on a blob encrypted using Customer Supplied Encryption Keys, only if supplied - * Decrpytion Key decrypts the blob successfully, otherwise a {@link StorageException} is thrown. - * For more information review ttps://cloud.google.com/storage/docs/encryption#customer-supplied_encryption_keys - * - *

{@code
+   * 

Example of getting information on a blob encrypted using Customer Supplied Encryption Keys, + * only if supplied Decrpytion Key decrypts the blob successfully, otherwise a {@link + * StorageException} is thrown. For more information review + * + * @see Encrypted + * Elements + *

{@code
    * String bucketName = "my_unique_bucket";
    * String blobName = "my_blob_name";
    * String blobEncryptionKey = "";
diff --git a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
index 633663a17096..ff26c558d7f6 100644
--- a/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
+++ b/google-cloud-clients/google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java
@@ -492,7 +492,10 @@ public void testCreateGetBlobWithEncryptionKey() {
     byte[] readBytes =
         storage.readAllBytes(BUCKET, blobName, Storage.BlobSourceOption.decryptionKey(BASE64_KEY));
     assertArrayEquals(BLOB_BYTE_CONTENT, readBytes);
-    remoteBlob = storage.get(blob.getBlobId(), Storage.BlobGetOption.decryptionKey(BASE64_KEY),
+    remoteBlob =
+        storage.get(
+            blob.getBlobId(),
+            Storage.BlobGetOption.decryptionKey(BASE64_KEY),
             Storage.BlobGetOption.fields(BlobField.CRC32C, BlobField.MD5HASH));
     assertNotNull(remoteBlob.getCrc32c());
     assertNotNull(remoteBlob.getMd5());