Skip to content

Commit 6110b59

Browse files
fixit: Clean up Python sample at compute/encryption (#10118)
Co-authored-by: Andrew Ferlitsch <aferlitsch@gmail.com>
1 parent 97f8519 commit 6110b59

File tree

3 files changed

+117
-45
lines changed

3 files changed

+117
-45
lines changed
Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,122 @@
11
#!/usr/bin/env python
22

3-
# Copyright 2016 Google Inc. All Rights Reserved.
3+
# Copyright 2016 Google LLC
44
#
5-
# Licensed under the Apache License, Version 2.0 (the "License");
6-
# you may not use this file except in compliance with the License.
7-
# You may obtain a copy of the License at
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
88
#
9-
# http://www.apache.org/licenses/LICENSE-2.0
9+
# http://www.apache.org/licenses/LICENSE-2.0
1010
#
11-
# Unless required by applicable law or agreed to in writing, software
12-
# distributed under the License is distributed on an "AS IS" BASIS,
13-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14-
# See the License for the specific language governing permissions and
15-
# limitations under the License.
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
1616

1717
"""Example of authenticating using access tokens directly on Compute Engine.
1818
1919
For more information, see the README.md under /compute.
2020
"""
2121

2222
# [START all]
23-
23+
# [START compute_generate_wrapped_rsa_key]
2424
import argparse
2525
import base64
2626
import os
27+
from typing import Optional
2728

2829
from cryptography import x509
2930
from cryptography.hazmat.backends import default_backend
3031
from cryptography.hazmat.primitives import hashes
3132
from cryptography.hazmat.primitives.asymmetric import padding
33+
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
3234
import requests
3335

3436

3537
GOOGLE_PUBLIC_CERT_URL = (
36-
'https://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem')
38+
"https://cloud-certs.storage.googleapis.com/google-cloud-csek-ingress.pem"
39+
)
40+
3741

42+
def get_google_public_cert_key() -> RSAPublicKey:
43+
"""
44+
Downloads the Google public certificate.
3845
39-
def get_google_public_cert_key():
46+
Returns:
47+
RSAPublicKey object with the Google public certificate.
48+
"""
4049
r = requests.get(GOOGLE_PUBLIC_CERT_URL)
4150
r.raise_for_status()
4251

4352
# Load the certificate.
44-
certificate = x509.load_pem_x509_certificate(
45-
r.content, default_backend())
53+
certificate = x509.load_pem_x509_certificate(r.content, default_backend())
4654

4755
# Get the certicate's public key.
4856
public_key = certificate.public_key()
4957

5058
return public_key
5159

5260

53-
def wrap_rsa_key(public_key, private_key_bytes):
54-
# Use the Google public key to encrypt the customer private key.
55-
# This means that only the Google private key is capable of decrypting
56-
# the customer private key.
61+
def wrap_rsa_key(public_key: RSAPublicKey, private_key_bytes: bytes) -> bytes:
62+
"""
63+
Use the Google public key to encrypt the customer private key.
64+
65+
This means that only the Google private key is capable of decrypting
66+
the customer private key.
67+
68+
Args:
69+
public_key: The public key to use for encrypting.
70+
private_key_bytes: The private key to be encrypted.
71+
72+
Returns:
73+
private_key_bytes encrypted using the public_key. Encoded using
74+
base64.
75+
"""
5776
wrapped_key = public_key.encrypt(
5877
private_key_bytes,
5978
padding.OAEP(
6079
mgf=padding.MGF1(algorithm=hashes.SHA1()),
6180
algorithm=hashes.SHA1(),
62-
label=None))
81+
label=None,
82+
),
83+
)
6384
encoded_wrapped_key = base64.b64encode(wrapped_key)
6485
return encoded_wrapped_key
6586

6687

