Skip to content

Commit 9867964

Browse files
ryanmatsdpebot
authored andcommitted
Storage Encryption Key Rotation Sample using Veneer + Tests (GoogleCloudPlatform#672)
1 parent 504ae46 commit 9867964

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

storage/cloud-client/encryption.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,27 @@ def rotate_encryption_key(bucket_name, blob_name, base64_encryption_key,
9797
base64_new_encryption_key):
9898
"""Performs a key rotation by re-writing an encrypted blob with a new
9999
encryption key."""
100-
raise NotImplementedError(
101-
'This is currently not available using the Cloud Client Library.')
100+
storage_client = storage.Client()
101+
bucket = storage_client.get_bucket(bucket_name)
102+
current_encryption_key = base64.b64decode(base64_encryption_key)
103+
new_encryption_key = base64.b64decode(base64_new_encryption_key)
104+
105+
# Both source_blob and destination_blob refer to the same storage object,
106+
# but destination_blob has the new encryption key.
107+
source_blob = Blob(
108+
blob_name, bucket, encryption_key=current_encryption_key)
109+
destination_blob = Blob(
110+
blob_name, bucket, encryption_key=new_encryption_key)
111+
112+
token = None
113+
114+
while True:
115+
token, bytes_rewritten, total_bytes = destination_blob.rewrite(
116+
source_blob, token=token)
117+
if token is None:
118+
break
119+
120+
print('Key rotation complete for Blob {}'.format(blob_name))
102121

103122

104123
if __name__ == '__main__':

storage/cloud-client/encryption_test.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@
1616
import tempfile
1717

1818
from google.cloud import storage
19+
from google.cloud.storage import Blob
1920
import pytest
2021

2122
import encryption
2223

24+
2325
TEST_ENCRYPTION_KEY = 'brtJUWneL92g5q0N2gyDSnlPSYAiIVZ/cWgjyZNeMy0='
2426
TEST_ENCRYPTION_KEY_DECODED = base64.b64decode(TEST_ENCRYPTION_KEY)
2527

28+
TEST_ENCRYPTION_KEY_2 = 'o4OD7SWCaPjfeEGhAY+YCgMdY9UW+OJ8mvfWD9lNtO4='
29+
TEST_ENCRYPTION_KEY_2_DECODED = base64.b64decode(TEST_ENCRYPTION_KEY_2)
30+
2631

2732
def test_generate_encryption_key(capsys):
2833
encryption.generate_encryption_key()
@@ -47,9 +52,9 @@ def test_upload_encrypted_blob(cloud_config):
4752
def test_blob(cloud_config):
4853
"""Provides a pre-existing blob in the test bucket."""
4954
bucket = storage.Client().bucket(cloud_config.storage_bucket)
50-
blob = bucket.blob('encryption_test_sigil')
55+
blob = Blob('encryption_test_sigil',
56+
bucket, encryption_key=TEST_ENCRYPTION_KEY_DECODED)
5157
content = 'Hello, is it me you\'re looking for?'
52-
blob.encryption_key = TEST_ENCRYPTION_KEY_DECODED
5358
blob.upload_from_string(content)
5459
return blob.name, content
5560

@@ -65,3 +70,22 @@ def test_download_blob(test_blob, cloud_config):
6570

6671
downloaded_content = dest_file.read().decode('utf-8')
6772
assert downloaded_content == test_blob_content
73+
74+
75+
def test_rotate_encryption_key(test_blob, cloud_config):
76+
test_blob_name, test_blob_content = test_blob
77+
encryption.rotate_encryption_key(
78+
cloud_config.storage_bucket,
79+
test_blob_name,
80+
TEST_ENCRYPTION_KEY,
81+
TEST_ENCRYPTION_KEY_2)
82+
83+
with tempfile.NamedTemporaryFile() as dest_file:
84+
encryption.download_encrypted_blob(
85+
cloud_config.storage_bucket,
86+
test_blob_name,
87+
dest_file.name,
88+
TEST_ENCRYPTION_KEY_2)
89+
90+
downloaded_content = dest_file.read().decode('utf-8')
91+
assert downloaded_content == test_blob_content

0 commit comments

Comments
 (0)