Skip to content

Commit

Permalink
Merge pull request fsspec#9 from martindurant/cloud_token
Browse files Browse the repository at this point in the history
Cloud token
  • Loading branch information
martindurant authored May 11, 2017
2 parents 3d70e6c + 1bc19be commit 64e8071
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 11 deletions.
4 changes: 4 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ Two modes of authentication are supported:
- if ``token=None``, you will be given a "device code", which you must
enter into a browser where you are logged in with your Google identity.

- if ``token='cloud'``, we assume we are running within google (compute
or container engine) and fetch the credentials automatically from the
metadata service.

- you may supply a token generated by the
gcloud_ utility; this is either a python dictionary, or the name of a file
containing the JSON returned by logging in with the gcloud CLI tool. On
Expand Down
37 changes: 26 additions & 11 deletions gcsfs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class GCSFileSystem(object):
Two modes of authentication are supported:
- if ``token=None``, you will be given a "device code", which you must
enter into a browser where you are logged in with your Google identity.
- if ``token='cloud'``, we assume we are running within google compute
or google container engine, and query the internal metadata directly for
a token.
- you may supply a token generated by the
[gcloud](https://cloud.google.com/sdk/docs/)
utility; this is either a python dictionary, or the name of a file
Expand Down Expand Up @@ -204,13 +207,16 @@ def connect(self, refresh=False):
"""
token = self.input_token
project, access = self.project, self.access
if token is not None:
if token is not None and str(token) != 'cloud':
if 'type' in token or isinstance(token, str):
token = self._parse_gtoken(token)
self.tokens[(project, access)] = token
if (project, access) in self.tokens:
# cached credentials
data = self.tokens[(project, access)]
elif token == 'cloud':
data = {'timestamp': time.time() - 3600, 'expires_in': 1,
'type': 'cloud'}
else:
# no credentials - try to ask google in the browser
scope = "https://www.googleapis.com/auth/devstorage." + access
Expand Down Expand Up @@ -244,16 +250,25 @@ def connect(self, refresh=False):
data.update(not_secret)
if refresh or time.time() - data['timestamp'] > data['expires_in'] - 100:
# token has expired, or is about to - call refresh
path = "https://www.googleapis.com/oauth2/v4/token"
r = requests.post(
path,
params={'client_id': data['client_id'],
'client_secret': data['client_secret'],
'refresh_token': data['refresh_token'],
'grant_type': "refresh_token"})
validate_response(r, path)
data['timestamp'] = time.time()
data['access_token'] = json.loads(r.content.decode())['access_token']
if data.get('type', None) == 'cloud':
r = requests.get(
'http://metadata.google.internal/computeMetadata/v1/'
'instance/service-accounts/default/token',
headers={'Metadata-Flavor': 'Google'})
data = r.json()
data['timestamp'] = time.time()
data['type'] = 'cloud'
else:
path = "https://www.googleapis.com/oauth2/v4/token"
r = requests.post(
path,
params={'client_id': data['client_id'],
'client_secret': data['client_secret'],
'refresh_token': data['refresh_token'],
'grant_type': "refresh_token"})
validate_response(r, path)
data['timestamp'] = time.time()
data['access_token'] = r.json()['access_token']

self.tokens[(project, access)] = data
self.header = {'Authorization': 'Bearer ' + data['access_token']}
Expand Down

0 comments on commit 64e8071

Please sign in to comment.