Skip to content

Commit c5226c2

Browse files
committed
Merge pull request googleapis#24 from orestica/compacted_2
Introduce the 'application default credentials' concept.
2 parents d02b317 + df59cad commit c5226c2

9 files changed

+177
-149
lines changed

oauth2client/client.py

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@
7373
# The value representing service account credentials.
7474
SERVICE_ACCOUNT = 'service_account'
7575

76-
# The environment variable pointing the file with local Default Credentials.
77-
GOOGLE_CREDENTIALS_DEFAULT = 'GOOGLE_CREDENTIALS_DEFAULT'
76+
# The environment variable pointing the file with local
77+
# Application Default Credentials.
78+
GOOGLE_APPLICATION_CREDENTIALS = 'GOOGLE_APPLICATION_CREDENTIALS'
7879

7980
# The access token along with the seconds in which it expires.
8081
AccessTokenInfo = namedtuple('AccessTokenInfo', ['access_token', 'expires_in'])
@@ -111,8 +112,8 @@ class NonAsciiHeaderError(Error):
111112
"""Header names and values must be ASCII strings."""
112113

113114

114-
class DefaultCredentialsError(Error):
115-
"""Error retrieving the Default Credentials."""
115+
class ApplicationDefaultCredentialsError(Error):
116+
"""Error retrieving the Application Default Credentials."""
116117

117118

118119
def _abstract():
@@ -903,14 +904,15 @@ def _get_environment(urllib2_urlopen=None):
903904

904905

