Skip to content

Commit 4d9c490

Browse files
authored
fix: KMS Bad Key error when using existing Blob context to overwrite object (#507)
* fix: KMS Bad Key error when using existing Blob context to overwrite object * fix: KMS Bad Key error when using existing Blob context to overwrite object * fix: address review changes * fix: address review changes * address review changes * fix: address additional comments * fix: add the change inside HttpStorageRpc
1 parent 9415bb7 commit 4d9c490

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

google-cloud-storage/src/main/java/com/google/cloud/storage/BlobInfo.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public StorageObject apply(BlobInfo blobInfo) {
7272
return blobInfo.toPb();
7373
}
7474
};
75-
7675
private static final long serialVersionUID = -5625857076205028976L;
7776
private final BlobId blobId;
7877
private final String generatedId;
@@ -323,6 +322,23 @@ public Builder setTimeStorageClassUpdated(Long timeStorageClassUpdated) {
323322

324323
abstract Builder setCustomerEncryption(CustomerEncryption customerEncryption);
325324

325+
/**
326+
* Sets a customer-managed key for server-side encryption of the blob. Note that when a KMS key
327+
* is used to encrypt Cloud Storage object, object resource metadata will store the version of
328+
* the KMS cryptographic. If a {@code Blob} with KMS Key metadata is used to upload a new
329+
* version of the object then the existing kmsKeyName version value can't be used in the upload
330+
* request and the client instead ignores it.
331+
*
332+
* <p>Example of setting the KMS key name
333+
*
334+
* <pre>{@code
335+
* String bucketName = "my-unique-bucket";
336+
* String blobName = "my-blob-name";
337+
* String kmsKeyName = "projects/project-id/locations/us/keyRings/lab1/cryptoKeys/test-key"
338+
* BlobInfo blobInfo = BlobInfo.newBuilder(bucketName, blobName).build();
339+
* Blob blob = storage.create(blobInfo, Storage.BlobTargetOption.kmsKeyName(kmsKeyName));
340+
* }</pre>
341+
*/
326342
abstract Builder setKmsKeyName(String kmsKeyName);
327343

328344
/** Sets the blob's event-based hold. */
@@ -1095,7 +1111,6 @@ public ObjectAccessControl apply(Acl acl) {
10951111
if (retentionExpirationTime != null) {
10961112
storageObject.setRetentionExpirationTime(new DateTime(retentionExpirationTime));
10971113
}
1098-
10991114
storageObject.setKmsKeyName(kmsKeyName);
11001115
storageObject.setEventBasedHold(eventBasedHold);
11011116
storageObject.setTemporaryHold(temporaryHold);

google-cloud-storage/src/main/java/com/google/cloud/storage/spi/v1/HttpStorageRpc.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,10 @@ public String open(StorageObject object, Map<Option, ?> options) {
832832
Span span = startSpan(HttpStorageRpcSpans.SPAN_NAME_OPEN);
833833
Scope scope = tracer.withSpan(span);
834834
try {
835+
String kmsKeyName = object.getKmsKeyName();
836+
if (kmsKeyName != null && kmsKeyName.contains("cryptoKeyVersions")) {
837+
object.setKmsKeyName("");
838+
}
835839
Insert req = storage.objects().insert(object.getBucket(), object);
836840
GenericUrl url = req.buildHttpRequest().getUrl();
837841
String scheme = url.getScheme();

google-cloud-storage/src/test/java/com/google/cloud/storage/it/ITStorageTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3605,4 +3605,23 @@ public void testBlobTimeStorageClassUpdated() {
36053605
.isEqualTo(updatedBlob1.getTimeStorageClassUpdated());
36063606
assertThat(updatedBlob2.delete()).isTrue();
36073607
}
3608+
3609+
@Test
3610+
public void testWriterWithKmsKeyName() throws IOException {
3611+
// Write an empty object with a kmsKeyName.
3612+
String blobName = "test-empty-blob";
3613+
BlobInfo blobInfo = BlobInfo.newBuilder(BUCKET, blobName).build();
3614+
Blob blob =
3615+
storage.create(blobInfo, Storage.BlobTargetOption.kmsKeyName(kmsKeyOneResourcePath));
3616+
3617+
// Create a writer using blob that already has metadata received from Storage API.
3618+
int numberOfBytes;
3619+
try (WriteChannel writer = blob.writer()) {
3620+
byte[] content = BLOB_STRING_CONTENT.getBytes(UTF_8);
3621+
numberOfBytes = writer.write(ByteBuffer.wrap(content, 0, content.length));
3622+
}
3623+
assertThat(numberOfBytes).isEqualTo(27);
3624+
assertThat(blob.getKmsKeyName()).isNotNull();
3625+
assertThat(storage.delete(BUCKET, blobName)).isTrue();
3626+
}
36083627
}

0 commit comments

Comments
 (0)