Skip to content

Commit ad88be0

Browse files
committed
Merge pull request #1446 from dhermes/fix-1445
Allowing pyOpenSSL import to fail for GAE.
2 parents ac33853 + 7921ebc commit ad88be0

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

gcloud/credentials.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
import six
2020
from six.moves.urllib.parse import urlencode # pylint: disable=F0401
2121

22-
from OpenSSL import crypto
22+
try:
23+
from OpenSSL import crypto
24+
except ImportError: # pragma: NO COVER
25+
# pyOpenSSL can't be installed on App Engine, but it will not
26+
# be needed there since app_identity is used.
27+
crypto = None
2328

2429
from oauth2client import client
2530
from oauth2client.client import _get_application_default_credential_from_file
@@ -170,6 +175,7 @@ def _get_pem_key(credentials):
170175
:rtype: :class:`OpenSSL.crypto.PKey`
171176
:returns: A PKey object used to sign text.
172177
:raises: `TypeError` if `credentials` is the wrong type.
178+
`EnvironmentError` if `crypto` did not import successfully.
173179
"""
174180
if isinstance(credentials, client.SignedJwtAssertionCredentials):
175181
# Take our PKCS12 (.p12) text and convert to PEM text.
@@ -181,6 +187,9 @@ def _get_pem_key(credentials):
181187
raise TypeError((credentials,
182188
'not a valid service account credentials type'))
183189

190+
if crypto is None:
191+
raise EnvironmentError(
192+
'pyOpenSSL must be installed to load a private key')
184193
return crypto.load_privatekey(crypto.FILETYPE_PEM, pem_text)
185194

186195

@@ -198,6 +207,7 @@ def _get_signature_bytes(credentials, string_to_sign):
198207
199208
:rtype: bytes
200209
:returns: Signed bytes produced by the credentials.
210+
:raises: `EnvironmentError` if `crypto` did not import successfully.
201211
"""
202212
if isinstance(credentials, _GAECreds):
203213
_, signed_bytes = app_identity.sign_blob(string_to_sign)
@@ -207,6 +217,10 @@ def _get_signature_bytes(credentials, string_to_sign):
207217
pkey = _get_pem_key(credentials)
208218
if not isinstance(string_to_sign, six.binary_type):
209219
string_to_sign = string_to_sign.encode('utf-8')
220+
if crypto is None:
221+
raise EnvironmentError(
222+
'pyOpenSSL must be installed to sign content using a '
223+
'private key')
210224
return crypto.sign(pkey, string_to_sign, 'SHA256')
211225

212226

gcloud/test_credentials.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,21 @@ def test_gae_type(self):
350350
self.assertEqual(signed_bytes, STRING_TO_SIGN)
351351
self.assertEqual(APP_IDENTITY._strings_signed, [STRING_TO_SIGN])
352352

353+
def test_without_pyopenssl(self):
354+
from gcloud._testing import _Monkey
355+
from gcloud import credentials as credentials_mod
356+
357+
mock_called = []
358+
credentials = object()
359+
360+
def mock_pem_key(local_creds):
361+
mock_called.append(local_creds)
362+
363+
with _Monkey(credentials_mod, crypto=None, _get_pem_key=mock_pem_key):
364+
with self.assertRaises(EnvironmentError):
365+
self._callFUT(credentials, b'STRING_TO_SIGN')
366+
self.assertEqual(mock_called, [credentials])
367+
353368

354369
class Test__get_service_account_name(unittest2.TestCase):
355370

@@ -520,6 +535,25 @@ def _get_private_key(private_key_pkcs8_text):
520535
[(openssl_crypto.FILETYPE_PEM, PRIVATE_TEXT)])
521536
self.assertEqual(openssl_crypto._signed, [])
522537

538+
def test_without_pyopenssl(self):
539+
from oauth2client import service_account
540+
from gcloud._testing import _Monkey
541+
from gcloud import credentials as credentials_mod
542+
543+
PRIVATE_TEXT = 'dummy_private_key_pkcs8_text'
544+
545+
def _get_private_key(private_key_pkcs8_text):
546+
return private_key_pkcs8_text
547+
548+
with _Monkey(service_account, _get_private_key=_get_private_key):
549+
credentials = service_account._ServiceAccountCredentials(
550+
'dummy_service_account_id', 'dummy_service_account_email',
551+
'dummy_private_key_id', PRIVATE_TEXT, '')
552+
553+
with _Monkey(credentials_mod, crypto=None):
554+
with self.assertRaises(EnvironmentError):
555+
self._callFUT(credentials)
556+
523557

524558
class Test__get_expiration_seconds(unittest2.TestCase):
525559

0 commit comments

Comments
 (0)