diff --git a/google/auth/app_engine.py b/google/auth/app_engine.py index d20ddf646..566475e9f 100644 --- a/google/auth/app_engine.py +++ b/google/auth/app_engine.py @@ -86,6 +86,13 @@ def refresh(self, request): self.token, self.expiry = token, expiry + @property + def service_account_email(self): + """The service account email.""" + if self._service_account_id is None: + self._service_account_id = app_identity.get_service_account_name() + return self._service_account_id + @property def requires_scopes(self): """Checks if the credentials requires scopes. diff --git a/google/auth/compute_engine/credentials.py b/google/auth/compute_engine/credentials.py index cd215c570..572995690 100644 --- a/google/auth/compute_engine/credentials.py +++ b/google/auth/compute_engine/credentials.py @@ -92,6 +92,15 @@ def refresh(self, request): except exceptions.TransportError as exc: raise exceptions.RefreshError(exc) + @property + def service_account_email(self): + """The service account email. + + .. note: This is not guaranteed to be set until :meth`refresh` has been + called. + """ + return self._service_account_email + @property def requires_scopes(self): """False: Compute Engine credentials can not be scoped.""" diff --git a/google/oauth2/service_account.py b/google/oauth2/service_account.py index 615930102..24c852b2a 100644 --- a/google/oauth2/service_account.py +++ b/google/oauth2/service_account.py @@ -231,6 +231,11 @@ def to_jwt_credentials(self): issuer=self._service_account_email, subject=self._service_account_email) + @property + def service_account_email(self): + """The service account email.""" + return self._service_account_email + @property def requires_scopes(self): """Checks if the credentials requires scopes. diff --git a/system_tests/test_compute_engine.py b/system_tests/test_compute_engine.py index 2d6f42cc8..e828cff17 100644 --- a/system_tests/test_compute_engine.py +++ b/system_tests/test_compute_engine.py @@ -32,7 +32,7 @@ def test_refresh(http_request, token_info): credentials.refresh(http_request) assert credentials.token is not None - assert credentials._service_account_email is not None + assert credentials.service_account_email is not None info = token_info(credentials.token) info_scopes = _helpers.string_to_scopes(info['scope']) diff --git a/system_tests/test_service_account.py b/system_tests/test_service_account.py index 6b41ca225..aad1497e9 100644 --- a/system_tests/test_service_account.py +++ b/system_tests/test_service_account.py @@ -39,7 +39,7 @@ def test_refresh_success(http_request, credentials, token_info): info = token_info(credentials.token) - assert info['email'] == credentials._service_account_email + assert info['email'] == credentials.service_account_email info_scopes = _helpers.string_to_scopes(info['scope']) assert set(info_scopes) == set([ 'https://www.googleapis.com/auth/userinfo.email', diff --git a/tests/compute_engine/test_credentials.py b/tests/compute_engine/test_credentials.py index daa61fecf..87f747266 100644 --- a/tests/compute_engine/test_credentials.py +++ b/tests/compute_engine/test_credentials.py @@ -34,6 +34,8 @@ def test_default_state(self): assert not self.credentials.expired # Scopes aren't needed assert not self.credentials.requires_scopes + # Service account email hasn't been populated + assert self.credentials.service_account_email == 'default' @mock.patch( 'google.auth._helpers.utcnow', return_value=datetime.datetime.min) @@ -58,7 +60,7 @@ def test_refresh_success(self, get_mock, now_mock): datetime.datetime.min + datetime.timedelta(seconds=500)) # Check the credential info - assert (self.credentials._service_account_email == + assert (self.credentials.service_account_email == 'service-account@example.com') assert self.credentials._scopes == ['one', 'two'] diff --git a/tests/oauth2/test_service_account.py b/tests/oauth2/test_service_account.py index 01234b5ae..f07f79d81 100644 --- a/tests/oauth2/test_service_account.py +++ b/tests/oauth2/test_service_account.py @@ -63,7 +63,7 @@ def test_from_service_account_info(self): assert (credentials._signer.key_id == SERVICE_ACCOUNT_INFO['private_key_id']) - assert (credentials._service_account_email == + assert (credentials.service_account_email == SERVICE_ACCOUNT_INFO['client_email']) assert credentials._token_uri == SERVICE_ACCOUNT_INFO['token_uri'] @@ -77,8 +77,8 @@ def test_from_service_account_info_args(self): info, scopes=scopes, subject=subject, additional_claims=additional_claims) + assert credentials.service_account_email == info['client_email'] assert credentials._signer.key_id == info['private_key_id'] - assert credentials._service_account_email == info['client_email'] assert credentials._token_uri == info['token_uri'] assert credentials._scopes == scopes assert credentials._subject == subject @@ -90,8 +90,8 @@ def test_from_service_account_file(self): credentials = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_JSON_FILE) + assert credentials.service_account_email == info['client_email'] assert credentials._signer.key_id == info['private_key_id'] - assert credentials._service_account_email == info['client_email'] assert credentials._token_uri == info['token_uri'] def test_from_service_account_file_args(self): @@ -104,8 +104,8 @@ def test_from_service_account_file_args(self): SERVICE_ACCOUNT_JSON_FILE, subject=subject, scopes=scopes, additional_claims=additional_claims) + assert credentials.service_account_email == info['client_email'] assert credentials._signer.key_id == info['private_key_id'] - assert credentials._service_account_email == info['client_email'] assert credentials._token_uri == info['token_uri'] assert credentials._scopes == scopes assert credentials._subject == subject diff --git a/tests/test__oauth2client.py b/tests/test__oauth2client.py index 9478406fa..1d7a4a805 100644 --- a/tests/test__oauth2client.py +++ b/tests/test__oauth2client.py @@ -54,7 +54,7 @@ def test__convert_service_account_credentials(): new_credentials = _oauth2client._convert_service_account_credentials( old_credentials) - assert (new_credentials._service_account_email == + assert (new_credentials.service_account_email == old_credentials.service_account_email) assert new_credentials._signer.key_id == old_credentials._private_key_id assert new_credentials._token_uri == old_credentials.token_uri @@ -68,7 +68,7 @@ def test__convert_service_account_credentials_with_jwt(): new_credentials = _oauth2client._convert_service_account_credentials( old_credentials) - assert (new_credentials._service_account_email == + assert (new_credentials.service_account_email == old_credentials.service_account_email) assert new_credentials._signer.key_id == old_credentials._private_key_id assert new_credentials._token_uri == old_credentials.token_uri @@ -81,7 +81,7 @@ def test__convert_gce_app_assertion_credentials(): new_credentials = _oauth2client._convert_gce_app_assertion_credentials( old_credentials) - assert (new_credentials._service_account_email == + assert (new_credentials.service_account_email == old_credentials.service_account_email) diff --git a/tests/test_app_engine.py b/tests/test_app_engine.py index e1189ed49..94f528d1d 100644 --- a/tests/test_app_engine.py +++ b/tests/test_app_engine.py @@ -70,6 +70,23 @@ def test_with_scopes(self, app_identity_mock): assert scoped_credentials.has_scopes(['email']) assert not scoped_credentials.requires_scopes + def test_service_account_email_implicit(self, app_identity_mock): + app_identity_mock.get_service_account_name.return_value = ( + mock.sentinel.service_account_email) + credentials = app_engine.Credentials() + + assert (credentials.service_account_email == + mock.sentinel.service_account_email) + assert app_identity_mock.get_service_account_name.called + + def test_service_account_email_explicit(self, app_identity_mock): + credentials = app_engine.Credentials( + service_account_id=mock.sentinel.service_account_email) + + assert (credentials.service_account_email == + mock.sentinel.service_account_email) + assert not app_identity_mock.get_service_account_name.called + @mock.patch( 'google.auth._helpers.utcnow', return_value=datetime.datetime.min)