905906
class GoogleCredentials(OAuth2Credentials):
906-
"""Default credentials for use in calling Google APIs.
907+
"""Application Default Credentials for use in calling Google APIs.
907908
908-
The Default Credentials are being constructed as a function of the environment
909-
where the code is being run. More details can be found on this page:
910-
https://developers.google.com/accounts/docs/default-credentials
909+
The Application Default Credentials are being constructed as a function of
910+
the environment where the code is being run.
911+
More details can be found on this page:
912+
https://developers.google.com/accounts/docs/application-default-credentials
911913
912-
Here is an example of how to use the Default Credentials for a service that
913-
requires authentication:
914+
Here is an example of how to use the Application Default Credentials for a
915+
service that requires authentication:
914916
915917
<code>
916918
from googleapiclient.discovery import build
@@ -919,7 +921,8 @@ class GoogleCredentials(OAuth2Credentials):
919921
PROJECT = 'bamboo-machine-422' # replace this with one of your projects
920922
ZONE = 'us-central1-a' # replace this with the zone you care about
921923
922-
service = build('compute', 'v1', credentials=GoogleCredentials.get_default())
924+
credentials = GoogleCredentials.get_application_default()
925+
service = build('compute', 'v1', credentials=credentials)
923926
924927
request = service.instances().list(project=PROJECT, zone=ZONE)
925928
response = request.execute()
@@ -949,7 +952,8 @@ def __init__(self, access_token, client_id, client_secret, refresh_token,
949952
950953
This constructor is not usually called by the user, instead
951954
GoogleCredentials objects are instantiated by
952-
GoogleCredentials.from_stream() or GoogleCredentials.get_default().
955+
GoogleCredentials.from_stream() or
956+
GoogleCredentials.get_application_default().
953957
954958
Args:
955959
access_token: string, access token.
@@ -982,53 +986,53 @@ def create_scoped(self, scopes):
982986
return self
983987

984988
@staticmethod
985-
def get_default():
986-
"""Get the Default Credentials for the current environment.
989+
def get_application_default():
990+
"""Get the Application Default Credentials for the current environment.
987991
988992
Exceptions:
989-
DefaultCredentialsError: raised when the credentials fail to be retrieved.
993+
ApplicationDefaultCredentialsError: raised when the credentials fail
994+
to be retrieved.
990995
"""
991996

992997
_env_name = _get_environment()
993998

994999
if _env_name in ('GAE_PRODUCTION', 'GAE_LOCAL'):
9951000
# if we are running inside Google App Engine
9961001
# there is no need to look for credentials in local files
997-
default_credential_filename = None
1002+
application_default_credential_filename = None
9981003
well_known_file = None
9991004
else:
1000-
default_credential_filename = _get_environment_variable_file()
1005+
application_default_credential_filename = _get_environment_variable_file()
10011006
well_known_file = _get_well_known_file()
10021007

1003-
if default_credential_filename:
1008+
if application_default_credential_filename:
10041009
try:
1005-
return _get_default_credential_from_file(default_credential_filename)
1006-
except (DefaultCredentialsError, ValueError) as error:
1007-
extra_help = (' (pointed to by ' + GOOGLE_CREDENTIALS_DEFAULT +
1010+
return _get_application_default_credential_from_file(
1011+
application_default_credential_filename)
1012+
except (ApplicationDefaultCredentialsError, ValueError) as error:
1013+
extra_help = (' (pointed to by ' + GOOGLE_APPLICATION_CREDENTIALS +
10081014
' environment variable)')
1009-
_raise_exception_for_reading_json(default_credential_filename,
1010-
extra_help, error)
1015+
_raise_exception_for_reading_json(
1016+
application_default_credential_filename, extra_help, error)
10111017
elif well_known_file:
10121018
try:
1013-
return _get_default_credential_from_file(well_known_file)
1014-
except (DefaultCredentialsError, ValueError) as error:
1019+
return _get_application_default_credential_from_file(well_known_file)
1020+
except (ApplicationDefaultCredentialsError, ValueError) as error:
10151021
extra_help = (' (produced automatically when running'
10161022
' "gcloud auth login" command)')
10171023
_raise_exception_for_reading_json(well_known_file, extra_help, error)
10181024
elif _env_name in ('GAE_PRODUCTION', 'GAE_LOCAL'):
1019-
return _get_default_credential_GAE()
1025+
return _get_application_default_credential_GAE()
10201026
elif _env_name == 'GCE_PRODUCTION':
1021-
return _get_default_credential_GCE()
1027+
return _get_application_default_credential_GCE()
10221028
else:
1023-
raise DefaultCredentialsError(
1024-
"The Default Credentials are not available. They are available if "
1025-
"running in Google App Engine or Google Compute Engine. They are "
1026-
"also available if using the Google Cloud SDK and running 'gcloud "
1027-
"auth login'. Otherwise, the environment variable " +
1028-
GOOGLE_CREDENTIALS_DEFAULT + " must be defined pointing to a file "
1029-
"defining the credentials. "
1030-
"See https://developers.google.com/accounts/docs/default-credentials "
1031-
"for details.")
1029+
raise ApplicationDefaultCredentialsError(
1030+
"The Application Default Credentials are not available. They are "
1031+
"available if running in Google Compute Engine. Otherwise, the "
1032+
" environment variable " + GOOGLE_APPLICATION_CREDENTIALS +
1033+
" must be defined pointing to a file defining the credentials. "
1034+
"See https://developers.google.com/accounts/docs/application-default-"
1035+
"credentials for more information.")
10321036

10331037
@staticmethod
10341038
def from_stream(credential_filename):
@@ -1041,41 +1045,46 @@ def from_stream(credential_filename):
10411045
are to be read
10421046
10431047
Exceptions:
1044-
DefaultCredentialsError: raised when the credentials fail to be retrieved.
1048+
ApplicationDefaultCredentialsError: raised when the credentials fail
1049+
to be retrieved.
10451050
"""
10461051

10471052
if credential_filename and os.path.isfile(credential_filename):
10481053
try:
1049-
return _get_default_credential_from_file(credential_filename)
1050-
except (DefaultCredentialsError, ValueError) as error:
1054+
return _get_application_default_credential_from_file(
1055+
credential_filename)
1056+
except (ApplicationDefaultCredentialsError, ValueError) as error:
10511057
extra_help = ' (provided as parameter to the from_stream() method)'
10521058
_raise_exception_for_reading_json(credential_filename,
10531059
extra_help,
10541060
error)
10551061
else:
1056-
raise DefaultCredentialsError('The parameter passed to the from_stream()'
1057-
' method should point to a file.')
1062+
raise ApplicationDefaultCredentialsError(
1063+
'The parameter passed to the from_stream() '
1064+
'method should point to a file.')
10581065

10591066

10601067
def _get_environment_variable_file():
1061-
default_credential_filename = os.environ.get(GOOGLE_CREDENTIALS_DEFAULT,
1062-
None)
1068+
application_default_credential_filename = (
1069+
os.environ.get(GOOGLE_APPLICATION_CREDENTIALS,
1070+
None))
10631071

1064-
if default_credential_filename:
1065-
if os.path.isfile(default_credential_filename):
1066-
return default_credential_filename
1072+
if application_default_credential_filename:
1073+
if os.path.isfile(application_default_credential_filename):
1074+
return application_default_credential_filename
10671075
else:
1068-
raise DefaultCredentialsError(
1069-
'File ' + default_credential_filename + ' (pointed by ' +
1070-
GOOGLE_CREDENTIALS_DEFAULT + ' environment variable) does not exist!')
1076+
raise ApplicationDefaultCredentialsError(
1077+
'File ' + application_default_credential_filename + ' (pointed by ' +
1078+
GOOGLE_APPLICATION_CREDENTIALS +
1079+
' environment variable) does not exist!')
10711080

10721081

10731082
def _get_well_known_file():
10741083
"""Get the well known file produced by command 'gcloud auth login'."""
10751084
# TODO(orestica): Revisit this method once gcloud provides a better way
10761085
# of pinpointing the exact location of the file.
10771086

1078-
WELL_KNOWN_CREDENTIALS_FILE = 'credentials_default.json'
1087+
WELL_KNOWN_CREDENTIALS_FILE = 'application_default_credentials.json'
10791088
CLOUDSDK_CONFIG_DIRECTORY = 'gcloud'
10801089

10811090
if os.name == 'nt':
@@ -1098,14 +1107,17 @@ def _get_well_known_file():
10981107
return default_config_path
10991108

11001109

1101-
def _get_default_credential_from_file(default_credential_filename):
1102-
"""Build the Default Credentials from file."""
1110+
def _get_application_default_credential_from_file(
1111+
application_default_credential_filename):
1112+
"""Build the Application Default Credentials from file."""
11031113

11041114
import service_account
11051115

11061116
# read the credentials from the file
1107-
with open(default_credential_filename) as default_credential:
1108-
client_credentials = service_account.simplejson.load(default_credential)
1117+
with open(application_default_credential_filename) as (
1118+
application_default_credential):
1119+
client_credentials = service_account.simplejson.load(
1120+
application_default_credential)
11091121

11101122
credentials_type = client_credentials.get('type')
11111123
if credentials_type == AUTHORIZED_USER:
@@ -1114,9 +1126,9 @@ def _get_default_credential_from_file(default_credential_filename):
11141126
required_fields = set(['client_id', 'client_email', 'private_key_id',
11151127
'private_key'])
11161128
else:
1117-
raise DefaultCredentialsError("'type' field should be defined "
1118-
"(and have one of the '" + AUTHORIZED_USER +
1119-
"' or '" + SERVICE_ACCOUNT + "' values)")
1129+
raise ApplicationDefaultCredentialsError(
1130+
"'type' field should be defined (and have one of the '" +
1131+
AUTHORIZED_USER + "' or '" + SERVICE_ACCOUNT + "' values)")
11201132

11211133
missing_fields = required_fields.difference(client_credentials.keys())
11221134

@@ -1142,25 +1154,25 @@ def _get_default_credential_from_file(default_credential_filename):
11421154

11431155

11441156
def _raise_exception_for_missing_fields(missing_fields):
1145-
raise DefaultCredentialsError('The following field(s): ' +
1146-
', '.join(missing_fields) + ' must be defined.')
1157+
raise ApplicationDefaultCredentialsError(
1158+
'The following field(s) must be defined: ' + ', '.join(missing_fields))
11471159

11481160

11491161
def _raise_exception_for_reading_json(credential_file,
11501162
extra_help,
11511163
error):
1152-
raise DefaultCredentialsError('An error was encountered while reading '
1153-
'json file: '+ credential_file + extra_help +
1154-
': ' + str(error))
1164+
raise ApplicationDefaultCredentialsError(
1165+
'An error was encountered while reading json file: '+
1166+
credential_file + extra_help + ': ' + str(error))
11551167

11561168

1157-
def _get_default_credential_GAE():
1169+
def _get_application_default_credential_GAE():
11581170
from oauth2client.appengine import AppAssertionCredentials
11591171

11601172
return AppAssertionCredentials([])
11611173

11621174

1163-
def _get_default_credential_GCE():
1175+
def _get_application_default_credential_GCE():
11641176
from oauth2client.gce import AppAssertionCredentials
11651177

11661178
return AppAssertionCredentials([])

samples/call_compute_service.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
# To be used to test GoogleCredential.GetDefaultCredential()
1+
# To be used to test GoogleCredentials.get_application_default()
22
# from local machine and GCE.
33

44
from googleapiclient.discovery import build
55
from oauth2client.client import GoogleCredentials
66

7-
PROJECT = "bamboo-machine-422" # Provide your own GCE project here
8-
ZONE = "us-central1-a" # Put here a zone which has some VMs
7+
PROJECT = 'bamboo-machine-422' # Provide your own GCE project here
8+
ZONE = 'us-central1-a' # Put here a zone which has some VMs
99

10-
service = build("compute", "v1", credentials=GoogleCredentials.get_default())
10+
credentials = GoogleCredentials.get_application_default()
11+
service = build('compute', 'v1', credentials=credentials)
1112

1213
request = service.instances().list(project=PROJECT, zone=ZONE)
1314
response = request.execute()

samples/googleappengine/call_compute_service_from_gae.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
# To be used to test GoogleCredential.GetDefaultCredential()
1+
# To be used to test GoogleCredentials.get_application_default()
22
# from devel GAE (ie, dev_appserver.py).
33

44
import webapp2
55
from googleapiclient.discovery import build
66
from oauth2client.client import GoogleCredentials
77

8-
PROJECT = "bamboo-machine-422" # Provide your own GCE project here
9-
ZONE = "us-central1-a" # Put here a zone which has some VMs
8+
PROJECT = 'bamboo-machine-422' # Provide your own GCE project here
9+
ZONE = 'us-central1-a' # Put here a zone which has some VMs
1010

1111
def get_instances():
12-
service = build("compute", "v1", credentials=GoogleCredentials.get_default())
12+
credentials = GoogleCredentials.get_application_default()
13+
service = build('compute', 'v1', credentials=credentials)
1314
request = service.instances().list(project=PROJECT, zone=ZONE)
1415
return request.execute()
1516

0 commit comments

Comments
 (0)