Files
deb-python-oauth2client/oauth2client/contrib/_metadata.py
Craig Citro feec15f070 Allow customizing the GCE metadata service address via an env var. (#704)
The goal here is to make it possible for a user of a binary that depends on
this library (eg the google cloud SDK) to be able to customize where it looks
for the GCE metadata service. (An adventurous user can already customize the
GCE metadata service location via the existing global vars in this library.)

The only bit of awkwardness here is really the test: since this is a top-level
statement, reloading is the only way to ensure it works.
2017-03-27 09:47:44 -07:00

119 lines
4.1 KiB
Python

# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Provides helper methods for talking to the Compute Engine metadata server.
See https://cloud.google.com/compute/docs/metadata
"""
import datetime
import json
import os
from six.moves import http_client
from six.moves.urllib import parse as urlparse
from oauth2client import _helpers
from oauth2client import client
from oauth2client import transport
METADATA_ROOT = 'http://{}/computeMetadata/v1/'.format(
os.getenv('GCE_METADATA_ROOT', 'metadata.google.internal'))
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
def get(http, path, root=METADATA_ROOT, recursive=None):
"""Fetch a resource from the metadata server.
Args:
http: an object to be used to make HTTP requests.
path: A string indicating the resource to retrieve. For example,
'instance/service-accounts/default'
root: A string indicating the full path to the metadata server root.
recursive: A boolean indicating whether to do a recursive query of
metadata. See
https://cloud.google.com/compute/docs/metadata#aggcontents
Returns:
A dictionary if the metadata server returns JSON, otherwise a string.
Raises:
http_client.HTTPException if an error corrured while
retrieving metadata.
"""
url = urlparse.urljoin(root, path)
url = _helpers._add_query_parameter(url, 'recursive', recursive)
response, content = transport.request(
http, url, headers=METADATA_HEADERS)
if response.status == http_client.OK:
decoded = _helpers._from_bytes(content)
if response['content-type'] == 'application/json':
return json.loads(decoded)
else:
return decoded
else:
raise http_client.HTTPException(
'Failed to retrieve {0} from the Google Compute Engine'
'metadata service. Response:\n{1}'.format(url, response))
def get_service_account_info(http, service_account='default'):
"""Get information about a service account from the metadata server.
Args:
http: an object to be used to make HTTP requests.
service_account: An email specifying the service account for which to
look up information. Default will be information for the "default"
service account of the current compute engine instance.
Returns:
A dictionary with information about the specified service account,
for example:
{
'email': '...',
'scopes': ['scope', ...],
'aliases': ['default', '...']
}
"""
return get(
http,
'instance/service-accounts/{0}/'.format(service_account),
recursive=True)
def get_token(http, service_account='default'):
"""Fetch an oauth token for the
Args:
http: an object to be used to make HTTP requests.
service_account: An email specifying the service account this token
should represent. Default will be a token for the "default" service
account of the current compute engine instance.
Returns:
A tuple of (access token, token expiration), where access token is the
access token as a string and token expiration is a datetime object
that indicates when the access token will expire.
"""
token_json = get(
http,
'instance/service-accounts/{0}/token'.format(service_account))
token_expiry = client._UTCNOW() + datetime.timedelta(
seconds=token_json['expires_in'])
return token_json['access_token'], token_expiry