Skip to content
This repository was archived by the owner on Mar 6, 2026. It is now read-only.

Commit 5b4e9c8

Browse files
author
Jon Wayne Parrott
authored
Fix issue where GAE Signer erroneously returns a tuple from sign() (#109)
1 parent 924191c commit 5b4e9c8

2 files changed

Lines changed: 46 additions & 5 deletions

File tree

google/auth/app_engine.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,30 @@
3434

3535

3636
class Signer(object):
37-
"""Signs messages using the App Engine app identity service.
37+
"""Signs messages using the App Engine App Identity service.
3838
3939
This can be used in place of :class:`google.auth.crypt.Signer` when
4040
running in the App Engine standard environment.
41+
42+
.. warning::
43+
The App Identity service signs bytes using Google-managed keys.
44+
Because of this it's possible that the key used to sign bytes will
45+
change. In some cases this change can occur between successive calls
46+
to :attr:`key_id` and :meth:`sign`. This could result in a signature
47+
that was signed with a different key than the one indicated by
48+
:attr:`key_id`. It's recommended that if you use this in your code
49+
that you account for this behavior by building in retry logic.
4150
"""
42-
def __init__(self):
43-
self.key_id = None
51+
52+
@property
53+
def key_id(self):
54+
"""Optional[str]: The key ID used to identify this private key.
55+
56+
.. note::
57+
This makes a request to the App Identity service.
58+
"""
59+
key_id, _ = app_identity.sign_blob(b'')
60+
return key_id
4461

4562
@staticmethod
4663
def sign(message):
@@ -53,7 +70,8 @@ def sign(message):
5370
bytes: The signature of the message.
5471
"""
5572
message = _helpers.to_bytes(message)
56-
return app_identity.sign_blob(message)
73+
_, signature = app_identity.sign_blob(message)
74+
return signature
5775

5876

5977
def get_project_id():

tests/test_app_engine.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,28 @@ def test_get_project_id_missing_apis():
4141
assert excinfo.match(r'App Engine APIs are not available')
4242

4343

44+
class TestSigner(object):
45+
def test_key_id(self, app_identity_mock):
46+
app_identity_mock.sign_blob.return_value = (
47+
mock.sentinel.key_id, mock.sentinel.signature)
48+
49+
signer = app_engine.Signer()
50+
51+
assert signer.key_id == mock.sentinel.key_id
52+
53+
def test_sign(self, app_identity_mock):
54+
app_identity_mock.sign_blob.return_value = (
55+
mock.sentinel.key_id, mock.sentinel.signature)
56+
57+
signer = app_engine.Signer()
58+
to_sign = b'123'
59+
60+
signature = signer.sign(to_sign)
61+
62+
assert signature == mock.sentinel.signature
63+
app_identity_mock.sign_blob.assert_called_with(to_sign)
64+
65+
4466
class TestCredentials(object):
4567
def test_missing_apis(self):
4668
with pytest.raises(EnvironmentError) as excinfo:
@@ -107,7 +129,8 @@ def test_refresh(self, now_mock, app_identity_mock):
107129
assert not credentials.expired
108130

109131
def test_sign_bytes(self, app_identity_mock):
110-
app_identity_mock.sign_blob.return_value = mock.sentinel.signature
132+
app_identity_mock.sign_blob.return_value = (
133+
mock.sentinel.key_id, mock.sentinel.signature)
111134
credentials = app_engine.Credentials()
112135
to_sign = b'123'
113136

0 commit comments

Comments
 (0)