67-
def main(key_file):
88+
def main(key_file: Optional[str]) -> None:
89+
"""
90+
This script will encrypt a private key with Google public key.
91+
92+
Args:
93+
key_file: path to a file containing your private key. If not
94+
provided, a new key will be generated (256 bit).
95+
"""
6896
# Generate a new 256-bit private key if no key is specified.
6997
if not key_file:
7098
customer_key_bytes = os.urandom(32)
7199
else:
72-
with open(key_file, 'rb') as f:
100+
with open(key_file, "rb") as f:
73101
customer_key_bytes = f.read()
74102

75103
google_public_key = get_google_public_cert_key()
76104
wrapped_rsa_key = wrap_rsa_key(google_public_key, customer_key_bytes)
77105

78-
print('Base-64 encoded private key: {}'.format(
79-
base64.b64encode(customer_key_bytes).decode('utf-8')))
80-
print('Wrapped RSA key: {}'.format(wrapped_rsa_key.decode('utf-8')))
106+
b64_key = base64.b64encode(customer_key_bytes).decode("utf-8")
107+
108+
print(f"Base-64 encoded private key: {b64_key}")
109+
print(f"Wrapped RSA key: {wrapped_rsa_key.decode('utf-8')}")
81110

82111

83-
if __name__ == '__main__':
112+
if __name__ == "__main__":
84113
parser = argparse.ArgumentParser(
85-
description=__doc__,
86-
formatter_class=argparse.RawDescriptionHelpFormatter)
87-
parser.add_argument(
88-
'--key_file', help='File containing your binary private key.')
114+
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
115+
)
116+
parser.add_argument("--key_file", help="File containing your binary private key.")
89117

90118
args = parser.parse_args()
91119

92120
main(args.key_file)
121+
# [END compute_generate_wrapped_rsa_key]
93122
# [END all]

compute/encryption/generate_wrapped_rsa_key_test.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,38 @@
1919

2020
import generate_wrapped_rsa_key
2121

22-
PROJECT = os.environ['GOOGLE_CLOUD_PROJECT']
22+
PROJECT = os.environ["GOOGLE_CLOUD_PROJECT"]
2323

2424

25-
def test_main():
25+
def test_main() -> None:
2626
generate_wrapped_rsa_key.main(None)
2727

2828

29-
def test_create_disk():
30-
compute = googleapiclient.discovery.build('compute', 'beta')
29+
def test_create_disk() -> None:
30+
compute = googleapiclient.discovery.build("compute", "beta")
3131

3232
# Generate the key.
3333
key_bytes = os.urandom(32)
3434
google_public_key = generate_wrapped_rsa_key.get_google_public_cert_key()
3535
wrapped_rsa_key = generate_wrapped_rsa_key.wrap_rsa_key(
36-
google_public_key, key_bytes)
37-
disk_name = f'new-encrypted-disk-{uuid.uuid4().hex}'
36+
google_public_key, key_bytes
37+
)
38+
disk_name = f"new-encrypted-disk-{uuid.uuid4().hex}"
3839

3940
try:
4041
# Create the disk, if the encryption key is invalid, this will raise.
4142
compute.disks().insert(
4243
project=PROJECT,
43-
zone='us-central1-f',
44+
zone="us-central1-f",
4445
body={
45-
'name': disk_name,
46-
'diskEncryptionKey': {
47-
'rsaEncryptedKey': wrapped_rsa_key.decode('utf-8')
48-
}
49-
}).execute()
46+
"name": disk_name,
47+
"diskEncryptionKey": {
48+
"rsaEncryptedKey": wrapped_rsa_key.decode("utf-8")
49+
},
50+
},
51+
).execute()
5052
finally:
5153
# Delete the disk.
5254
compute.disks().delete(
53-
project=PROJECT,
54-
zone='us-central1-f',
55-
disk=disk_name).execute()
55+
project=PROJECT, zone="us-central1-f", disk=disk_name
56+
).execute()

compute/encryption/noxfile_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {},
42+
}

0 commit comments

Comments
 (0)