From b47dc9b140e43d879158dba2d71c382b29c640bd Mon Sep 17 00:00:00 2001 From: Orest Bolohan Date: Thu, 17 Jul 2014 16:06:35 -0700 Subject: [PATCH] Introduce the save_to_well_known_file() method. --- oauth2client/appengine.py | 4 ++++ oauth2client/client.py | 35 +++++++++++++++++++++++++++-- oauth2client/gce.py | 5 +++++ oauth2client/service_account.py | 10 +++++++++ tests/test_appengine.py | 5 +++++ tests/test_gce.py | 6 ++++- tests/test_oauth2client.py | 39 ++++++++++++++++++++++++++++----- 7 files changed, 96 insertions(+), 8 deletions(-) diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py index 7c7feab..a08427d 100644 --- a/oauth2client/appengine.py +++ b/oauth2client/appengine.py @@ -197,6 +197,10 @@ class AppAssertionCredentials(AssertionCredentials): raise AccessTokenRefreshError(str(e)) self.access_token = token + @property + def serialization_data(self): + raise NotImplementedError('Cannot serialize credentials for AppEngine.') + def create_scoped_required(self): return not self.scope diff --git a/oauth2client/client.py b/oauth2client/client.py index c0b79df..9275edb 100644 --- a/oauth2client/client.py +++ b/oauth2client/client.py @@ -985,6 +985,16 @@ class GoogleCredentials(OAuth2Credentials): """ return self + @property + def serialization_data(self): + """Get the fields and their values identifying the current credentials.""" + return { + 'type': 'authorized_user', + 'client_id': self.client_id, + 'client_secret': self.client_secret, + 'refresh_token': self.refresh_token + } + @staticmethod def get_application_default(): """Get the Application Default Credentials for the current environment. @@ -1004,6 +1014,8 @@ class GoogleCredentials(OAuth2Credentials): else: application_default_credential_filename = _get_environment_variable_file() well_known_file = _get_well_known_file() + if not os.path.isfile(well_known_file): + well_known_file = None if application_default_credential_filename: try: @@ -1064,6 +1076,26 @@ class GoogleCredentials(OAuth2Credentials): 'method should point to a file.') +def save_to_well_known_file(credentials, well_known_file=None): + """Save the provided GoogleCredentials to the well known file. + + Args: + credentials: + the credentials to be saved to the well known file; + it should be an instance of GoogleCredentials + well_known_file: + the name of the file where the credentials are to be saved; + this parameter is supposed to be used for testing only + """ + if well_known_file is None: + well_known_file = _get_well_known_file() + + credentials_data = credentials.serialization_data + + with open(well_known_file, 'w') as f: + simplejson.dump(credentials_data, f, sort_keys=True, indent=2) + + def _get_environment_variable_file(): application_default_credential_filename = ( os.environ.get(GOOGLE_APPLICATION_CREDENTIALS, @@ -1103,8 +1135,7 @@ def _get_well_known_file(): default_config_path = os.path.join(default_config_path, WELL_KNOWN_CREDENTIALS_FILE) - if os.path.isfile(default_config_path): - return default_config_path + return default_config_path def _get_application_default_credential_from_file( diff --git a/oauth2client/gce.py b/oauth2client/gce.py index c9ff8f4..41cf89f 100644 --- a/oauth2client/gce.py +++ b/oauth2client/gce.py @@ -93,6 +93,11 @@ class AppAssertionCredentials(AssertionCredentials): ' with no service account or scopes.') raise AccessTokenRefreshError(content) + @property + def serialization_data(self): + raise NotImplementedError( + 'Cannot serialize credentials for GCE service accounts.') + def create_scoped_required(self): return not self.scope diff --git a/oauth2client/service_account.py b/oauth2client/service_account.py index de8c0a2..6bd4bd1 100644 --- a/oauth2client/service_account.py +++ b/oauth2client/service_account.py @@ -92,6 +92,16 @@ class _ServiceAccountCredentials(AssertionCredentials): def service_account_email(self): return self._service_account_email + @property + def serialization_data(self): + return { + 'type': 'service_account', + 'client_id': self._service_account_id, + 'client_email': self._service_account_email, + 'private_key_id': self._private_key_id, + 'private_key': self._private_key_pkcs8_text + } + def create_scoped_required(self): return not self._scopes diff --git a/tests/test_appengine.py b/tests/test_appengine.py index 0cb37b8..579b30f 100644 --- a/tests/test_appengine.py +++ b/tests/test_appengine.py @@ -69,6 +69,7 @@ from oauth2client.client import Credentials from oauth2client.client import FlowExchangeError from oauth2client.client import OAuth2Credentials from oauth2client.client import flow_from_clientsecrets +from oauth2client.client import save_to_well_known_file from webtest import TestApp @@ -248,6 +249,10 @@ class TestAppAssertionCredentials(unittest.TestCase): self.assertEqual('a_token_123', token.access_token) self.assertEqual(None, token.expires_in) + def test_save_to_well_known_file(self): + credentials = AppAssertionCredentials([]) + self.assertRaises(NotImplementedError, save_to_well_known_file, credentials) + class TestFlowModel(db.Model): flow = FlowProperty() diff --git a/tests/test_gce.py b/tests/test_gce.py index 60e876e..f8b328d 100644 --- a/tests/test_gce.py +++ b/tests/test_gce.py @@ -26,6 +26,7 @@ import unittest from oauth2client.client import AccessTokenRefreshError from oauth2client.client import Credentials +from oauth2client.client import save_to_well_known_file from oauth2client.gce import AppAssertionCredentials @@ -131,4 +132,7 @@ class AssertionCredentialsTests(unittest.TestCase): m.UnsetStubs() m.VerifyAll() - + + def test_save_to_well_known_file(self): + credentials = AppAssertionCredentials([]) + self.assertRaises(NotImplementedError, save_to_well_known_file, credentials) diff --git a/tests/test_oauth2client.py b/tests/test_oauth2client.py index d214cdf..a633fba 100644 --- a/tests/test_oauth2client.py +++ b/tests/test_oauth2client.py @@ -67,6 +67,7 @@ from oauth2client.client import _update_query_params from oauth2client.client import credentials_from_clientsecrets_and_code from oauth2client.client import credentials_from_code from oauth2client.client import flow_from_clientsecrets +from oauth2client.client import save_to_well_known_file from oauth2client.clientsecrets import _loadfile from oauth2client.service_account import _ServiceAccountCredentials @@ -260,11 +261,6 @@ class GoogleCredentialsTests(unittest.TestCase): os.environ['APPDATA'] = DATA_DIR self.assertEqual(well_known_file, _get_well_known_file()) - def test_get_well_known_file_on_windows_no_file(self): - os.name = 'nt' - os.environ['APPDATA'] = os.path.join(DATA_DIR, 'nonexistentpath') - self.assertEqual(None, _get_well_known_file()) - def test_get_application_default_credential_from_file_service_account(self): credentials_file = datafile( os.path.join('gcloud', 'application_default_credentials.json')) @@ -272,6 +268,22 @@ class GoogleCredentialsTests(unittest.TestCase): credentials_file) self.validate_service_account_credentials(credentials) + def test_save_to_well_known_file_service_account(self): + credential_file = datafile( + os.path.join('gcloud', 'application_default_credentials.json')) + credentials = _get_application_default_credential_from_file( + credential_file) + temp_credential_file = datafile( + os.path.join('gcloud', 'temp_well_known_file_service_account.json')) + save_to_well_known_file(credentials, temp_credential_file) + with open(temp_credential_file) as f: + d = simplejson.load(f) + self.assertEqual('service_account', d['type']) + self.assertEqual('123', d['client_id']) + self.assertEqual('dummy@google.com', d['client_email']) + self.assertEqual('ABCDEF', d['private_key_id']) + os.remove(temp_credential_file) + def test_get_application_default_credential_from_file_authorized_user(self): credentials_file = datafile( os.path.join('gcloud', @@ -280,6 +292,23 @@ class GoogleCredentialsTests(unittest.TestCase): credentials_file) self.validate_google_credentials(credentials) + def test_save_to_well_known_file_authorized_user(self): + credentials_file = datafile( + os.path.join('gcloud', + 'application_default_credentials_authorized_user.json')) + credentials = _get_application_default_credential_from_file( + credentials_file) + temp_credential_file = datafile( + os.path.join('gcloud', 'temp_well_known_file_authorized_user.json')) + save_to_well_known_file(credentials, temp_credential_file) + with open(temp_credential_file) as f: + d = simplejson.load(f) + self.assertEqual('authorized_user', d['type']) + self.assertEqual('123', d['client_id']) + self.assertEqual('secret', d['client_secret']) + self.assertEqual('alabalaportocala', d['refresh_token']) + os.remove(temp_credential_file) + def test_get_application_default_credential_from_malformed_file_1(self): credentials_file = datafile( os.path.join('gcloud',